Files
ClaudeMarketing/docs/plans/2026-03-23-marketing-command-center.md

28 KiB
Raw Permalink Blame History

Marketing Command Center Implementation Plan

For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

Goal: Build a self-hosted Next.js dashboard that orchestrates a 7-agent AI marketing pipeline, previews generated assets, integrates with Claude Code (Max plan) for feedback, and publishes to Instagram/TikTok via Postiz and Nextdoor via direct API.

Architecture: Next.js 15 App Router with SQLite (Prisma), NextAuth credentials auth, Server-Sent Events for realtime, Claude Code subprocess spawning (Max plan OAuth, no API key), Postiz for media hosting + social publishing. Everything in Docker Compose.

Tech Stack: Next.js 15, TypeScript, Tailwind CSS, shadcn/ui, Prisma + SQLite, NextAuth v5, @postiz/node, Docker Compose, Remotion, Playwright, Tavily AI SDK

Reference docs (read before starting any task):

  • FRONTEND_ARCHITECTURE.md — full technical architecture, DB schema, code samples
  • THE_COMPLETE_PICTURE.md — system overview, data flow, user journey
  • AUTONOMOUS_MARKETING_PLAN.md — 7-agent pipeline design, creative frameworks
  • PLATFORM_SPECS.md — Instagram/TikTok/Nextdoor API specs and dimensions
  • BEST_PRACTICES_GUIDE.md — Anthropic skill authoring guidelines, knowledge file templates

Phase 1: Project Scaffold + Docker

Task 1: Initialize Next.js Project

Files:

  • Create: package.json
  • Create: tsconfig.json
  • Create: next.config.ts
  • Create: tailwind.config.ts
  • Create: postcss.config.mjs
  • Create: .gitignore
  • Create: app/layout.tsx
  • Create: app/page.tsx

Step 1: Create the Next.js project

Run:

cd ~/Desktop/code/claude_marketing
npx create-next-app@latest . --typescript --tailwind --eslint --app --src-dir=false --import-alias="@/*" --turbopack

Expected: Project scaffold created, package.json exists

Step 2: Verify it runs

Run: npm run dev Expected: Server starts at http://localhost:3000

Step 3: Commit

git init
git add -A
git commit -m "feat: scaffold Next.js 15 project with TypeScript and Tailwind"

Task 2: Add shadcn/ui

Files:

  • Modify: package.json (new deps)
  • Create: components/ui/ (component files)
  • Create: lib/utils.ts
  • Modify: tailwind.config.ts (shadcn theme)

Step 1: Initialize shadcn/ui

Run:

npx shadcn@latest init -d

Expected: components.json created, lib/utils.ts created

Step 2: Add core components we'll need

Run:

npx shadcn@latest add button card input label badge dialog tabs table textarea separator avatar dropdown-menu sheet sidebar toast

Expected: Components installed in components/ui/

Step 3: Commit

git add -A
git commit -m "feat: add shadcn/ui with core components"

Task 3: Set Up Prisma + SQLite Database

Files:

  • Create: prisma/schema.prisma
  • Create: lib/prisma.ts

Step 1: Install Prisma

Run:

npm install prisma @prisma/client
npx prisma init --datasource-provider sqlite

Expected: prisma/schema.prisma created with SQLite datasource

Step 2: Write the full schema

Replace prisma/schema.prisma with the complete schema from FRONTEND_ARCHITECTURE.md lines 68-156. Models: User, Campaign, AgentRun, Asset, ClaudeSession, TrendReport.

Step 3: Create the Prisma client singleton

Create lib/prisma.ts:

import { PrismaClient } from "@prisma/client";

const globalForPrisma = globalThis as unknown as { prisma: PrismaClient };

export const prisma = globalForPrisma.prisma || new PrismaClient();

if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;

Step 4: Push schema to database

Run: npx prisma db push Expected: SQLite file created at prisma/data/marketing.db

Step 5: Commit

git add -A
git commit -m "feat: add Prisma with SQLite schema — campaigns, assets, agent runs"

Task 4: Set Up NextAuth Authentication

