Last Updated: 2026-03-15 Estimated Duration: 10–12 weeks (solo developer pace)
Phase 1: Foundation (Week 1–2)
1.1 Project Scaffolding
- Create
apps/content-engine/Worker (Hono + TypeScript) - Add to
pnpm-workspace.yamlandturbo.json - Configure
wrangler.tomlwith Queue bindings, Secrets (CONTENT_ENGINE_DATABASE_URL,GATEWAY_SECRET) - Add Gateway proxy route:
/content/*→ Content Engine Worker (newCONTENT_ENGINE_SERVICEbinding in gatewaywrangler.toml) - Register
contentas a service incore-types/src/service.ts
1.2 Database Schema
- Create Neon PostgreSQL database:
content-engine-db - Write Drizzle schema in
src/db/schema.tsand generate migration viadrizzle-kit generate:social_connectionstablecampaignstablelabelstablecontent_slotstableslot_targetstablecontent_slot_labels(junction table)recurring_schedulestablepublish_logstable
- Create indexes for
tenantId,scheduledAt,status
1.3 Core Types & Shared Package
- Add content engine types to
packages/core-types/:ContentSlot,SlotTarget,SocialConnection,Campaign,Label,RecurringSchedule- Status enums:
SlotStatus,PublishStatus,ConnectionStatus,CampaignStatus
- Add PBAC permission strings to
packages/core-access/:content:connections.read,content:connections.writecontent:campaigns.read,content:campaigns.writecontent:labels.read,content:labels.writecontent:slots.read,content:slots.write,content:slots.approvecontent:recurring.read,content:recurring.write
Phase 2: Social Connections (Week 2–3)
2.1 OAuth Connectors
- Implement
PlatformAdapterinterface insrc/adapters/ -
twitter.adapter.ts— Twitter/X OAuth 2.0 PKCE flow -
meta.adapter.ts— Meta Graph API (Instagram + Facebook Pages) -
linkedin.adapter.ts— LinkedIn OAuth 2.0 flow - Adapter registry:
getAdapter(platform: SocialPlatform): PlatformAdapter
2.2 Connection API
-
GET /content/connections— list connections -
POST /content/connections/:platform/authorize— start OAuth -
POST /content/connections/:platform/callback— complete OAuth -
DELETE /content/connections/:connectionId— disconnect
2.3 Token Security
- Implement AES-256-GCM encryption/decryption utility (
src/lib/crypto.ts) - Store encrypted tokens in D1
- Cron trigger: daily token health check + proactive refresh
Phase 3: Content Calendar — CRUD (Week 3–5)
3.1 Campaigns & Labels API
- Full CRUD for campaigns
- Full CRUD for labels
- Many-to-many label assignment on slots
3.2 Content Slots API
-
POST /content/slots— create slot with targets -
GET /content/slots?from=&to=— calendar query (optimized for week/month views) -
PATCH /content/slots/:slotId— update (draft only) -
DELETE /content/slots/:slotId— delete (draft/scheduled only) -
POST /content/slots/:slotId/reschedule— drag-and-drop support
3.3 Approval Workflow
-
POST /content/slots/:slotId/submit-review—draft → pending_review -
POST /content/slots/:slotId/approve—pending_review → approved → scheduled -
POST /content/slots/:slotId/reject—pending_review → draft - State machine validation middleware
Phase 4: Publishing Engine (Week 5–7)
4.1 Scheduler
- Cron Trigger (every 1 minute): find due slots
WHERE status='scheduled' AND scheduledAt <= NOW() - Enqueue each due slot into Cloudflare Queue
content-publish-queue
4.2 Publisher Worker (Queue Consumer)
- Consume from
content-publish-queue - For each SlotTarget:
- Decrypt the connection's OAuth token
- Upload media via platform adapter
- Publish via platform adapter
- Update SlotTarget status (
published/failed)
- Update ContentSlot overall status based on target results
4.3 Retry Logic
- Failed SlotTargets → re-enqueue with delay (1m → 5m → 15m)
- Max 3 retries
- After final failure → mark permanently failed, emit
content.failedevent
4.4 Publish Logs
- Log every publish attempt to
publish_logstable -
GET /content/slots/:slotId/logsendpoint
Phase 5: Recurring Schedules (Week 7–8)
5.1 Recurring API
- Full CRUD for recurring schedules
- Pause / Resume endpoints
5.2 Slot Generation Job
- Daily cron trigger: generate content slots 7 days in advance
- Parse cron expression → calculate next N occurrence dates
- Create ContentSlots from template
- Respect
autoScheduleflag (skip →draft, auto →scheduled)
Phase 6: Cross-Service Integration (Week 8–9)
6.1 Event Bus — Producer
- Emit
content.scheduledevent when slot becomes scheduled - Emit
content.publishedevent on successful publish (with external URLs) - Emit
content.failedevent on permanent failure
6.2 Event Bus — Consumer (Optional)
- Listen for
blog.publishedevent (optional cross-service integration) - Auto-create content slots from blog post data
- Respect tenant's auto-promote settings
Phase 7: MCP Agent Control Server (Week 9–10)
7.1 MCP Server Scaffolding
- Create
packages/content-engine-mcp/package (Node.js + TypeScript) - Configure MCP SDK (
@modelcontextprotocol/sdk) - Set up dual transport: SSE (for remote agents) + stdio (for local agents)
- Configure API Key authentication for agent connections
7.2 MCP Tool Implementation
- Calendar Tools:
schedule_content,reschedule_content,cancel_content,get_calendar,get_slot_details - Connection Tools:
list_connections,check_connection_health - Campaign Tools:
create_campaign,list_campaigns - Publishing Tools:
get_publish_status,retry_failed_publish - Recurring Tools:
create_recurring_schedule,list_recurring_schedules - Bulk Tools:
bulk_schedule,bulk_action
7.3 MCP Resources
-
content://calendar/today— today's scheduled content -
content://calendar/week— this week's calendar -
content://connections— connected accounts and health -
content://campaigns/active— active campaigns -
content://stats/overview— quick stats -
content://queue/pending— publish queue state
7.4 Agent Safety & Auth
- PBAC permission mapping for each MCP tool
-
agentIdtracking in audit trail - Rate limits: 50 slots/bulk call, 200 slots/hour/agent
-
dryRunmode for all write tools -
autoApprovedefaults tofalse
7.5 Agent Integration Testing
- Test with Claude Desktop (stdio transport)
- Test with custom agent (SSE transport)
- Verify permission enforcement per tool
- Test bulk operations within rate limits
Phase 8: Dashboard UI (Week 10–12)
8.1 Calendar View
- Week / Month / Day views with content slots
- Color-coded by campaign / platform
- Drag-and-drop rescheduling
- Status badges (draft, scheduled, published, failed)
8.2 Connection Management
- OAuth connect/disconnect flow
- Connection health status display
8.3 Content Slot Editor
- Rich caption editor with per-platform preview
- Media attachment (images/videos from Media Service)
- Platform selector with character count validation
- Approval workflow UI (submit, approve, reject with comments)
8.4 Recurring Schedule Manager
- Create/edit recurring patterns
- Preview upcoming generated slots
Phase 9: Hardening & Polish (Ongoing)
- Rate limit compliance per platform
- Billing enforcement:
checkLimit()for max slots and max connections - Connection health monitoring alerts
- Comprehensive error handling and user-friendly error messages
- Integration tests for publish pipeline
- Load testing for calendar queries at scale
Dependency Order Summary
Phase 1 (Foundation) ──▶ Phase 2 (Connections) ──▶ Phase 3 (Calendar)
│
▼
Phase 5 (Recurring) ◀── Phase 4 (Publishing) ◀───────────┘
│
▼
Phase 6 (Events) ──▶ Phase 7 (MCP) ──▶ Phase 8 (UI) ──▶ Phase 9 (Hardening)Required Environment Secrets
| Secret | Purpose |
|---|---|
SOCIAL_TOKEN_KEY |
AES-256 encryption key for OAuth tokens |
TWITTER_CLIENT_ID |
Twitter OAuth2 app client ID |
TWITTER_CLIENT_SECRET |
Twitter OAuth2 app client secret |
META_APP_ID |
Meta (Instagram/Facebook) app ID |
META_APP_SECRET |
Meta app secret |
LINKEDIN_CLIENT_ID |
LinkedIn OAuth2 client ID |
LINKEDIN_CLIENT_SECRET |
LinkedIn OAuth2 client secret |
GATEWAY_KEY |
Inter-service authentication key |