This project is archived until I have time to make all the (many) necessary updates 💔.
AI-assisted marketing management platform for agencies — Social Media scheduling, Google Ads management, AI content generation, and an MCP server. Everything managed through the UI, no CLI required.
Stack: Go 1.25.11+ (chi, pgx/v5, goose) · React 19 (Vite, TanStack Router + Query, Tailwind v4) · PostgreSQL 16 · Docker Compose
Development is paused (since June 2026). This is alpha software and is not safe for production use.
The codebase builds and its test suites pass, but it is not ready to be deployed or to manage real client accounts. Known gaps:
- Tenant isolation is broken. The seeded
ownerandmanagerroles carryview-any:tenant, which bypasses the tenant check, so a tenant user can reach other tenants' data. Several endpoints also trust IDs without scoping them to the caller's tenant. - No deployable image. There is no Dockerfile;
docker-compose.ymlonly provides Postgres for local development and migrations must be run by hand. - Integrations are partial. Meta (Facebook Pages and Instagram, Graph API v18) and Google Ads are implemented. LinkedIn and X are not. Storage (S3/R2), email (Resend/Brevo) and Sentry exist only as settings forms with no backing code.
- Google Ads adjustments are unfinished. Approving a suggested adjustment only changes its status and does not apply it; auto-apply mode mutates campaigns without transactions or rollback, and the scheduler can run a job twice.
- Credentials are encrypted only with
APP_ENV=production, and Meta page tokens are stored unencrypted. - Frontend needs hardening. AI-generated markdown is rendered without sanitization, there is no logout action, and PDF export calls an endpoint the backend does not provide.
Issues and pull requests are welcome, but responses may be slow while the project is paused.
Go Backend (port 8080 — SPA embedded in binary for production)
├── GET /health health check + setup detection
├── POST /setup first-run admin account creation
├── /auth/* JWT login/refresh/logout, OAuth (Google Ads, Meta)
├── /admin/* REST API — users, roles, tenants, posts,
│ campaigns, alerts, reports, integrations
├── GET|DELETE /api/media/{tenant}/{id} media serve & delete
├── POST /api/media/{tenant}/{postId} media upload (JWT-gated)
├── POST /ai/generate AI content (SSE stream, JWT-gated)
└── /mcp MCP endpoint (Streamable HTTP, API-key auth)
React SPA (Vite dev server :5174; in dev the backend at :8181 proxies non-API routes to it — access the app at :8181)
├── /login /setup public pages
├── /tenants/new onboarding
├── /[tenant]/social post planner (calendar + drawers)
├── /[tenant]/social/drafts draft management
├── /[tenant]/campaigns/* Google Ads live & history
├── /[tenant]/alerts monitoring alerts
├── /[tenant]/reports AI reports
└── /settings/* integrations, users, roles
Credentials are stored in the integrations table (encrypted). Connecting in the UI unlocks features:
| Category | Providers |
|---|---|
| LLM | OpenAI, Gemini, Kimi, Groq, Claude (Anthropic) |
| Storage | S3, R2 |
| Ads (OAuth2) | Google Ads |
| Social (OAuth2) | Meta (Instagram) |
| Resend, Brevo | |
| Tracking | Sentry |
Prerequisites: Go 1.25.11+, Bun 1.x, Docker, air, goose, golangci-lint, sqlc
docker compose up -d
cp backend/.env.example backend/.env # set DATABASE_URL + JWT_SECRET (openssl rand -hex 32)
cd frontend && bun install && cd ..
make migrate/up
make dev/bundleOpen http://localhost:8181 — the setup wizard creates the first admin account.
Development
make dev/backend Go backend (air hot-reload; proxies the SPA, serve at :8181)
make dev/frontend React/Vite dev server (:5174)
make dev/bundle All processes in parallel (recommended) — open http://localhost:8181
Build
make build Build frontend + Go binary
Migrations
make migrate/up Apply all pending migrations
make migrate/down Rollback last migration
make migrate/status Show migration state
make migrate/create Interactive: create a new migration file
Testing
make test/backend Go tests (all)
make test/backend/unit Go unit tests with race detector
make test/backend/integration Integration tests (requires Postgres)
make test/backend/cover Coverage report (opens browser)
make smoke Smoke tests against localhost:8080
make smoke/remote URL=… Smoke tests against a remote URL
make test/frontend Vitest unit + browser component tests
make test/e2e Playwright E2E tests (requires running stack)
make test/e2e/ui Playwright interactive UI mode
make test/e2e/report Open last Playwright HTML report
Quality
make lint golangci-lint + ESLint/Prettier
make sqlc Regenerate sqlc query bindings
| Layer | Command | What it covers |
|---|---|---|
| Unit | make test/backend/unit |
Crypto (AES-256-GCM), JWT, password hashing, middleware, HTTP handlers |
| Integration | make test/backend/integration |
Repository layer against embedded Postgres (overall backend coverage is about 27%) |
| Smoke | make smoke |
7 contract tests (health, auth endpoints, protected routes, MCP) |
Build tags: //go:build integration and //go:build smoke.
| Layer | Command | What it covers |
|---|---|---|
| API specs | make test/frontend |
159 Vitest tests — full CRUD for every API client module |
| Component | make test/frontend |
99 browser component tests via Playwright + Vitest |
| E2E | make test/e2e |
10 Playwright tests — auth flows, protected routes, post creation golden path |
E2E tests require a running stack and credentials:
E2E_USER_EMAIL=admin@example.com E2E_USER_PASSWORD=yourpassword make test/e2eTo test the first-run setup flow against a fresh DB: E2E_FRESH_DB=true make test/e2e.
ci.yml — every push and PR to main: lint → build → unit tests → integration tests → security scan → frontend quality → frontend tests → frontend build → smoke tests → gate job.
e2e.yml — push to main and manual dispatch only: installs the frontend, then runs the Playwright E2E suite. The React specs are self-contained — Playwright boots the Vite dev server and each spec stubs its backend routes via page.route, so no Postgres/backend/test-user is needed. Playwright report uploaded as artifact on failure.