Files:

  • Create: lib/auth.ts
  • Create: app/api/auth/[...nextauth]/route.ts
  • Create: prisma/seed.ts
  • Create: middleware.ts
  • Modify: package.json (add deps)

Step 1: Install auth dependencies

Run: npm install next-auth@beta @auth/prisma-adapter bcryptjs && npm install -D @types/bcryptjs

Step 2: Create auth config

Create lib/auth.ts with NextAuth Credentials provider from FRONTEND_ARCHITECTURE.md lines 170-201. JWT session strategy, bcrypt password comparison.

Step 3: Create the API route

Create app/api/auth/[...nextauth]/route.ts:

import { handlers } from "@/lib/auth";
export const { GET, POST } = handlers;

Step 4: Create auth middleware

Create middleware.ts that protects all routes except /login and /api/auth.

Step 5: Create seed script

Create prisma/seed.ts from FRONTEND_ARCHITECTURE.md lines 206-222. Reads ADMIN_EMAIL and ADMIN_PASSWORD from env, bcrypt hashes, upserts user.

Add to package.json:

"prisma": { "seed": "npx tsx prisma/seed.ts" }

Step 6: Create .env.local

Create .env.local:

NEXTAUTH_SECRET=dev-secret-change-in-production-32chars
NEXTAUTH_URL=http://localhost:3000
ADMIN_EMAIL=admin@localhost
ADMIN_PASSWORD=admin123

Step 7: Seed the database

Run: npx prisma db seed Expected: Admin user created

Step 8: Commit

git add -A
git commit -m "feat: add NextAuth credentials auth with admin seed"

Task 5: Create Login Page

Files:

  • Create: app/(auth)/login/page.tsx
  • Create: app/(auth)/layout.tsx

Step 1: Create auth layout

Centered layout, no sidebar. Just a card in the middle of the screen.

Step 2: Create login page

Form with email + password inputs, submit button, error state. Uses signIn("credentials", { ... }) from next-auth. Redirects to / on success.

Step 3: Test login flow

Run: npm run dev Navigate to http://localhost:3000 → should redirect to /login Log in with admin@localhost / admin123 → should redirect to dashboard

Step 4: Commit

git add -A
git commit -m "feat: add login page with credentials auth"

Task 6: Create Dashboard Layout Shell

Files:

  • Create: app/(dashboard)/layout.tsx
  • Create: app/(dashboard)/page.tsx
  • Create: components/app-sidebar.tsx
  • Create: components/header.tsx

Step 1: Create sidebar navigation

Using shadcn Sidebar component. Navigation items:

  • Dashboard (home icon)
  • Campaigns (megaphone icon)
  • Assets (image icon)
  • Trends (trending-up icon)
  • Queue (calendar icon)

Step 2: Create header bar

Shows current page title, user avatar dropdown with sign out.

Step 3: Create dashboard home page

Placeholder cards: "Active Campaigns", "Pending Review", "Published This Week", plus a "New Campaign" button.

Step 4: Verify layout

Run: npm run dev, log in, verify sidebar + header + content area render correctly.

Step 5: Commit

git add -A
git commit -m "feat: add dashboard layout with sidebar navigation"

Task 7: Docker Compose Setup

Files:

  • Create: Dockerfile
  • Create: docker-compose.yml
  • Create: .env.example
  • Create: .dockerignore

Step 1: Create Dockerfile

Multi-stage build from FRONTEND_ARCHITECTURE.md lines 478-499. Stages: base (node:20-alpine + Claude CLI + Playwright), deps, builder, runner. Output: standalone Next.js.

Step 2: Create docker-compose.yml

4 services from FRONTEND_ARCHITECTURE.md lines 516-557: app, postiz, postiz-db, redis. 7 named volumes. App mounts pipeline-outputs and pipeline-knowledge.

Step 3: Create .env.example

TAVILY_API_KEY=tvly-your-key
POSTIZ_URL=http://postiz:5000
POSTIZ_API_KEY=your-postiz-key
POSTGRES_PASSWORD=secure-password
NEXTDOOR_API_TOKEN=your-token
NEXTDOOR_ADVERTISER_ID=your-id
NEXTAUTH_SECRET=generate-random-32-char-string
ADMIN_EMAIL=you@yourdomain.com
ADMIN_PASSWORD=your-password

