1013 lines
28 KiB
Markdown
1013 lines
28 KiB
Markdown
# 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 `<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**
|
||
|
||
```bash
|
||
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**
|
||
|
||
```bash
|
||
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**
|
||
|
||
```bash
|
||
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**
|
||
|
||
```bash
|
||
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**
|
||
|
||
```bash
|
||
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**
|
||
|
||
```bash
|
||
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**
|
||
|
||
```bash
|
||
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**
|
||
|
||
```bash
|
||
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**
|
||
|
||
```bash
|
||
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**
|
||
|
||
```bash
|
||
#!/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:
|
||
```bash
|
||
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**
|
||
|
||
```bash
|
||
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**
|
||
|
||
```bash
|
||
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**
|
||
|
||
```bash
|
||
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.**
|