A self-hosted automation service that takes marketing ideas, generates branded assets via Google Pomelli (browser automation), and posts to X/Twitter with human-in-the-loop approval.
Stack: Bun + Hono + HTMX + Playwright + X API v2 + SQLite Deploy: Fly.io (Docker + persistent volume)
Idea → Pomelli (brand-aware asset generation) → Review/Approve → Post on X
# Install dependencies
bun install
# Copy env and configure
cp .env.example .env
# Start dev server
bun run devDashboard loads at http://localhost:8080.
| Command | Description |
|---|---|
bun run dev |
Start dev server with watch mode |
bun run start |
Start production server |
bun run check |
Typecheck + lint + test |
bun run test |
Run tests |
bun run lint |
Run Biome linter |
┌──────────────────────────────────────────────────┐
│ Fly.io (Docker) │
│ │
│ ┌───────────┐ ┌────────────┐ ┌───────────┐ │
│ │ Web UI / │──▶│ Pomelli │──▶│ X API │ │
│ │ API │ │ Playwright│ │ Poster │ │
│ │ (Hono) │ │ Automation│ │ (v2) │ │
│ └───────────┘ └────────────┘ └───────────┘ │
│ │ │ │ │
│ └────────┬───────┘────────────────┘ │
│ ▼ │
│ ┌────────────┐ │
│ │ SQLite DB │ │
│ └────────────┘ │
└──────────────────────────────────────────────────┘
- Dashboard (
src/routes/pages.tsx) — Hono JSX + HTMX server-rendered UI with PicoCSS - API (
src/routes/api.ts) — Queue CRUD, settings, history endpoints - Pomelli Service (
src/services/pomelli.ts) — Playwright browser automation with persistent context, concurrency lock, debug screenshots - Twitter Service (
src/services/twitter.ts) — Media upload (v1.1) + tweet creation (v2) - Scheduler (
src/services/scheduler.ts) — Croner cron job, posts approved items every minute - Auth (
src/routes/auth.ts) — Pomelli session health check + cookie import
POST /api/ideas — Submit new idea (triggers Pomelli async)
GET /api/queue — List pending review
POST /api/queue/:id/approve — Approve and post
POST /api/queue/:id/edit — Update caption
DELETE /api/queue/:id — Reject/delete
GET /api/history — Posted content log
POST /api/settings — Update config
POST /api/auth/pomelli — Cookie import
GET /api/auth/status — Session health
GET /health — Health check
fly apps create pomelli-x-flywheel
fly volumes create pomelli_data --region ord --size 1
fly secrets set X_API_KEY=... X_API_SECRET=... X_ACCESS_TOKEN=... X_ACCESS_TOKEN_SECRET=...
fly deployThis project was built in a single session using Claude Code with a team of 4 parallel AI agents, orchestrated from a plan document.
-
Planning — A detailed PRD (
prd.md) was written first, specifying the full architecture, API endpoints, database schema, deployment config, and component responsibilities. This was then broken into an implementation plan with 18 tasks across 4 phases, with a dependency graph. -
Phase 0: Foundation — The team lead agent built the project scaffolding (package.json, tsconfig, biome config) and core infrastructure (config, database with query helpers, Hono server skeleton). This was done first since all other work depended on it.
-
Phase 1: Parallel Development — Three specialist agents were spawned simultaneously using Claude Code's
TeamCreatesystem:xpost— Built the Twitter posting service and schedulerpomelli— Built the Playwright browser automation and auth routesdashboard— Built all UI views, HTMX components, and API routes
Each agent received the full project context (existing file structure, interfaces, config shape) and worked independently on their domain. All three ran in parallel, producing 10+ files concurrently.
-
Phase 2: Integration — The team lead wired all routes into the server entry point, added the Pomelli async pipeline (idea submission triggers background generation), connected the scheduler, added optional basic auth middleware, and created the Dockerfile + Fly.io config.
-
Verification — Ran
bun run check(typecheck + lint + tests). Fixed lint issues withbiome check --write, resolved non-null assertion warnings, and ensured all 43 tests passed across 5 test files.
team-lead: [Foundation] ──────── [Integration + Deploy]
xpost: wait → [Twitter service + tests + scheduler]
pomelli: wait → [Pomelli automation + auth + tests]
dashboard: wait → [Layout + API + pages + components + tests]
15:23:27 package.json created (project scaffolding begins)
15:23:50 config.ts, db.ts, server.ts (foundation complete)
── 3 agents spawned in parallel ──
15:25:40 twitter.ts (xpost agent)
15:25:58 scheduler.ts (xpost agent)
15:26:18 layout.tsx (dashboard agent)
15:26:21 twitter.test.ts (xpost agent)
15:26:23 scheduler.test.ts (xpost agent)
15:26:37 queue-list.tsx (dashboard agent)
15:26:40 history-list.tsx (dashboard agent)
15:27:26 api.test.ts (dashboard agent)
15:27:57 auth.test.ts (pomelli agent)
15:28:03 pages.tsx (dashboard agent)
15:28:24 post-card.tsx (dashboard agent)
15:28:42 api.ts (final version) (dashboard agent)
15:28:45 Dockerfile (team lead - integration)
15:28:49 fly.toml (team lead - integration)
15:29:13 server.ts (wired) (team lead - integration)
15:30:17 pomelli.ts (final) (pomelli agent)
15:30:38 pomelli.test.ts (final) (pomelli agent)
15:31:21 bun run check — all 43 tests pass ✓
- 4 agents working in parallel
- 29 files created
- 43 tests passing
- 0 lint errors, 0 type errors
- ~8 minutes wall-clock time from first file to all checks passing