Step 4: Create .dockerignore

node_modules
.next
prisma/data
.env.local

Step 5: Test Docker build

Run: docker compose build app Expected: Image builds successfully

Step 6: Commit

git add -A
git commit -m "feat: add Docker Compose with Postiz, Postgres, Redis"

Phase 2: Pipeline Integration

Task 8: Create Pipeline Directory Structure

Files:

  • Create: pipeline/CLAUDE.md
  • Create: pipeline/knowledge/brand_identity.md
  • Create: pipeline/knowledge/platform_guidelines.md
  • Create: pipeline/knowledge/product_campaign.md
  • Create: pipeline/assets/.gitkeep
  • Create: pipeline/outputs/.gitkeep
  • Create: pipeline/package.json

Step 1: Create CLAUDE.md

Write the project source-of-truth file following the template in BEST_PRACTICES_GUIDE.md Section 2. Declares all 7 agents, folder structure, pipeline execution order, output conventions, safety rules.

Step 2: Create knowledge file templates

Use the templates from BEST_PRACTICES_GUIDE.md Section 3. Placeholder content for each — user fills in their actual brand details.

Step 3: Create pipeline package.json

{
  "name": "marketing-pipeline",
  "private": true,
  "dependencies": {
    "@tavily/core": "^0.7.2"
  }
}

Step 4: Install pipeline deps

Run: cd pipeline && npm install

Step 5: Commit

git add -A
git commit -m "feat: add pipeline directory with CLAUDE.md and knowledge templates"

Task 9: Create the 7 Agent Skills

Files:

  • Create: pipeline/skills/trend-scout/SKILL.md
  • Create: pipeline/skills/marketing-research-agent/SKILL.md
  • Create: pipeline/skills/script-writer/SKILL.md
  • Create: pipeline/skills/ad-creative-designer/SKILL.md
  • Create: pipeline/skills/video-ad-producer/SKILL.md
  • Create: pipeline/skills/copywriter-agent/SKILL.md
  • Create: pipeline/skills/distribution-agent/SKILL.md

Step 1: Write each SKILL.md

Follow the template from BEST_PRACTICES_GUIDE.md Section 4. Each skill needs:

  • YAML frontmatter (name, description with trigger phrases, ≤1024 chars)
  • CRITICAL: Read Knowledge Files section
  • Step-by-step workflow
  • Output convention: outputs/{task_name}_{date}/{subfolder}/
  • Troubleshooting + Quality Checklist

Use the agent specs from AUTONOMOUS_MARKETING_PLAN.md for each agent's purpose, inputs, outputs, and tools. Use platform dimensions from PLATFORM_SPECS.md.

Key details per agent:

  • trend-scout: Tavily queries for trending hooks, competitor ads, viral formats. Outputs trend_report.json.
  • marketing-research-agent: 5 Tavily queries (trends, competitors, pain points, hooks, viral). Outputs research_results.json + research_brief.md + interactive_report.html.
  • script-writer: Reads research → writes 5 hook variations × 3 platform styles. Outputs to scripts/ folder.
  • ad-creative-designer: NanoBanana MCP → HTML/CSS layout → Playwright screenshot. Configs for IG 1080x1080, IG Stories 1080x1920, Nextdoor 1200x1200, Nextdoor 1200x628.
  • video-ad-producer: Remotion compositions. Style param: polished (IG), authentic (TikTok), local (Nextdoor). Auto-render to MP4.
  • copywriter-agent: Platform-tuned captions. Outputs instagram_captions.json, tiktok_captions.json, nextdoor_posts.json.
  • distribution-agent: Assembles publish manifest. Gate-protected. Outputs Publish_{campaign}_{date}.md.

Step 2: Verify skills are discoverable

Run from pipeline/ directory:

claude -p "What skills are available?" --allowedTools "Read,Grep,Glob"

Expected: All 7 skills listed

