SMM Studio
Multi-brand social control room · live at portal.karismma.com · doc updated 2026-06-17
Snapshot
Overall roadmap progress — all versions combined
58%42 of 72 items shipped. Pre-launch: prototype done, infrastructure underway — building toward the v1.0 MVP.
v0.9 — First real post (walking skeleton)
0%0 of 4 — one idea → one AI image → stored in R2 → published to Instagram → live. One creator, all the way through, before we widen..
v1.0 — Solo-creator MVP
81%42 of 52 — builds on the v0.9 skeleton: real video, Reels, reliable auto-publish, and a queue that stays full.
v1.1 — First creators
0%0 of 6 — make the live loop trustworthy for the first invited creators and add TikTok.
v1.2 — Grow
0%0 of 4 — the 3rd network and depth once the basics work with real creators.
v2.0 — Agency phase + big bets
0%0 of 6 — turn the solo tool into an agency platform; big bets scheduled when a deal pulls them forward.
Daily progress
What shipped each day, newest first. Tag a finished task with a completion date in roadmap-data.ts and it groups here automatically.
v0.9First real post (walking skeleton)— prove the whole spine end-to-end, thinnest slice
★ The thinnest end-to-end slice (image → Instagram feed)
- HIGHMedia storage foundation — Cloudflare R2 (S3 API) + media_asset modelPREREQUISITE for any media post. A private R2 bucket via the S3 API behind a swappable MediaStorage adapter; a media_asset table (project-scoped: kind, source, status, storage_path, mime, dimensions); upload + short-lived signed URLs at publish & preview. Bytes in R2, a Postgres row points to each file. R2 chosen for zero egress.
- HIGHAI image generation (OpenAI) → store in R2 → attach to a postThe fastest visible 'wow'. Wire OpenAI gpt-image-1 behind the credential vault: prompt → generate → download (provider URLs expire) → store in R2 as a media_asset → attach to a post variant; preview via signed URL.
- HIGHInstagram feed image publish (single image, tester-mode)The thin publish path that proves the spine WITHOUT waiting on video: IG container with a public R2 signed image_url → publish → write status + permalink back. Runs in Meta tester-mode (no App Review); the creator needs only a Business/Creator account (no Facebook Page). NOT Reels — a single feed image is the lowest-risk first publish; Reels (video) comes in v1.0.
- HIGHOne creator through it end-to-end + instrument first-valueGet one real creator (the owner) from idea → generated image → published-to-IG → live, against the live stack. Instrument time-to-first-published-post — the proof the loop works before we widen. Surfaces every real gap (token refresh, signed-URL fetch by Meta, error paths).
v1.0Solo-creator MVP— generate content → publish reliably → stay consistent
Foundation · Stage 0 — Clickable prototype
- DONE · 2026-06-08Every feature built & clickable on dummy dataAll 13 screens (dashboard, calendar, composer, strategist, approvals, inbox, listening, analytics, reports, projects, connections, settings) running, no backend.
- DONE · 2026-06-08DataSource seam — the one swap point for going realEvery screen reads through the DataSource interface in src/lib/data/datasource.ts; never the mock directly. Stage 1 swaps in SupabaseDataSource with zero screen rewrites.
- DONE · 2026-06-08GitHub → Vercel, behind a temporary login gateCookie + middleware demo gate; auto-deploys on push.
- DONE · 2026-06-09Public, shareable /roadmap pageThis page. Now on the IP roadmap pattern — % derived from the checklist.
Foundation · Stage 1 — Infrastructure & multi-project
- DONE · 2026-06-09Rename Brand → Project across the appEntity, route (/projects), switcher, nav & storage all renamed; design tokens (bg-brand etc.) left intact. BrandKit kept — a Project has a brand kit.
- DONE · 2026-06-09Project switcher + create / rename / deleteCRUD added to the DataSource contract (so SupabaseDataSource mirrors it); topbar + Projects page wired.
- DONE · 2026-06-09Multi-tenant schema, RLS & seed (written)supabase/migrations/0001_init.sql — project_id on every tenant table, project.owner_id; RLS policies written but enabled at the go-public gate (supabase/policies); seed for the demo user + 3 projects.
- DONE · 2026-06-09Async DataSource seam + SupabaseDataSourceSeam went async (useQuery hook); SupabaseDataSource backs real projects behind it, mock fallback when no env.
- DONE · 2026-06-09Live Supabase connected — projects are realSchema + seed applied to the Supabase project; app reads/creates/renames/deletes projects against Postgres (verified end-to-end via the UI). RLS deferred; anon-key access granted on `project`.
- DONE · 2026-06-09Project content live in SupabaseAccounts, posts (+variants) and approvals are real in Postgres — Dashboard, Calendar, Composer, Connections, Approvals & Analytics run on live data; KPIs/top-posts/metrics derived from real follower counts (synthetic until real metrics land).
- DONE · 2026-06-10Light / dark themeApp-shell theming via design tokens: System / Light / Dark in Settings → Appearance + a quick toggle in the topbar. No-flash inline script sets the theme before first paint; choice persists per-browser; charts adapt too. Dark stays the default.
- DONE · 2026-07-16Database locked down — no browser access, RLS on every tableThe browser no longer holds database credentials. Reads and writes moved off the public key and behind session-checked server functions that run on the server with the secret key (src/lib/data/actions.ts → server-source.ts); the job worker moved too. The Supabase client is now entirely absent from the browser bundle (verified), so migration 0011 could revoke every public grant and enable Row-Level Security on all 14 tables — closing the advisor's rls_disabled_in_public finding for real. Per-user policies still land with Clerk at the go-public gate.
Foundation · Stage 2 — Connection & job framework
- DONE · 2026-06-09Integration adapter framework + mock adaptersrc/lib/integrations: Connection/Publisher/Metrics adapter interfaces + a registry every platform resolves through + a mock adapter. Adding a network later = one adapter.
- DONE · 2026-06-10Server-side OAuth + encrypted token vaultOAuth handshake runs server-side; tokens encrypted (AES-256-GCM) into the vault via the service-role key — never the browser/anon key. Migration 0004 applied; verified end-to-end (ciphertext at rest, decrypts to original, anon read denied).
- DONE · 2026-06-09Background job/queue layerGeneric durable queue (job table) + worker that claims due jobs, retries with backoff and dead-letters. Live on Vercel Cron → /api/jobs/run (CRON_SECRET-guarded); verified in production with the mock adapter. This is what the publish + generate-video jobs ride.
Foundation · Stage 3 — First real connect (Facebook + Instagram)
- DONE · 2026-06-12One-click OAuth connect for Facebook + InstagramLive: Facebook and Instagram are independent real connections. Facebook Login connects a Page (in-app picker when an account has several); Instagram Login connects an IG Business/Creator account directly (standalone, no Page — the key enabler for Instagram Reels publish). Tokens encrypted in the vault; CSRF-protected; verified end-to-end against the live DB. (Surfaced & fixed a service_role DML grant gap — migration 0006.)
★ Create · AI content — building on the v0.9 skeleton
- IN PROGRESSAI copy (Claude) — LIVE; video generation nextClaude (Anthropic) copy is LIVE: encrypted AI-credential vault + Settings → AI Providers key entry (migration 0005), Composer & AI Strategist generate real per-platform caption variants. Image generation + R2 storage land in v0.9 (the skeleton); video generation is the v1.0 Create focus.
- HIGHAI video generation (generate_video job) → store in R2 — the differentiatorThe moat — honest generative video for faceless content (the on-camera-anxiety pain). A generate_video job calls the provider (Sora / Veo / Runway / Kling, behind a provider-agnostic adapter), polls until done (self-re-enqueues on the cron), downloads with resumable upload → stores the source MP4 in R2 (reusing the v0.9 MediaStorage). Scoped truthfully: short clips, B-roll/hooks/image-to-video — not a final-cut replacement. v1 publishes the source AS-IS (per-platform transcoding is parked — see backlog).
★ Publish · get it live reliably — Instagram Reels first
- HIGHInstagram Reels publish (video — extends the v0.9 image path)Extends the v0.9 IG feed-image publish to video Reels: media_type=REELS with a public R2 signed video_url → poll status until FINISHED → media_publish → write status + permalink back. Same Meta TESTER-MODE pilot (no App Review); creator needs a Business/Creator account (no Facebook Page — Instagram Login). 100 posts/24h; 60-day token-refresh job.
- HIGHFacebook Page auto-publish — text/link, photo & videoScheduler enqueues due scheduled posts → real Facebook Page publish (text/link via /feed; photo/video + FB Reels via the media flow using R2 signed URLs) → status + live URL written back. Rides the existing job queue (retry/backoff/dead-letter). Cheap alongside IG (shared Meta infra); needs a Page.
- HIGHPublish reliability — failure visibility + retry / repairPromoted from post-launch: silent publish failures + forced reconnections are the #1 trust-killer across every competitor. Show WHY a post failed (token expired, format rejected pre-transcoding, platform error) with a one-click retry/repair; surface expiring tokens before they break the connection.
★ Sustain · stay consistent — the retention engine
- HIGHOne idea → copy + image/video variants → “refill my queue”The activation AND retention engine — it hits three journey stages (Plan + Create + Sustain). One idea → Claude copy + a generated image/video per network → one click to fill the calendar. The solo creator's biggest pains are the blank page and keeping the queue full; this is the single highest-leverage flow.
- MEDConsistency engine — reminders, streaks, queue-healthRetention is the #1 reason solo creators abandon (burnout, habit collapse; most quit within year one). Nudge before the queue runs dry, show a streak, flag gaps in the calendar. Consistency over weeks — not raw frequency — drives the engagement payoff.
Measure · what worked — simple, not a report suite
- IN PROGRESSLive follower/reach metricsHalf shipped: an hourly cron (+ a Refresh button) pulls real follower counts (and best-effort 24h reach) for connected FB/IG accounts and writes the live numbers the UI shows. Remaining: verify end-to-end with fresh tokens.
- DONE · 2026-06-15Simple per-post “what worked” — import IG posts + per-post insightsImport a connected Instagram account's recent posts + per-post analytics (reach/likes/comments/shares/saves) into the DB via the stored token (migration 0007; read-only, idempotent upsert), then surface them on Analytics: a 'what worked' leaderboard ranked by engagement, engagement-by-format, best-day-to-post, and headline KPIs — real numbers replace the synthetic demo. (Full 24h/7d/30d time-series, UTM attribution and white-label client reports stay agency-grade — deferred to v2.0.)
Control room, AI & reliability — 2026-06-16 build (v0.9 → v0.15)
- DONE · 2026-06-16Composer — full create studioWrite-once master copy auto-adapts per platform with realistic Meta-Business-Suite-style previews (Platform → Device tabs, per-format aspect, char-limit + banned-word checks, each network rendered in the format it actually supports — YouTube/TikTok as video). AI copy (Claude) writes per-platform variants; AI image (OpenAI gpt-image-1, auto-fallback to DALL·E 3) generates + stores a public image; “Draft with AI” writes whole post concepts (copy + hashtags + image prompt + format) to pick from. Schedule lands on the calendar; Publish now pushes live to connected Facebook/Instagram. (Media still on Supabase Storage — Cloudflare R2 migration pending.)
- DONE · 2026-06-16AI Strategist, Client Reports & Listening — liveAI Strategist generates strategy + predictions + content ideas grounded in the project's real imported-post performance; Client Reports writes a white-label monthly summary (copy/download); Listening is a compact comments/mentions table with keyword tracking (DMs stay in the Social Inbox). Every AI/server action returns its error as data, so a missing or invalid key shows the real reason instead of an opaque crash.
- DONE · 2026-06-16CRM-style control room — shell, search & tablesTopbar + sidebar rebuilt CRM-style: collapsible sidebar, light/dark toggle, notifications, profile menu, and a ⌘K command palette. Every directory table (SMM Accounts/Records, YouTube Channels/Records, Listening) uses the shared DataTable — sort, drag-resize, column manager, per-column filter, page-size + numbered pagination. Project logos fetched from the brand's site replace the emoji in the switcher, dashboard and reports.
- DONE · 2026-06-16Projects brand kit — fetch logo + AI brand inferenceA project carries a website URL, logo, design style, audience, palette, voice, hashtags + banned words. “Fetch logo & brand” pulls the site logo and (with an Anthropic key) infers voice/style/audience/palette; hashtags can be AI-suggested and blended from the project's own posts. This grounds AI copy + image generation per project.
- DONE · 2026-06-16Records thumbnails bulletproof + connection-aware recordsPost thumbnails are re-hosted into our own public Storage at import time so they survive CDN expiry/hotlink-block; YouTube rows derive a stable thumbnail from the video id and always render. Records now only show posts for currently-connected accounts — disconnecting an account hides its imported posts. The calendar is month-navigable and opens on the month of the next scheduled post.
- DONE · 2026-06-16Records thumbnails — fetch + render across platformsSMM Records + YouTube Records pull a real thumbnail (image / video poster / first carousel frame) per post, with a carousel-count badge and a format-icon fallback; the detail drawer shows the full preview. Adapters for Instagram, Facebook, Threads + YouTube return the thumbnail at import.
- DONE · 2026-06-16Image proxy for post thumbnails (SSRF-allowlisted)Instagram/Facebook media CDNs block cross-origin hotlinking, so thumbnails 403'd in the browser. A server-side /api/img proxy (allowlisted to social CDNs only) fetches and re-streams them from our own origin.
- DONE · 2026-06-16Social inbox webhook hardeningFixed the empty-inbox chain end-to-end: handle Meta's {sample} dashboard-test payload + the IG changes[messages] DM shape, normalise second/millisecond timestamps, and grant the conversation table to the anon role (the actual cause of the blank inbox).
- DONE · 2026-06-16Inbox + app shell — fit-to-screen, internal scrollLocked the app shell (fixed sidebar + topbar; only the main pane scrolls) so the Social Inbox fills the viewport and the thread scrolls internally instead of stretching the whole page — also fixes the sticky-menu / page-drag regressions across every screen.
- DONE · 2026-06-16Connection-aware dashboard + quick toolsDashboard rebuilt to react to real connections: connected-account followers, accounts needing attention, scheduled-today, a live trend area, top posts, and a quick-tools row (Compose, Inbox, Strategist, Report, Connections).
- DONE · 2026-06-16AI image generation + DALL·E 3 auto-fallbackComposer generates images via OpenAI (gpt-image-1) behind the vaulted key, stores them in a public bucket and previews them in the per-format canvas. Auto-falls back to DALL·E 3 when gpt-image-1 hits OpenAI's org-verification wall, so it just works.
- DONE · 2026-06-16Draft with AI — full post conceptsA “Draft with AI” panel writes 1–10 complete post concepts (master copy + hashtags + image prompt + post type) from an optional brief; “Use this” fills the composer fields.
- DONE · 2026-06-16Errors surfaced as data across every AI actionImage, caption-variants, strategist, reports, draft-a-post and fetch-brand all return their real failure reason instead of the opaque “Server Components render” crash — so a missing/invalid key or provider error is actually readable.
- DONE · 2026-06-16Project logos everywhereThe brand's fetched site logo (with an emoji fallback) replaces the placeholder in the topbar project switcher + dropdown, the dashboard header and the client report header.
- DONE · 2026-06-16Polish batch — profile menu, pagination, strategist, fetch-brandProfile chip → dropdown (Settings + Log out); analytics post-leaderboard paginated; AI Strategist error surfaced + token limit raised; projects “Fetch logo & brand” renamed + hardened (returns the real error, never wipes an existing logo).
Directory consolidation, Library & control-room polish — 2026-06-17 (v0.16)
- DONE · 2026-06-17One Accounts page + one Records page (YouTube merged in)YouTube Channels folded into Accounts and YouTube Records into Records, each a single shared DataTable with the union of every platform's columns (followers/subscribers, posts/videos/shorts, avg likes & comments, monetized, cadence, geo, language, content pillars, managed-by, setup, last post…), so nothing from the YouTube views is lost. Dropped the “SMM” prefix — they're just Accounts and Records now. Accounts shows each profile's real platform logo and pulls the brand colour palette from the connected site.
- DONE · 2026-06-17Records — click-to-expand media lightbox + bulletproof thumbnailsClicking a record opens a lightbox that shows the post larger — a swipeable carousel (‹ ›, arrow keys, dots + counter) for multi-image posts, a play-overlay → watch link for video — with the metrics grid + caption beside it. Fixed the “some pictures don't load” cases by de-duplicating posts that re-import on account reconnect (keep the copy with the best re-hosted thumbnail + highest engagement) so every record renders an image.
- DONE · 2026-06-17Analytics — Generate Report button (Client Reports page retired)Removed the standalone Client Reports page; reporting now lives where the data is — a “Generate Report” dropdown in Analytics offers report types (monthly performance summary, content & format audit, growth & reach, engagement deep-dive, executive one-pager) and writes a white-label summary you can copy/download.
- DONE · 2026-06-17Projects — list view + palette scraped from the siteProjects is now a sortable table (logo + name + active toggle, voice, website, design style, audience, connected-account logos, brand-palette swatches, hashtag/banned counts, row actions) with inline rename. “Fetch brand” now also scrapes the brand's dominant hex colours from its website (frequency-ranked, greys/near-white dropped, theme-colour pinned) to seed the palette.
- DONE · 2026-06-17Flat, reordered navigationDissolved the sidebar section-group headers — the menu is small enough that they added noise — into one flat list, reordered around the daily workflow: Dashboard · Records · Accounts · Analytics · Social Inbox · Composer · AI Strategist · Approvals · Listening · Calendar · Library · Projects · Settings. Connections moved into Settings as the first tab. (The ⌘K command palette tracks the same flat list.)
- DONE · 2026-06-17Dashboard — CRM-style date filter, quick-tools row removedReplaced the 7d/28d/90d toggle (and the redundant “New post” button) with the CRM-style date-range chip bar — Today, Yesterday, This/Last week, Last 7/30/90 days, Last 12 months, This/Last month, This quarter, Year to date, All time + a Custom range picker — driving the reach-trend window. Removed the quick-tools shortcut row (the flat nav covers it).
- DONE · 2026-06-17Dashboard rebuilt on 100% real data — no more synthetic numbersRipped out the three synthetic feeds the board was using — getKpis (hardcoded Reach/Engagement/Link-click deltas), getMetrics (a fake reach curve derived from follower count) and getTopPosts (numbers fabricated by row index, which is why an X/Twitter post showed up on an IG-only account). Every box now computes from real connected-account data + imported-post analytics: 6 KPI tiles (Followers, Reach, Engagement rate, Interactions, Posts published, Scheduled) with REAL period-over-period deltas (current window vs the equal-length prior window of the same posts); a real Reach/Engagement trend bucketed by publish date; real Engagement-by-format + Best-day-to-post; a real Top-posts leaderboard ranked by actual engagement (correct platform + thumbnail + live link); Audience-by-platform follower split; and a workflow row — Scheduled, Needs-approval and Inbox (open conversations + sentiment) — all live. Honest empty states show where data hasn't accrued yet instead of inventing it. The date filter now actually windows the underlying real posts.
- DONE · 2026-06-17Five new pages — Campaigns, Competitors, Content Ideas, Automations, TeamBuilt out the product around the post: (1) Campaigns — group posts into themed pushes (launch/sale/seasonal) with objective, colour, dates + a real rollup (a campaign's posts are the real posts tagged with its name, with a live status/engagement mini-report). (2) Competitors — track rival handles (followers, posts/week, notes) and benchmark them against YOUR real numbers (your followers + cadence from connected accounts), e.g. “they post 5×/wk, you post 2×”. (3) Content Ideas — an AI-generated + saved hooks bank (Claude via the vaulted key) you can star and send straight into the Composer (one-click hand-off prefills the master copy). (4) Automations — a rules builder (auto-draft weekly, alert on a viral comment, email a weekly report) with one-click templates; saved now, executes once the scheduler is wired (honest banner). (5) Team & Clients — people + role→permission management (Owner/Manager/Creator/Client/Viewer) for when more than one brand is involved. All five match the dashboard/Library idiom (KPI tiles, real-data integration, honest empty states, no fabricated metrics) and slot into the flat nav.
- DONE · 2026-06-17Library — a per-project asset dumpNew Library page (after Calendar) where the client drops videos, pictures, documents, links or text notes to reuse later. Drag-and-drop anywhere or use Upload / Link / Note; files upload to our permanent public bucket (≤50 MB) and render as a filterable, searchable card grid (Images / Videos / Docs / Links / Notes) with previews, a click-to-expand lightbox for media, copy-URL and remove. The catalog is kept per project; a shared DB-backed library + pull-into-Composer is the next slice.
Deferred to the go-public gate
- DONE · 2026-06-16Social inbox (comments & DMs) — live + history backfillUnified inbox over the connected Meta accounts: live DMs/comments arrive via the Meta webhook (/api/webhooks/meta, idempotent upsert keyed on account+external_id) and a “Sync DM history” button backfills past Messenger/Instagram threads through the Graph conversations API. Per-platform triage tags, assignment, full-thread view, and real brand logos. Sending replies + AI-draft are the remaining v2 slice.
- DEEPMeta App Review + Business Verification (leave tester-mode)Needed to publish for creators NOT added as app testers — i.e. to go beyond the invite-only pilot. instagram_business_content_publish needs Advanced Access (App Review screencast + business verification, ~2–4 wk, often rejected first try). Deferred to the same milestone as self-serve sign-up.
- DEEPSelf-serve sign-up (Clerk) + per-user RLS policiesInvite-only manual onboarding for now (the dummy login stays). RLS is already ON for every table and the public keys have no access at all (2026-07-16) — what's left is the per-user half: replace the login with Clerk (real users) and add the owner_id / project_id policies already modeled in supabase/policies, so rows are scoped per account rather than per server function.
v1.1First creators— harden the pilot & add the 2nd network
- HIGHError monitoring + alertingSentry (or similar) on the app and the job/publish layer; know about failures before the creator does.
- HIGHOnboard the first real solo creators end-to-endConnect → generate → schedule → publish → see results for a handful of invited creators (Meta tester-mode); capture the rough edges and first-value speed.
- HIGHTikTok publishing (2nd network)Direct Post API (video.publish). Personal accounts work — no business tier. Needs TikTok's app audit for public posting (~2–6 wk); until then posts are private/self-only. Big video audience; next after Instagram is proven.
- MEDMedia lifecycle / garbage collectionObject stores don't cascade with Postgres FKs: deleting a project must purge its R2 prefix, and generated-but-unused media must be swept so storage cost doesn't grow unbounded. A cleanup job over media_asset.
- MEDEmpty-state & first-run guidance for a new creatorA brand-new account should guide the creator: connect → generate first post → publish, reaching first value in minutes (first-value speed drives 30-day retention).
- HIGHNew-client sign-up & onboarding intakeA guided first-run wizard for a client who just signed up: capture the company profile once — business name, website (auto-fetch logo + brand voice/style/palette/audience), industry, target audience, locations/languages, competitors, brand do's & don'ts, and goals — and write it straight into the project's brand kit. That single source then feeds every tool automatically (Composer copy + image generation, AI Strategist, Listening keywords, Client Reports), so the creator never re-enters the same info. Steps: company profile → connect accounts → brand kit + hashtags → first post. Persisted + resumable; later powers the Phase-2 AI customisation agent.
v1.2Grow— more reach & depth once the loop is proven
- MEDYouTube Shorts publishing (3rd network)videos.insert upload (no special Shorts API). Upload-only scope is 'sensitive' (no costly CASA audit) but needs OAuth verification + a YouTube compliance audit, and the ~6 uploads/day-per-project quota is a real wall until raised. Lowest priority of the three networks.
- MEDAI & media cost guardrailsGeneration (image/video) and storage meter real money; add monitoring + per-creator quotas/limits so a runaway prompt or heavy video usage can't blow the budget. R2's zero egress helps, but generation + storage still meter.
- MEDBest-time-to-post suggestions from real metricsUse the account's real engagement history to recommend calendar slots.
- LOWBulk scheduling & CSV importLoad a month of posts at once.
v2.0Agency phase + big bets— the multi-client vision, after the solo product is proven
- DEEPAgency mode — multiple client brands + team rolesThe original agency vision, deferred until the solo product is proven: manage many client projects with SMM-team vs account-manager vs client roles (who can publish vs approve vs view). The multi-project schema already supports it.
- DEEPClient approvals + review portalClients review/approve posts and view their dashboards. The approvals screen exists from the prototype but is low-value for a solo creator; it becomes core in the agency phase.
- DEEPWhite-label monthly client reports + UTM attributionAuto monthly reports tracing posts → reach → clicks → leads, branded per client (the renew-the-contract artifact) plus full 24h/7d/30d time-series. Agency-grade — not the solo MVP.
- DEEPBilling & plan tiersExplicitly OUT of scope until the owner confirms the MVP is complete. Designed only after that.
- DEEPPaid-ad management / boostingPromote top posts from inside the tool. Large external lift per network.
- DEEPMobile app / push approvalsApprove on the go; native push for pending sign-offs.
CleanupBacklog & parked items— not counted in progress
- TECH DEBTPer-platform video transcoding / normalizationv1 publishes the AI source video AS-IS, so clips that don't match a network's spec (codec, aspect, duration, max size for IG Reels / TikTok / YouTube Shorts / FB) will be rejected at publish. Deliberately deferred: add a managed transcoder (AWS MediaConvert / Coconut / Mux) that re-encodes the source media_asset into per-platform renditions (a media_rendition table) which publish then selects. Prioritised once real video volume justifies it.
- TECH DEBTVideo poster/thumbnail generationVideo needs a poster frame for the UI and some publish flows. v1 uses the provider-supplied thumbnail where available; real frame-extraction (off-Vercel worker / transcoder) comes with the transcoding work above.
- PARKEDMigrate Next middleware → proxyBuild warns the middleware convention is deprecated in this Next version; switch to the proxy file before launch.
- PARKEDResolve set-state-in-effect lint warningsSeveral Stage-0 screens hydrate seed data in an effect; tidy when convenient.
- PARKEDReplace dummy-login copy & branding before public launchThe temporary password gate is demo-only; swap for Clerk (go-public gate) and remove the demo credentials.
- PARKEDMobile navigationThe sidebar is desktop-only (hidden below md) with no hamburger/drawer; phones can't navigate. Deferred — desktop-first for now.
- PARKEDLift muted/faint text contrast to WCAG AA--color-faint (#6b7280 on #0f1115) ≈ 3.9:1, below the 4.5:1 needed for normal text; it's used widely for small/secondary copy.
- PARKEDAdd aria-labels to icon-only buttonsSeveral icon buttons (inbox send, topbar logout, theme toggle) rely on title= or nothing; screen readers announce them with no purpose.
- PARKEDKeyboard alternative for calendar drag-to-rescheduleRescheduling is drag-only (WCAG 2.1.1); add a per-post date menu or arrow-key move for keyboard/AT users.