KariSMMa
Multi-brand social control room · live at portal.karismma.com · doc updated 2026-06-17
Snapshot
Overall roadmap progress (all versions combined)
75%96 of 128 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
89%96 of 108: 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 MVPgenerate 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.
- IN PROGRESSLinkedIn - connect + text/image publish (member feed)Code shipped: real OAuth connect (Sign In with LinkedIn + w_member_social) via /api/oauth/linkedin, encrypted-vault token storage, and text + image publish through the Posts API in publishVariant (images ride the LinkedIn Images upload flow). Blocked on the owner: a LinkedIn Developer app (client id/secret in Vercel) with posting access approved. Pending: scheduled auto-publish (shared with the Facebook item above) and Company-Page posting (Community Management API + org-admin scopes).
- 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 to 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-09-24Analytics: removed the last fabricated numbersv0.16.3 unplugged the synthetic feeds from the Dashboard only. getKpis (fixed +3.2/+11.4/+0.6/+8.9% deltas), getMetrics (a fake 28-day curve from follower count), getTopPosts (reach invented by row position) and a hardcoded Reels-142k format chart still powered Analytics whenever a project had no imported posts, mixing real follower counts and post titles with invented metrics. Deleted the whole synthetic path at the core (the three DataSource methods, their server + mock implementations, synthTrend, the KpiTile/MetricPoint/TopPost types, KpiCard) so it cannot return. Analytics now shows the real imported-post insights or an honest empty state pointing to Connections.
- DONE · 2026-09-24Instagram connect: never leave the user strandedClicking Connect on Instagram left the user on their Instagram feed. Production logs showed Instagram never called our callback: Meta silently refuses an account that has no access to the app (before App Review, only accounts added to the app, as Instagram testers who accepted the invite, and Professional accounts can connect). A forced re-login was suspected first and removed from the default Connect (v0.21.002; "Use a different account" still forces it), but that was not the cause. v0.21.004: Connect records the attempt for the tab, so a provider that never sends the user back now gets a clear explanation in the portal with the exact fix, instead of nothing.
- DONE · 2026-09-24Data integrity: reconnects keep history, no fake accountsFrom the full audit (wave 1). Reconnecting an account used to delete and recreate its row, which wiped its inbox and metric history and duplicated every post on the next import; it now updates in place, and the importer matches posts by platform post id, re-links old copies and removes duplicates (existing damage heals on the next import). Disconnect also removes the account's imported posts so they stop counting. Platforms without a real sign-in (Pinterest, Google Business, X, TikTok) no longer create made-up accounts; they show Coming soon, and old placeholder rows can be removed from Connections. The Meta webhook now requires a valid signature on every delivery, ignores dashboard test samples and no longer exposes a debug dump; cron routes are closed in production without CRON_SECRET; the two destructive setup migrations refuse to run on a database with real data.
- DONE · 2026-09-24Composer publishes exactly what you wroteFrom the full audit (wave 2). The Composer used to add template text to real posts ("Shop the launch", "Here's the story behind it", #fyp, cut X posts to 180 characters), start from demo copy, and fill template captions labelled "AI draft" when the AI failed. Now the master copy is posted exactly as written (plus the brand hashtags); Adapt with AI writes per-platform versions you can edit or reset, and a failure shows the error instead of inventing text; a changed master warns that AI versions are stale. Only connected accounts that can really be posted to (Facebook, Instagram, LinkedIn) and formats that really publish are offered; posting is blocked with the reasons listed when a post is empty, over a limit, over 30 hashtags on Instagram, has a banned term, or is an Instagram post without an image; scheduling needs a future time and the picker works on phones. Publish now records the post before publishing and each result right after, links it to the account, and can't post the same content twice. AI images are stored as JPEG (Instagram accepts only JPEG). The Composer resets when you switch project.
- DONE · 2026-09-24Scheduled posts publish automaticallyScheduling used to save a row that nothing ever published. A cron every 5 minutes now publishes due posts to Facebook, Instagram and LinkedIn and records each platform's result. Safety rules: posts scheduled before automatic publishing existed go back to draft (never posted by surprise); a post more than 30 minutes late is marked failed instead of going out late; each due post is claimed so overlapping runs can't double-post, and it only shows published once a platform accepted it. The old mock job worker, which marked jobs done with fake URLs, no longer runs.
- DONE · 2026-09-24Instagram connect fixed at the root + Connect opens a popupTwo causes, both proven in the Meta dashboard. 1) The Ink Paragon Instagram account was not an Instagram Tester on the Meta app, which is required until the app passes Meta review, so Instagram silently dropped the sign-in onto its feed; it is now a tester (invite accepted). 2) The portal was also reachable on smm-tool-ten.vercel.app, and the return address was built from whichever address was used, but Instagram only has portal.karismma.com registered, so it answered Invalid redirect_uri. Production now has one address: pages opened on a *.vercel.app alias redirect to portal.karismma.com (API routes are left alone). Connect now opens the sign-in in a popup; the popup hands the result back and closes itself, and the page shows Connected without leaving. Version format moves to vX.X.XXX: v0.0.008.
- DONE · 2026-09-24Posts you can manage: approvals and calendar that saveApprovals used to live only on the page (lost on reload) and approved posts never got a date or became scheduled; the calendar's drag-to-reschedule was local only, forced 09:00 UTC, and saved posts could not be edited, cancelled or deleted. Now: Approve asks for the publish time (prefilled with the time proposed in the Composer) and schedules the post; Changes sends it back to draft; comments are saved. In the calendar, click any post to schedule, reschedule, move to draft or delete it (with its captions, image and live links); drag to another day saves and keeps the time of day, never moves a published post, and refuses the past for a scheduled one. Days are your local days, not UTC; drafts without a date are listed on their own instead of being placed on today; approvals show a name instead of a raw id and the post image. v0.0.009.
- DONE · 2026-09-24Account health and numbers you can trustToken days were a hardcoded 60 and accounts never left connected, so dead Instagram / Threads tokens (60 days) failed silently. Now token days come from the real expiry at read time (Facebook Pages and YouTube renew themselves), accounts turn expiring at 7 days and error when expired or when a sync / import hits a dead token (Reconnect is offered), and the hourly job renews Instagram and Threads tokens 20 days ahead. Followers now refresh hourly for Threads and YouTube too (unknown stays unknown, never a fake 0). Client Reports no longer multiply the engagement rate by 100 (3.2% was shown as 320%) and report exactly the chosen period (last 30 days, this month, last month, all time) instead of labelling all-time totals as this month. The AI Strategist no longer auto-runs on every visit from empty data; it generates on request from this project's loaded data, and ideas open in the Composer. A failed project load shows an error with Try again instead of the create-your-first-project screen (which invited duplicate brands). v0.0.010.
- DONE · 2026-09-24Social Inbox replies for realSend used to mark a conversation Replied and throw the text away. Now replies are sent on the platform: Messenger and Instagram DMs (within Meta's 24-hour window) and replies to Instagram and Facebook comments, then added to the thread. Draft with AI writes a reply in the brand voice for you to edit (1 point, never sends by itself). Every message now merges through one path: a customer has one thread (webhook and Sync DM history used different keys, so everyone appeared twice; older threads are re-keyed on the next sync), Meta retries and echoes never duplicate a message, replies sent from the Instagram / Messenger app appear as your side instead of as a new conversation, new customers get their name instead of a numeric id, and Facebook Page comments are ingested. A failed save makes Meta retry instead of losing the message. Close / Reopen work; tag and status saves undo on failure; a load error is shown instead of an empty inbox. Fake sentiment, the hardcoded assignee list and the dead Canned / Make a lead buttons are gone. v0.0.011.
- DONE · 2026-09-24Post your own photosThe Composer could only use AI images, and Library uploads over 1 MB failed. Now Upload image in the Composer (and images in the Library) are scaled to at most 2048 px and converted to JPEG in the browser, then checked and stored by the server, so any phone photo fits and Instagram gets the JPEG it requires; a format the browser can't read (iPhone HEIC) gets a clear message. Videos and documents (up to 50 MB) upload straight to storage through a one-time signed URL. Instagram's feed shape rule (4:5 to 1.91:1) is checked before posting. The LinkedIn API version moves off the retired 202401 (configurable). v0.0.012.
- DONE · 2026-09-24Works on phones, and says only what is trueBelow tablet width there was no navigation at all; a menu button now opens every page in a slide-in panel. A crashed page shows an error with Try again inside the app instead of a blank screen, and unknown addresses get a proper page. Every page note was labelled Prototype, and several made false claims (automations saved and about to run, campaigns tagged from the Composer, @-mentions in Listening, a shared team roster); they now say exactly what is true. The placeholder Settings tabs (hardcoded Team & roles with an Invite that did nothing, General with a Save that did nothing) are removed. Creating a project from the top bar can no longer create two, shows its errors, and long names no longer push the bar off screen. v0.0.013.
- DONE · 2026-09-24Security hardeningThe thumbnail image relay answered anyone and followed redirects anywhere; it now needs a signed-in user, follows redirects only to allowed image hosts, caps size and is no longer cached publicly. The brand scan fetched any address a user typed from the server (internal network and cloud metadata included), without a timeout, and filled the brand kit from error pages; it now reaches public websites only (every hop checked), times out, caps the size and refuses error pages. The portal can no longer be framed by other sites (clickjacking) and sends baseline security headers. When a platform connection fails, the platform's own reason is now shown. v0.0.014.
- DONE · 2026-09-24Saves say why they failedSaving a post or a project threw its error, and production hides thrown messages, so a failed save said nothing useful (on the Projects page, creating, renaming, saving a brand kit or deleting failed silently). Saves now return the real reason and the page shows it. A new post is saved as one unit: its captions, account links and approval request, or nothing (a failed step removes the half-saved post), and the server refuses a scheduled post without a future time or a post with no platform. Two unused post endpoints were removed, and the security build check can no longer be satisfied by a comment. v0.0.015.
- DONE · 2026-09-24AI writes for the real brand, with current modelsEvery AI feature took the brand from the browser as just a name, a voice and hashtags, so the audience, visual style and banned words never reached a prompt, and an empty kit sent its placeholder text as the brand voice. Now the server loads the project's saved kit for every AI request (captions, drafted posts, images, ideas, strategy, reports, hashtags, inbox replies) and passes the voice, audience, website, visual style, colours, hashtags and the words to avoid. Models updated to Claude Sonnet 5 (default), Opus 5.5 and Haiku 4.5; the server accepts only the offered models. Busy or rate-limited answers are retried; an answer cut off, refused, empty or unreadable is reported as such instead of silently producing nothing. AI keys are checked with the provider before they are saved, so Connected means a working key, and key errors are shown. v0.0.016.
- DONE · 2026-09-24A bell you can trust; no demo data in productionThe notification bell called every open conversation New, kept approvals after they were decided (it loaded once), showed a failed check as all caught up, and could show the previous project's activity after a switch. It now lists what needs someone: approvals still pending and conversations whose last message is from the customer, checks again when opened, on focus and every two minutes while visible, says when a check failed (with Try again), and ignores late answers for a project you left. A production deployment missing its Supabase address used to show the demo brands and numbers as if they were real; it now shows a clear not-connected screen. v0.0.017.
- DONE · 2026-09-24Numbers that mean what they sayThreads and YouTube views were stored and summed as reach, so the dashboard's Reach mixed unique accounts with plays; they are now separate everywhere (history corrected on read, new imports store views on their own). The dashboard tile is Post reach (each post's lifetime reach, Instagram / Facebook) with views beside it, and the trend is engagement, which every platform reports. Date ranges are now real calendar periods in your local time: Today starts at midnight, Last month is the previous calendar month, and trends and the best weekday use your local days instead of UTC; format and weekday panels follow the chosen range. Records: Views no longer shows reach, the tiles describe exactly the rows in the table, Followers @ Post is named Followers at import (what it is), and the always-empty Creator, Notes and Impressions columns are gone. Accounts: eight always-empty columns removed, Connected counts only healthy accounts, and LinkedIn members no longer link to a company page. v0.0.018.
- DONE · 2026-09-24Post metrics refresh every day by themselvesPost numbers used to change only when someone pressed Import, and each import read just the latest 25 posts per account. A daily job (03:00 UTC) now imports every project's recent posts, most out of date first, within the time limit; imports read 50 posts per account by following the platforms' pages, with at most 8 insight calls at a time. Each post keeps one current metrics row, updated in place (the old way added a row per import, which the dashboard loaded in full on every view), and Records shows when its metrics were taken. v0.0.019.
- DONE · 2026-09-24Deleting really deletesDeleting a project, a post or a connected account used to leave its stored files behind (AI images, re-hosted thumbnails, uploads), public forever, and removing a Library item only took it off the list. Now a project takes all its files with it, a post or account takes the images made for it (unless another post still uses them; Library files stay), and removing a Library file deletes it unless a post uses it. New files are stored per project. Meta's deauthorize and data-deletion requests now work for Facebook and Instagram as well as Threads, remove the stored images too, refuse unverified requests, never report success when the removal failed, and no longer put the user's id in the public status link. v0.0.020.
- DONE · 2026-09-24Keyboard and screen reader basics; honest docsSide panels are now proper dialogs: focus moves into them, Tab stays inside, Escape closes them and focus returns to where you were. Menus (project switcher, account, notifications, report types) close with Escape and announce whether they are open; Settings tabs work with the arrow keys; icon-only buttons (table pages, image arrows, close) have names. The README describes the app as it is now (it still called it a dummy-data prototype and listed a demo login), there is one version number (package.json follows the app version, checked on every build), the Meta setup guide lists the deletion callback URLs, and the roadmap's Assign says it is saved only in your browser. v0.0.021.
- DONE · 2026-09-24Smaller truthsLists no longer stop silently at 1,000 rows (posts, approvals, inbox, analytics now read every page). A Facebook Page's followers are the same number at connect and in the hourly refresh (connect used to show Page likes). YouTube Shorts are recognised up to 3 minutes, and YouTube now asks only for read access. An import where one platform failed is flagged even when others worked, and an account with no posts is not an error. The dashboard Followers tile counts connected accounts only, and top posts' engagement rates are no longer always shown green with an up arrow. A project without a logo shows its initials on its brand colour instead of an emoji. v0.0.022.
- DONE · 2026-09-24No long dashes in the interfaceEvery em and en dash the app shows was replaced: empty values read -, ranges read 1-20 or 3 to 5, dates read from to, and sentences use colons, commas or full stops. The same for the public roadmap, error messages and the instructions sent to the AI. v0.0.023.
- DONE · 2026-09-24Reports and strategies are keptA generated client report or strategy used to vanish on reload, so reopening it meant paying for it again. Each one is now saved with the project: the Reports page lists the saved reports (open, copy, download or delete them) and the Strategist opens on the last strategy with the time it was written. If saving ever fails, the page says so instead of pretending. v0.0.024.
- DONE · 2026-09-24A failed load never looks emptyOn most pages a data read that failed looked exactly like having no data: Analytics said no posts were imported, Records said there were no records, the dashboard showed zeros. Every page now says when its data couldn't be loaded, with Try again, and hides the empty-state message in that case. v0.0.025.
- DONE · 2026-09-24Use Library images in the ComposerThe Composer's From Library button lists the project's Library images; picking one attaches it to the post, with its real size checked against Instagram's aspect-ratio rule. The top-bar search now says what it does: jump to a page. v0.0.026.
- DONE · 2026-09-24Shared lists for the whole projectThe Library catalog, Ideas, Competitors, Campaigns and Automations lived only in each browser, so a colleague saw none of it and clearing the browser lost it. They now save to the project in the database (once migration 0014 is applied): everyone on the project sees the same lists, changes show at once and save in the background, two people saving at the same moment cannot overwrite each other, and each browser's existing items are added the first time it opens the page. Until the migration runs, the pages work as before and say the list is kept in this browser. The Team roster stays in the browser until real user accounts exist. v0.0.027.
- DONE · 2026-09-28Secure operator sign-inThe temporary login showed its shared credential on the public sign-in page and used a fixed session cookie, so anyone could open the app. Now the credential lives only in the hosting environment, is checked in constant time, and the session is an expiring signed token, so the old cookie no longer works. v0.0.028.
- DONE · 2026-09-28Inbox messages arrive by themselvesFacebook and Instagram deliver a Page's or account's DMs and comments only after that account subscribes the app, and nothing did, so new messages reached the Inbox only through Sync DM history. Each connected Page and Instagram account is now subscribed when it connects and again in the hourly upkeep, which also repairs the accounts connected before. The app-level webhooks were registered in the Meta app the same day. v0.0.029.
- DONE · 2026-09-28Connect TikTokTikTok accounts connect with TikTok's own sign-in (Login Kit). Their follower count refreshes hourly, and their posts come in with the daily import (views, likes, comments, shares) like the other networks. TikTok's one-day access token renews itself from the one-year refresh token. Until TikTok approves the app, only the test accounts added to its sandbox can connect. Posting to TikTok is the next step. v0.0.030.
- DONE · 2026-09-28Portal verified with TikTokThe portal address is verified with TikTok (a signature file at its root), which TikTok requires for every address its app lists and for photo posts, which TikTok fetches from a verified address. The portal now also has public /terms and /privacy links (to the Intelligent Punks pages) and serves post images under /media/ on its own address. v0.0.031.
- DONE · 2026-09-28Post to TikTokThe Composer posts to a connected TikTok account: a video, or a photo post of up to 35 images, now or scheduled. Upload several images or a video (Library videos too); images can be reordered. The TikTok settings follow TikTok's posting rules: the account's name, who can view (no default, only what the account allows), comments, duets and stitches off unless you turn them on, the brand and paid-partnership disclosure, and TikTok's music terms. TikTok fetches the files from the portal's own address; photos are fitted to TikTok's size limits. Posts TikTok is still processing are settled by the 5-minute job. Until TikTok approves the app, posts can only be private (Only me). v0.0.032.
- DONE · 2026-09-28Content PlannerA new page turns a brief into a calendar of written posts: say what the weeks should achieve, the offers and dates to cover, and per channel how many posts a week in which formats. The posts are spread evenly over the period at set times, the AI plans the whole period (pillars, a specific idea per post), then writes every caption, hashtags and visual brief (image prompt, carousel slides or a video shot list) in the brand voice, grounded in what has worked for the brand. Review it as a week by day board, edit any post, make its image, rewrite it with AI, and schedule everything that is ready at its planned time in one go. TikTok and video posts open in the Composer with everything filled in, and are marked done in the plan when scheduled. Plans are saved and shared per project. v0.0.033.
- DONE · 2026-09-28Look at one brand, several or allThe project switcher is a multi-select: tick several brands (or All projects) to see them together, or click one to see it alone. Accounts, Records, Dashboard, Analytics, Calendar, Approvals, Inbox and Listening show exactly the selected brands (Accounts used to list every brand's accounts whichever was chosen); with several shown, a Client column and each post's brand logo tell them apart. Pages that work on one brand (Composer, Planner, Settings) say which one they use and switch with one click. Brand logos now fill in by themselves from the connected accounts' profile pictures, else the brand's website, stored with the app. v0.0.034.
- DONE · 2026-09-28Connect the right account to the right brandNetworks sign in with whatever account the browser is logged into, so a brand could quietly get another brand's account. TikTok now always shows its screen with the account on it, an account already connected to another brand is refused with a clear message (on every network), and Connections says which account was connected to which brand. v0.0.035.
- DONE · 2026-09-28Fix: Analytics, Strategist and Composer stopped workingA type re-export in three server-action files compiled into code that crashed on load, so every action on those pages failed (Analytics could not even load the projects). Fixed, and the build now refuses that pattern. v0.0.037.
- DONE · 2026-09-28Every page matches the real dataA live audit of Records, Accounts, Analytics, Competitors, Listening and Calendar against the database. Records now shows every account's posts (with a warning for accounts whose sign-in expired) and nothing is counted twice; Facebook reach works again (Meta retired its old metric in June); cadence is posts a week over the last 4 weeks; a new account's posts arrive right after connecting; comments on recent posts fill Listening and the Inbox; and the Calendar shows what was published on the networks and what is scheduled directly on Facebook. v0.0.038.
- DONE · 2026-09-28Audit follow-upsInstagram comments show who wrote them, Settings and Connections get time for long imports, and the Calendar says when a Page's scheduled posts can't be read. v0.0.039.
- DONE · 2026-09-29A portal built for clientsThe menu is grouped the way a client works (Create, Engage, Insights, Strategy, Workspace) with plain names: Create post, Posts, Inbox, Media library, Reports. Projects became Brands: a card per brand with its accounts, what's scheduled and how complete its brand kit is, one click to work on it. A new brand gets a Get ready checklist on its Overview (connect accounts, brand kit, plan, first post). Backoffice pages left the menu, and every page now speaks to the client. v0.0.040.
- DONE · 2026-09-29Brand kit: Fetch logo & brand works end to endThe result no longer disappears a second after it shows, and a brand with no website in its kit gets it from its Facebook Page or Instagram profile, so its colours and a suggested voice come in too. v0.0.041.
- DONE · 2026-09-28Own dropdowns everywhere, real link icons, a phone-width top barEvery remaining native select (Inbox, Composer, Team, Automations, Competitors, Campaigns, Accounts, Records, the table footer and filter, the public roadmap) is now the app's own Dropdown, and the old Select is deleted. The Dropdown gained type-to-jump (as a native select has), opens upward when there is no room below, sizes to its longest option, announces its value to screen readers, and Escape in its list no longer closes the drawer or modal around it. Library link cards show the site's own icon, found and stored in our bucket when the link is added (older links on the next visit), with a plain link icon when a site has none; the Google favicon service (a generic globe for most sites) is gone. The top bar fits a 375 px phone: the project name gives way, and the account and workspace buttons show only the avatar below the sm width.
- DONE · 2026-10-07Redesign W0: the new look's foundationNavy and red-orange tokens in one place (globals.css maps the old names), Geist with Heebo for Hebrew, the KariSMMa logo kit on the favicon, app icons, menu and sign-in. A new shell: a 248px menu that collapses to 72, the brand switcher, a points meter with what the points buy, the bell panel, an account menu with theme, language and the version, a phone top bar with a bottom tab bar, and a first-load skeleton. Every shared control restyled, plus toasts, inline notices, one empty, loading and error frame, and a keyboard shortcut sheet (Shift+?). The pages themselves follow in W1 to W7.
- DONE · 2026-10-07Redesign W7: roles, team and recordsThree roles, enforced on the server for every action and read: Owner (the workspace admin, everything), Manager (all brands, no billing, AI keys or deleting brands) and Client approver (Awaiting approval, Calendar and Reports for the brands on their list, landing on Awaiting approval with a three-item menu). Settings gets Team (members, invite by email through the sign-in provider with role cards and brand access, the roles table, approval links you can revoke), Workspace defaults (week start and time zone for the whole workspace, used by every date and picker, and the points alert at 20%) and an Activity log (every approval, publish, delete, rule change, connection and role change, who did it, the brand and a link; filters, CSV, kept 2 years). Clients approve through a 7-day link without signing in, giving their name and email once, every decision logged. Team comments on a post with @mentions that reach the person's bell, a post history, and a points history pop-up from the points meter. Needs migrations 0024 to 0028.
- DONE · 2026-10-07Redesign W1: Overview and Create postOverview in the new look: a Needs you strip (approvals, unanswered messages, failed posts, accounts to reconnect, each one click away), KPI tiles in plain words with a definition behind each (i) and the change against the previous period, the reactions trend daily or as a 7-day average in one chart colour, audience by network with one health line, Top posts and Scheduled next, a skeleton while it loads, and the Get ready checklist restyled. Create post in three zones: the content (text with its counter, media with Upload, From library and Generate, format, the networks as toggle cards, link, tone and hashtags), the networks and their preview (a tab per network with its own character count, phone or desktop, the real frame, the caption per network with Reset to main text), and a sticky action bar (date and time, Save as draft, Send for approval, Schedule, More with Publish now). One AI assist pop-up (Write, Tailor per network, Image, Slides, Video) states each action's real points before it runs and what the balance is after. Ctrl or Cmd + J opens it, Ctrl or Cmd + Enter schedules.
- DONE · 2026-10-07Redesign W2: Calendar and Awaiting approvalThe Calendar in the new look: one navigation bar (previous, Today, next, the period, Month / Week / List, New post), Status and Network filters, a switch for the posts that live on the networks with its dashed legend, and the drafts without a date in a pop-up. Month cards with a status edge, dot, time and the networks' logos; a week time grid with a now line and drag between slots; a list grouped by day with the day on the start side. The post pop-up has two columns: the post as each network shows it, then status, time, networks, history, team comments and Edit, Duplicate, Move to draft, Delete, with Retry on a failed post. Awaiting approval: cards with the real per-network preview, the time picker, the conversation, Ask for changes (with a comment) and Approve and schedule, plus Select all, a decision bar for many at once and a Share approval link pop-up. Keys T M W L and the arrows on the Calendar, A and C on approvals. Team comments, the full history and approval links are wired by W7 (roles, team and records).
- DONE · 2026-10-07Redesign W3: Inbox, Notifications, Listening and CompetitorsThe Inbox in the new look: status tabs with counts (Open, Replied, Closed, All), network, type and label filters as pills, rows with the person, the network, one label, an unread dot and where it came from, and a thread with a Label menu, Automate and Close. Public replies and private messages look different down to the send button, Draft with AI shows its 1 point cost, scams and spam show as a banner and a comment deleted on the network says so. J and K move along the list, Enter opens, R replies, E closes. Notifications: underline tabs with counts, a Brand filter, rows that lead with the brand or the kind with the network on its corner, one action each (Reply, Retry, Review, Reconnect, Open), the same rows in the bell, and Undo after Mark all as read. Listening and Competitors share a tab row: mention cards with the full text, sentiment and matched keywords, tracked keywords with a 7-day trend and none yet instead of 0, and one comparison block of you against each competitor, a table with signed differences, Add and Update in a pop-up, Remove with a confirm and a CSV download.
- DONE · 2026-10-07Redesign W4: Analytics, Posts, Accounts and ReportsThe four Insights pages in the new look. Analytics, Posts and Reports each have their own period, and every number is compared with the period of the same length just before it (never with a made-up baseline). Analytics: four plain-words tiles with the previous value and the change, reactions over time, posting cadence against the reaction rate, reactions by format, the best day to post, and the best posts of the period, each opening in the post pop-up. Posts: the thumbnail, title and type in one column, a tile row for the period, click-to-sort on every column and a pop-up with the media large, every measure, Open on the network and Reuse as a new post. Accounts: three tiles (connected, followers, posts a week) above the table, with a CSV. Reports: the saved reports beside a brand-styled document (the kit colour, the logo, the period, three big numbers, the chart, Highlights, What worked and Recommendations, and where the numbers come from), Copy link, PDF printing on white, Copy as text, Download as Markdown and Delete. Every report keeps the numbers it was written from, so an old report still shows what was true then. CSV on all four pages, and the Free plan still says it shows the last 30 days.
- DONE · 2026-10-07Redesign W5: Autopilot, Content plan, Media library, Strategy and AutomationsAutopilot shows the three modes as cards (Semi and Full locked on the Free plan), channels with a switch, a cadence stepper and format chips, this week's summary with the most it can cost, the last run, and a sticky Unsaved changes bar. The Content plan is a board with a column per week in the shared status colours, a three-step brief pop-up that shows its cost before it writes, and an item pop-up with Make image, pick from the library, Finish in Create post and Schedule. The Media library has folders as a row, an Add menu, pop-ups instead of inline forms, a six-across grid and a two-column asset pop-up. Strategy shows insight cards and predictions and puts its ideas into the one Ideas backlog. Automations gets plain-words search with filters, templates that say which rule does their job, a rules table with status, the builder's live sentence, and a rule library pop-up to copy rules between brands. Every AI button wears the AI gradient and shows its points first.
- DONE · 2026-10-08Marketing website for karismma.comA public website for KariSMMa, served by the same app on karismma.com (www redirects to it, and a temporary vercel.app address serves it without being indexed) while the portal stays exactly as it was on portal.karismma.com. Home, all features and one page for each main part, For agencies, For small businesses, Pricing read from the app's own plans and points, seven beginner guides, About, Contact, Privacy policy and Terms. The product is shown with real portal screenshots and sample brands, in the visitor's light or dark theme. Every page is built ahead with its own title, description, social image and structured data; robots.txt welcomes AI search, and llms.txt describes the product for AI assistants. English first; Hebrew and Spanish are prepared.
- DONE · 2026-10-07Redesign W6: Brands, Settings, setup and sign-in in the new lookBrand cards with the kit colour along the top, followers, scheduled and published, the networks with a dot on one to reconnect, a brand health bar that says what holds it back, and Rename and Delete in the card menu. The brand kit pop-up has Look, Voice, Hashtags and words, and Website tabs with a live preview. Settings splits into brand settings (Connections with the social accounts and, below them, the workspace's AI tools; Brand kit) and workspace settings (Plan and points, Team, Activity log, Workspace defaults); old AI tools links still land on that section. Plan and points compares Free and every plan side by side. The setup wizard always shows its six steps, the ones that don't apply skipped. The upgrade pop-up names the smallest plan that removes the limit. Sign in, sign up, onboarding and not found are rebuilt as two-column and single-card pages.
- DONE · 2026-10-08Design gaps closed (GAPS.md)An audit of the live portal against every screen of the design handoff (276 items, docs/design/2026-10-07/GAPS.md), then the gaps built: the points meter always shows for Owners and Managers (Unlimited for the platform's own workspace and staff), one filter pill, row menus and a phone Sort and filter pop-up on every table, one date and time field with Tomorrow 09:00, eight real network preview frames shared by Create post, the Calendar and approvals, followers over time from the hourly counts, Hide from stats, failure reasons on failed posts, a fuller post history, @mentions with suggestions, a Content plan tray to drag onto the Calendar, structured Strategist insights, plain-language automation activity with Retry, the connect pop-up listing permissions, a Change plan pop-up, the full-screen first run, and design copy for every empty, loading and error state. Items that need an owner decision or a third party are listed as blocked. Needs migrations 0030 to 0033.
- DONE · 2026-10-08Agency details: white-label what goes to clientsSettings, Workspace, Agency details (Owners and Managers): the agency's logo for light and dark backgrounds, business name, website, email, phone, address, company or VAT number and a footer note, with a live preview. Client reports (and their PDF) lead with the agency's logo beside the client brand and end with Prepared by and the contacts; the approval link page shows the same. With nothing set, both keep the workspace name only. A small Made with KariSMMa line stays on for now. Needs migration 0029.
- DONE · 2026-10-08AI apps (MCP): run KariSMMa from Claude, ChatGPT, Cursor and Claude CodeA remote MCP server at portal.karismma.com/api/mcp, so a client runs their social media from any AI app that speaks MCP. Apps connect by signing in (claude.ai and ChatGPT connectors, through Clerk) or with a personal access token (Claude Code, Cursor, Claude Desktop), made in Settings, Connections, AI apps: read only or full, all brands or some, with an expiry, shown once and revocable. 53 tools cover the workspace, posts and the calendar, approvals, the Inbox, results and reports, AI writing and media, the media library, Autopilot, ideas, listening and automations, plus ready-made prompts and the brand kits as resources. Every call runs as the person with their role, through the same checks, plan limits and points as the app; publishing, replying and deleting need the person's OK, scams are never answered, every change is in the Activity log as via MCP, and calls are rate limited. The Free plan reads only (a placeholder until the owner decides). Needs migration 0035 and Clerk OAuth settings.
- DONE · 2026-10-08AI apps ready for the Claude, ChatGPT and MCP Registry directoriesThe MCP server meets the directories' rules: every tool has a title and is marked read-only or destructive (every write now asks before it runs), descriptions state facts only, plan messages name the plan without a price, errors say where to get help, and long answers come in pages. The AI image, video, upscale and voice tools are not offered to apps that sign in (the directories don't accept AI media generation); personal access tokens keep them (one switch, MCP_MEDIA_TOOLS_FOR_OAUTH). A public guide at karismma.com/ai-apps covers setup for Claude, ChatGPT, Claude Code, Cursor, VS Code and Claude Desktop, every tool (read from the server's own list), the safety model, privacy and an FAQ, linked from the footer and Features. The listing pack (docs/mcp/listing) has the answers for every portal step, the ChatGPT plugin package, the registry's server.json, the icons and a sample-data script for the reviewer account. Owner steps pending: karismma.com DNS, reviewer account, submissions, registry domain proof.
- DONE · 2026-10-26Daily comments: posts worth a comment, with drafts, left by handEngage, Daily comments: every day each brand that switches it on gets up to 20 Instagram posts by others worth a comment (top posts for its hashtags, the accounts it watches, its competitors, people who commented on its posts), each with a short comment drafted in the brand voice and checked to sound human (never generic, never self-promotion or a link). Phone-first: Copy and open copies the comment and opens the post in the Instagram app, then Done or Skip; a counter shows how many are done today. Nothing is posted by the app (the Instagram API cannot comment on other accounts' posts, and bots get accounts blocked). Daily limit, no repeat account within 7 days, quiet days and Shabbat. Learns which sources and comment styles bring profile visits, and says too early until it can. AI apps get get_engage_queue, mark_engaged and set_engage_watchlist. Migration 0039.
- DONE · 2026-10-26Make clips: one long video or song becomes short vertical clipsIn the Media library, Make clips on a video or audio file reads it on the server and suggests its best parts for Reels, trial reels, Shorts and TikTok, each with why: a song or DJ mix is cut by bars (its tempo and bar lines found from the sound) at the drops, the build-ups, the highest-energy bars, likely vocals and breakdowns; talking and other video by its loudest moments, movement, scene changes and pauses. The parts sit on a timeline and play on their own; the person picks them, moves a start or end by a bar (or a second), adds their own, and the clips are cut one by one into 1080 x 1920 MP4s (H.264 and AAC, sound in sync, no added text) in the folder Clips/<source title>, each tagged with its source and part. A square or wide video fills the tall frame over a blurred copy of itself or is cropped in the middle. The AI apps get suggest_clips and make_clips. No migration.
- 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 to 4 wk, often rejected first try). Deferred to the same milestone as self-serve sign-up.
- IN PROGRESSClient logins (Clerk) + workspace scopingDecided 2026-09-24: self-serve client platform, Clerk, workspaces = Clerk Organizations. Step 1 shipped (v0.20.0): Clerk sign-in/sign-up, workspace switcher + user menu, Clerk-aware requireSession(), middleware renamed to the Next 16 proxy; all of it switches on only when the Clerk keys are set, and the legacy login stays until then. The same PR gated the 23 feature Server Actions that never checked the session (publish, AI keys, connections, AI generation, uploads) and added a build guard (scripts/check-server-actions.mjs) that fails the build if an action ships without requireSession(). Step 2 shipped (v0.21.0): every project belongs to a workspace (migration 0012, project.workspace_id), and src/lib/tenant.ts is the isolation boundary (the app reads Postgres with the service-role key, so RLS does not apply to it): every Server Action and all 10 OAuth start/callback routes check the caller may touch that project or row, cross-brand reads are limited to the workspace's own projects, and the platform's AI keys are staff-only (PLATFORM_ADMIN_USER_IDS). The build guard now requires a tenancy check, not just a login. To go live: run 0012, claim the existing projects for your own org, then set the Clerk keys. DB-level RLS on the Clerk org claim is later hardening.
- IN PROGRESSPoints wallet + metering (subscriptions + points)Decided 2026-09-24: a subscription tier per mode (Manual / Semi-auto / Full-auto) with a monthly points allowance, plus top-ups; every AI action spends points. Step 3 shipped (v0.21.001): migration 0013 (workspace wallet + points ledger; the balance moves only through spend_points, atomic and never below zero, and grant_points, idempotent on a key); every AI action charges its cost before the provider call and refunds on failure (brand scan degrades to logo + colours when out of points); all prices in src/lib/billing/pricing.ts (proposed, awaiting sign-off); balance chip in the topbar; new workspaces start with a 30-point sign-up bonus. Not metered: legacy mode and platform staff. Step 4 shipped (v0.21.003): Stripe billing. Settings > Plan shows the balance, the three plans and top-ups; Checkout takes its prices from pricing.ts (no Stripe catalog to maintain); plan switches apply now with the new price and points from the next renewal; Manage billing opens Stripe's customer portal (card, invoices, cancel). Points are credited only by the signature-verified Stripe webhook (/api/webhooks/stripe), idempotent per invoice or checkout, and subscription events re-read Stripe so a late or out-of-order event can never undo a newer state. Paying is workspace-admin only; top-ups need an active plan. Switches on when the Stripe keys are set.
v1.1First creatorsharden 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 to 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.2Growmore 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 betsthe 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 itemsnot 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.