Step 3: Commit

git add -A
git commit -m "feat: add 7 agent skills — trend scout through distribution"

Task 10: Set Up Remotion Video Project

Files:

  • Create: pipeline/remotion-ad/ (full Remotion project)

Step 1: Initialize Remotion

Run:

cd pipeline
npx create-video@latest remotion-ad --template blank

Expected: Remotion project created in pipeline/remotion-ad/

Step 2: Install Remotion deps

Run:

cd pipeline/remotion-ad
npm install @remotion/google-fonts

Step 3: Verify Remotion renders

Run: npx remotion render src/index.ts MyComp --output out.mp4 Expected: MP4 file created

Step 4: Commit

git add -A
git commit -m "feat: add Remotion video project for ad generation"

Task 11: Claude Subprocess Spawner (lib/claude.ts)

Files:

  • Create: lib/claude.ts

Step 1: Write the failing test

Create __tests__/lib/claude.test.ts:

import { runAgentStep, buildCampaignPrompt } from "@/lib/claude";

describe("buildCampaignPrompt", () => {
  it("builds a prompt from campaign config", () => {
    const config = {
      name: "test",
      platforms: ["instagram", "tiktok"],
      goal: "app downloads",
      keyMessage: "test message",
    };
    const prompt = buildCampaignPrompt(config);
    expect(prompt).toContain("instagram");
    expect(prompt).toContain("tiktok");
    expect(prompt).toContain("app downloads");
  });
});

Step 2: Run test to verify it fails

Run: npx jest __tests__/lib/claude.test.ts Expected: FAIL

Step 3: Implement lib/claude.ts

Create lib/claude.ts with:

  • buildCampaignPrompt(config) — turns campaign form data into the prompt string
  • runAgentStep(agentName, prompt, cwd) — spawns claude -p as subprocess, returns { sessionId, output }
  • launchPipeline(campaignId, prompt, cwd) — runs all agent steps sequentially, emits SSE events
  • pipelineEvents — EventEmitter for SSE broadcasting
  • sendChatMessage(sessionId, message, cwd) — for the Claude feedback chat

Follow the code from FRONTEND_ARCHITECTURE.md lines 290-365. Key: each agent runs as its own short claude -p call (not one long session) to avoid the Max plan SIGTERM timeout issue.

Step 4: Run test to verify it passes

Run: npx jest __tests__/lib/claude.test.ts Expected: PASS (at least buildCampaignPrompt — subprocess tests need integration test)

Step 5: Commit

git add -A
git commit -m "feat: add Claude subprocess spawner with per-agent-step execution"

Task 12: Postiz Client (lib/postiz.ts)

Files:

  • Create: lib/postiz.ts

Step 1: Install Postiz SDK

Run: npm install @postiz/node

Step 2: Write lib/postiz.ts

Implement from FRONTEND_ARCHITECTURE.md lines 371-424:

  • uploadToPostiz(filePath) — multipart upload, returns { mediaId, publicUrl }
  • pushToPostiz(asset, scheduledAt) — uploads media + creates scheduled post
  • getPostizIntegrations() — lists connected channels

Step 3: Commit

git add -A
git commit -m "feat: add Postiz client for media upload and scheduling"

Task 13: File Serving API Route

Files:

  • Create: app/api/files/[...path]/route.ts

Step 1: Implement file server

From FRONTEND_ARCHITECTURE.md lines 433-466. Auth-gated, path-traversal protected, serves images/videos/JSON/HTML/markdown from the pipeline outputs directory.

Step 2: Test manually

Place a test image in pipeline/outputs/test.png, run dev server, navigate to /api/files/outputs/test.png → should see image (after login).

Step 3: Commit

git add -A
git commit -m "feat: add authenticated file serving for pipeline outputs"

Phase 3: Campaign CRUD + Pipeline UI

Task 14: Campaign List Page

Files:

  • Create: app/(dashboard)/campaigns/page.tsx
  • Create: app/api/campaigns/route.ts

Step 1: Create API route

GET /api/campaigns — returns all campaigns ordered by createdAt desc. POST /api/campaigns — creates a new campaign (name, platforms, config).

