Handoff: CreatorTrack Social Analytics Suite (2026-07-06)¶
Social Analytics expanded from a single dashboard into a 4-tab suite (Overview, Reports, Messages, Publishing) on branch feat/social-analytics-suite. Every tab verified in the running dev server on :3067 (Playwright: 200s, zero console/page errors, screenshots inspected) plus end-to-end functional tests of every API op.
What was built¶
Shell. components/apps/social/SocialShell.tsx + tabs.ts: AppSidebar wide-panel chrome mirroring FinanceShell (empty rail, flat 4-tab panel, ?view= server-rendered navigation). app/(suite)/social/page.tsx routes views; the open-time platform sync now runs ONLY on Overview (quota discipline).
Reports (lib/social/reports.ts, ReportsClient.tsx). Weekly/monthly roll-ups generated FROM the app.social_metrics cache (zero platform-API quota). One row per (workspace, kind, period_start) in app.social_reports, upsert so regeneration converges (tested: 2 reports stayed 2). Payload freezes per-platform sections (follower start/end/delta, views, watch time, subs gained/lost, engagement, top videos published in period) + cross-platform totals + a daily-views series for the in-report chart. Archive rail + viewer + delete in-app. Period math is America/Chicago; the boundary-day snapshot counts as the closing state.
Messages (lib/social/messages.ts, MessagesClient.tsx, app.social_messages). Unified inbox. YouTube comments sync FOR REAL: fetchRecentComments added to lib/youtube.ts (commentThreads, 1 quota unit per 50-thread page, one page per explicit Sync press; no polling). Same credential ladder as the dashboard (workspace/personal connection, owner-token fallback owner-only). Sync upserts on external identity WITHOUT touching status; verified read status survives re-sync. Inbox/Archived boxes, platform filter, permalink out-links, mark read/unread/archive. Honest gap: Instagram and TikTok are schema + UI ready but NOT live: IG needs a Graph API page token with instagram_manage_comments/instagram_manage_messages; TikTok needs the Business API comment tier. The TODO route is documented at the top of lib/social/messages.ts (add sync fns beside syncYouTubeComments, flip wired in MESSAGE_PLATFORMS); the UI states this plainly instead of faking.
Publishing (lib/social/publishing.ts, PublishingClient.tsx, app.social_posts). Month/week content calendar + drafts rail + editor modal (multi-platform picker, title, caption, media placeholder, datetime, draft/scheduled/published). Two-way Calendar hook, tested both directions:
- Post -> Calendar: a scheduled post owns a LOCAL app.calendar_events row (calendar_id='social-posts', calendar name "Publishing", platform color); confirmed visible through the Calendar app's own API.
- Calendar -> Post: reads resolve the linked event's start as the effective time, so an edit/drag in the Calendar app moves the post (tested via calendar op:update: post followed to the new time). Deleting the event in Calendar unschedules the post (FK ON DELETE SET NULL); unscheduling the post deletes the event (tested).
- Other local calendar events render as muted read-only context chips in the grid.
Data plane¶
- Migration
db/migrations/20260706T235752_..._social_suite_reports_messages_posts.sql:app.social_reports,app.social_messages,app.social_posts, all withcore.apply_workspace_rls. Applied toct_feat_social_analytics_suite. - Drizzle tables added to
db/schema.ts;readApiConnections/connectionForexported fromlib/social/data.tsfor reuse. /api/apps/socialextended: GET?surface=reports|messages|publishing, POST opsreport_generate|report_delete|msg_sync|msg_status|post_create|post_update|post_delete. Fail-loud (502 on real pull failures), idempotent upserts throughout.
Verification evidence¶
npx tsc --noEmitclean.- All 4 views: HTTP 200, expected content, 0 console errors (headless Playwright, shared MCP browser was contested by another agent so verification used the assets-venv Playwright directly).
- Functional run: weekly + monthly reports generated from real synced data (71.5K views, 72.1K subs, top videos); 50 real YouTube comments pulled; status persistence across re-sync confirmed; post CRUD + both calendar directions confirmed. Demo data left in place (2 reports, 50 messages, 1 scheduled post on Jul 10).
Incident during build¶
The dev-slot reaper tore down the slot mid-build at 19:02 (9 live slots > cap 4, this slot had zero browser connections). Worktree deleted; DB survived (reaper's pg terminate failed on permissions). Rebuilt via forge_creatortrack_agent_bootstrap.sh, all work restored from session context, and a keepalive TCP connection to :3067 now holds the slot active. Lesson for agents on this rig: hold a connection to your dev port (or keep a browser tab) for the whole session.
For review¶
- Branch:
feat/social-analytics-suite(3 commits: data plane 76ef881, UI 808f00c, polish fbfd6be). Not merged, not deployed, prod untouched. - Review: two-way semantics in
lib/social/publishing.ts(event-start-wins rule), the Messages TODO route, report period math, App Library copy forsocial(tagline still says dashboards only; consider updating at merge). - Preview: http://100.97.43.104:3067 (tabs: /social, ?view=reports, ?view=messages, ?view=publishing)
URL: https://mkdocs.justinsforge.com/memory/handoffs/creatortrack-social-analytics-suite-2026-07-06/