commit 3abe46fba644bbc1732cd289ada1d9d4f25c9b7d Author: Trey t Date: Mon Mar 23 11:50:39 2026 -0500 feat: scaffold Next.js 15 project with TypeScript and Tailwind diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 0000000..e1881b2 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,14 @@ +{ + "permissions": { + "allow": [ + "WebFetch(domain:www.youtube.com)", + "Bash(yt-dlp:*)", + "Bash(grep -v '^ *$')", + "Bash(ls -la /private/tmp/claude-501/-Users-treyt-Desktop-claude-marketing/fff1037b-284c-4767-98c1-36d3ea219e20/tasks/*.output)", + "WebSearch", + "WebFetch(domain:github.com)", + "WebFetch(domain:developer.nextdoor.com)", + "WebFetch(domain:docs.postiz.com)" + ] + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5ef6a52 --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..8bd0e39 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,5 @@ + +# This is NOT the Next.js you know + +This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices. + diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..43c994c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..e215bc4 --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/app/favicon.ico b/app/favicon.ico new file mode 100644 index 0000000..718d6fe Binary files /dev/null and b/app/favicon.ico differ diff --git a/app/globals.css b/app/globals.css new file mode 100644 index 0000000..a2dc41e --- /dev/null +++ b/app/globals.css @@ -0,0 +1,26 @@ +@import "tailwindcss"; + +:root { + --background: #ffffff; + --foreground: #171717; +} + +@theme inline { + --color-background: var(--background); + --color-foreground: var(--foreground); + --font-sans: var(--font-geist-sans); + --font-mono: var(--font-geist-mono); +} + +@media (prefers-color-scheme: dark) { + :root { + --background: #0a0a0a; + --foreground: #ededed; + } +} + +body { + background: var(--background); + color: var(--foreground); + font-family: Arial, Helvetica, sans-serif; +} diff --git a/app/layout.tsx b/app/layout.tsx new file mode 100644 index 0000000..976eb90 --- /dev/null +++ b/app/layout.tsx @@ -0,0 +1,33 @@ +import type { Metadata } from "next"; +import { Geist, Geist_Mono } from "next/font/google"; +import "./globals.css"; + +const geistSans = Geist({ + variable: "--font-geist-sans", + subsets: ["latin"], +}); + +const geistMono = Geist_Mono({ + variable: "--font-geist-mono", + subsets: ["latin"], +}); + +export const metadata: Metadata = { + title: "Create Next App", + description: "Generated by create next app", +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + {children} + + ); +} diff --git a/app/page.tsx b/app/page.tsx new file mode 100644 index 0000000..3f36f7c --- /dev/null +++ b/app/page.tsx @@ -0,0 +1,65 @@ +import Image from "next/image"; + +export default function Home() { + return ( +
+
+ Next.js logo +
+

+ To get started, edit the page.tsx file. +

+

+ Looking for a starting point or more instructions? Head over to{" "} + + Templates + {" "} + or the{" "} + + Learning + {" "} + center. +

+
+
+ + Vercel logomark + Deploy Now + + + Documentation + +
+
+
+ ); +} diff --git a/docs/plans/2026-03-23-marketing-command-center.md b/docs/plans/2026-03-23-marketing-command-center.md new file mode 100644 index 0000000..dd910af --- /dev/null +++ b/docs/plans/2026-03-23-marketing-command-center.md @@ -0,0 +1,1012 @@ +# 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: +```bash +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** + +```bash +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: +```bash +npx shadcn@latest init -d +``` + +Expected: `components.json` created, `lib/utils.ts` created + +**Step 2: Add core components we'll need** + +Run: +```bash +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** + +```bash +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: +```bash +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`: +```typescript +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** + +```bash +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`: +```typescript +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`: +```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** + +```bash +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** + +```bash +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** + +```bash +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** + +```bash +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** + +```bash +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** + +```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** + +```bash +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: +```bash +claude -p "What skills are available?" --allowedTools "Read,Grep,Glob" +``` +Expected: All 7 skills listed + +**Step 3: Commit** + +```bash +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: +```bash +cd pipeline +npx create-video@latest remotion-ad --template blank +``` + +Expected: Remotion project created in `pipeline/remotion-ad/` + +**Step 2: Install Remotion deps** + +Run: +```bash +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** + +```bash +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`: +```typescript +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** + +```bash +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** + +```bash +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** + +```bash +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** + +```bash +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** + +```bash +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** + +```bash +git add -A +git commit -m "feat: add campaign pipeline progress with real-time SSE updates" +``` + +--- + +### Task 17: Campaign Detail — Asset Gallery Tab + +**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 `