Step 2: Create the campaigns list page

Table or card grid showing: campaign name, status badge, platforms, created date, "View" button. Plus a "New Campaign" link.

Step 3: Commit

git add -A
git commit -m "feat: add campaign list page with CRUD API"

Task 15: New Campaign Form

Files:

  • Create: app/(dashboard)/campaigns/new/page.tsx
  • Create: components/campaign-form.tsx

Step 1: Build the campaign form component

Fields:

  • Campaign name (text input)
  • Platforms (checkboxes: Instagram, TikTok, Nextdoor)
  • Campaign goal (select: app downloads, brand awareness, engagement)
  • Key message (textarea)
  • Social proof (textarea)
  • Variations per platform (number input, default 5)
  • Use latest trend report (checkbox)

Submit → POST to /api/campaigns → redirect to campaign detail page.

Step 2: Commit

git add -A
git commit -m "feat: add new campaign form"

Task 16: Campaign Detail Page — Pipeline Progress Tab

Files:

  • Create: app/(dashboard)/campaigns/[id]/page.tsx
  • Create: app/(dashboard)/campaigns/[id]/layout.tsx
  • Create: app/api/campaigns/[id]/route.ts
  • Create: app/api/campaigns/[id]/launch/route.ts
  • Create: app/api/campaigns/[id]/stream/route.ts
  • Create: components/pipeline-progress.tsx
  • Create: hooks/usePipelineProgress.ts

Step 1: Create campaign detail layout

Tab navigation: Pipeline | Assets | Claude Chat. Shows campaign name + status badge in header. "Launch Pipeline" button (only when status is draft).

Step 2: Create launch API route

POST /api/campaigns/[id]/launch — calls launchPipeline() from lib/claude.ts. Creates output directory, builds prompt from campaign config, spawns Claude subprocess. Returns immediately (pipeline runs async).

Step 3: Create SSE stream route

GET /api/campaigns/[id]/stream — SSE endpoint from FRONTEND_ARCHITECTURE.md lines 231-266. Subscribes to pipelineEvents for this campaign ID.

Step 4: Create usePipelineProgress hook

From FRONTEND_ARCHITECTURE.md lines 270-285. Connects to SSE endpoint, updates agent status in real-time.

Step 5: Create pipeline progress component

Shows the 7 agent steps as a vertical list. Each step shows: status icon (pending/running/completed/failed), agent name, duration, output summary. Uses the SSE hook for live updates.

Step 6: Wire it all together

Campaign detail page shows pipeline progress. "Launch Pipeline" button triggers launch API → SSE updates flow to UI.

Step 7: Commit

git add -A
git commit -m "feat: add campaign pipeline progress with real-time SSE updates"

Files:

  • Create: app/(dashboard)/campaigns/[id]/assets/page.tsx
  • Create: app/api/assets/route.ts
  • Create: app/api/assets/[id]/route.ts
  • Create: components/asset-gallery.tsx
  • Create: components/asset-card.tsx

Step 1: Create assets API routes

GET /api/assets?campaignId=X&type=image&platform=instagram — filtered asset list. PATCH /api/assets/[id] — update status (approve/reject), update metadata.

Step 2: Create asset card component

Shows: thumbnail preview (images inline, video with play button), platform badge, dimensions badge, status badge, hook text preview, caption preview. Approve (green check) and Reject (red X) buttons.

Images served via /api/files/... route. Videos served via <video> element with same route.

Step 3: Create asset gallery component

Grid layout. Filter bar: platform dropdown, type dropdown (image/video/copy/all), status dropdown. Bulk select with "Approve Selected" / "Reject Selected" buttons.

Step 4: Commit

git add -A
git commit -m "feat: add asset gallery with filtering and approve/reject"

Task 18: Campaign Detail — Claude Chat Tab

Files:

  • Create: app/(dashboard)/campaigns/[id]/chat/page.tsx
  • Create: app/api/claude/route.ts
  • Create: components/claude-chat.tsx
  • Create: hooks/useClaudeChat.ts

Step 1: Create Claude chat API route

POST /api/claude — accepts { message, sessionId, campaignPath }. Spawns claude -p with --resume if sessionId exists. Streams response via stream-json format. Saves/updates ClaudeSession in DB.

Step 2: Create useClaudeChat hook

Manages message list, streaming state, session ID persistence. Sends messages to API, parses streaming response, appends text deltas to UI in real-time.

Step 3: Create Claude chat component

Chat interface: message list (user bubbles right, Claude bubbles left), text input with send button, streaming indicator. Session ID stored in ClaudeSession table for --resume across page navigations.

Step 4: Commit

git add -A
git commit -m "feat: add Claude chat panel with streaming and session persistence"

Phase 4: Publishing Integration

Task 19: Push to Postiz Flow

Files:

  • Create: app/api/postiz/route.ts
  • Create: components/postiz-push-modal.tsx

Step 1: Create Postiz API route

POST /api/postiz — accepts { assetIds, scheduledAt }. For each asset: uploads media to Postiz, creates scheduled post, updates asset record with postizPostId and status = "published".

GET /api/postiz/integrations — returns connected Postiz channels (so UI knows which platforms are available).

Step 2: Create push modal component

Triggered by "Push to Postiz" button in asset gallery. Shows:

  • Selected assets with previews
  • Platform for each asset
  • Caption preview (editable)
  • Schedule date/time picker (defaults to recommended time)
  • Confirm / Cancel buttons

On confirm → calls POST /api/postiz → closes modal → updates asset cards with "Scheduled" badge.

Step 3: Add "Push to Postiz" button to asset gallery

Appears when 1+ assets are approved and selected. Opens the push modal.

Step 4: Commit

git add -A
git commit -m "feat: add Push to Postiz flow with scheduling modal"

Task 20: Postiz Queue Page

Files:

  • Create: app/(dashboard)/queue/page.tsx

Step 1: Create the queue page

Lists all assets with postizPostId set. Shows: asset thumbnail, platform, caption preview, scheduled time, status (scheduled/published/failed). Sorted by scheduled time.

Optional: iframe embed of Postiz dashboard at POSTIZ_URL for the visual calendar.

Step 2: Commit

git add -A
git commit -m "feat: add Postiz publishing queue page"

Task 21: Nextdoor Direct API Integration

Files:

  • Create: lib/nextdoor.ts
  • Create: app/api/nextdoor/route.ts

Step 1: Create Nextdoor client

GraphQL client for Nextdoor Ads API. Functions:

  • createNextdoorCampaign(name, budget, schedule)
  • createNextdoorAdGroup(campaignId, targeting)
  • uploadNextdoorCreative(filePath)
  • createNextdoorAd(adGroupId, creativeId, copy)

Step 2: Create API route

POST /api/nextdoor — accepts asset IDs, creates campaign + ad group + creative + ad in Nextdoor. Updates asset status.

Step 3: Add Nextdoor option to push modal

When asset platform is "nextdoor", show "Push to Nextdoor" instead of "Push to Postiz".

Step 4: Commit

git add -A
git commit -m "feat: add Nextdoor Ads API direct integration"

Phase 5: Supporting Pages + Polish

Task 22: Global Asset Library Page

Files:

  • Create: app/(dashboard)/assets/page.tsx

Step 1: Build the page

Same asset gallery component as campaign detail, but fetches all assets across all campaigns. Adds campaign name column/badge. Search input for filtering by caption/hook text.

Step 2: Commit

git add -A
git commit -m "feat: add global asset library page"

Task 23: Trend Reports Page

Files:

  • Create: app/(dashboard)/trends/page.tsx
  • Create: components/trend-report-viewer.tsx

Step 1: Build the page

Lists TrendReport records. Each shows name, date, summary. Click → expands to show the HTML report in an iframe (served via /api/files/...). "Create Campaign from This" button → navigates to /campaigns/new with trend report pre-selected.

Step 2: Commit

git add -A
git commit -m "feat: add trend reports page with HTML viewer"

Task 24: Dashboard Home — Real Data

Files:

  • Modify: app/(dashboard)/page.tsx
  • Create: app/api/stats/route.ts

Step 1: Create stats API route

GET /api/stats — returns:

  • Active campaigns count (status = running or review)
  • Pending review count (assets with status = draft in review campaigns)
  • Published this week count
  • Recent campaigns (last 5)
  • Latest trend report

Step 2: Update dashboard home page

Replace placeholder cards with real data from stats API. Add "New Campaign" button prominently.

Step 3: Commit

git add -A
git commit -m "feat: wire dashboard home to real campaign and asset data"

Task 25: Pipeline Output Scanner

Files:

  • Create: lib/scanner.ts

Step 1: Build the output scanner

When a pipeline run completes (or on-demand), scan the campaign's output directory and create Asset records for every file found:

  • outputs/{campaign}/ads/*.png → type: image
  • outputs/{campaign}/video/*.mp4 → type: video
  • outputs/{campaign}/copy/*.json → type: copy
  • outputs/{campaign}/scripts/*.md → type: script
  • outputs/{campaign}/*.html → type: research
  • outputs/{campaign}/*.md → type: research

Infers platform from filename (instagram_, tiktok_, nextdoor_). Reads dimensions from image metadata. Reads caption/metadata from adjacent JSON files.

Step 2: Integrate with pipeline completion

In lib/claude.ts, call scanOutputDirectory(campaignId, outputPath) when pipeline completes.

Step 3: Commit

git add -A
git commit -m "feat: add pipeline output scanner to auto-populate asset database"

Phase 6: Docker Finalization + Testing

Task 26: Final Docker Configuration

Files:

  • Modify: Dockerfile (finalize)
  • Modify: docker-compose.yml (finalize)
  • Create: scripts/setup.sh

Step 1: Finalize Dockerfile

Ensure it handles:

  • Claude Code CLI installation
  • Playwright Chromium installation
  • Prisma generation
  • Pipeline directory copy
  • Remotion project copy with node_modules

Step 2: Create setup script

#!/bin/bash
# scripts/setup.sh — first-time setup
docker compose up -d
docker compose exec app npx prisma db push
docker compose exec app npx prisma db seed
echo "Dashboard: http://localhost:3000"
echo "Postiz: http://localhost:5000"
echo "Connect your Instagram + TikTok accounts in Postiz"

Step 3: Test full Docker build and startup

Run:

docker compose build
docker compose up -d
bash scripts/setup.sh

Expected: Dashboard at :3000, Postiz at :5000, login works, pages load.

Step 4: Commit

git add -A
git commit -m "feat: finalize Docker setup with one-command startup script"

Task 27: End-to-End Smoke Test

Step 1: Start the full stack

docker compose up -d

Step 2: Log in

Navigate to http://localhost:3000 → login with admin credentials.

Step 3: Create a test campaign

Click "New Campaign" → fill in test data → submit.

Step 4: Launch pipeline (dry run)

Click "Launch Pipeline" → watch agent steps execute in real-time via SSE.

Step 5: Review assets

Navigate to Assets tab → verify images/videos render in gallery → approve a few.

Step 6: Test Claude chat

Navigate to Claude tab → send "make the hook text snarkier" → verify streaming response.

Step 7: Push to Postiz

Select approved assets → Push to Postiz → verify post appears in Postiz queue.

Step 8: Document any issues

Create docs/known-issues.md if anything needs fixing.

Step 9: Commit

git add -A
git commit -m "docs: add smoke test results and known issues"

Summary

Phase Tasks What You Get
1: Scaffold 1-7 Next.js + shadcn + Prisma + Auth + Docker Compose
2: Pipeline 8-13 7 agent skills + Remotion + Claude spawner + Postiz client + file server
3: Campaign UI 14-18 Campaign CRUD + pipeline progress + asset gallery + Claude chat
4: Publishing 19-21 Postiz push flow + queue page + Nextdoor API
5: Polish 22-25 Asset library + trends page + dashboard stats + output scanner
6: Docker 26-27 Final Docker config + setup script + smoke test

Total: 27 tasks across 6 phases.