All work
Own product · live, pre-revenue

MarketingOS

Multi-tenant AI software that writes, moderates and publishes a small business's social posts.

Role
Sole engineer
Year
2026
Stack
Next.js 16, Supabase Postgres and RLS, pg_cron, Claude, fal.ai, Remotion (built, dormant), Satori, Stripe, Model Context Protocol
marketingos.studio
Demo dataHeld posts wait with a plain-English reason. One approval publishes through the app's single publish path, here to its mock provider. The holds are seeded for a fictional brand.
API route handlersCounted in the repo · source
74
Row Level Security policy statements across 31 migrationsCounted in the repo · source
44
MCP tools that let an outside model drive an account through the same gatesCounted in the repo · source
6

The problem

A small business needs a steady stream of on-brand posts and has no one to write them. Tools that generate content will publish anything, including an off-brand or risky post the owner never saw.

What I built

  1. 01An autonomy policy engine as a pure function, modeled on Claude Code's permission system: blocking guardrails first, then approval-forcing ones, then the most cautious matching policy wins.
  2. 02One publish path with an atomic claim, so overlapping cron runs or retries can never double-publish.
  3. 03A reserve, commit and refund credit ledger in atomic Postgres functions, with the Stripe webhook as the source of truth and an idempotent de-dupe table.
  4. 04A security audit shipped as a migration: a policy with no WITH CHECK that let a user move into another organization, and credit functions any signed-in user could call.
  5. 05Moderation that fails safe: any classifier error returns 'flagged' so a person looks at it.
  6. 06An MCP server with hashed per-organization keys, so Claude or any MCP client can run the account through the same autonomy and credit gates.
  7. 07Brand media rendered from code: Remotion reels driven by model-written JSON and Satori graphics for posts and carousels.

More screens

The Create page on a phone: goal cards, the prompt box and a tab bar with a raised Create button
Demo dataOn a phone: a tab bar with a raised Create button and a live Review badge.
Demo dataA vertical reel rendered from JSON by the same Remotion composition the app sends to Lambda. Reels are built and dormant in production.
A 4:5 promo graphic for a fictional plant shop: a gold pill, the headline 'Two ferns, one price' and a Visit us Saturday button
Demo dataA promo graphic from the app's Satori templates: a brand kit and four text fields in, a post out. The brand is fictional.
A 4:5 tip graphic in the same brand kit: 'Water when the top inch is dry'
Demo dataA tip template in the same brand kit.
marketingos.studio
Demo dataOne draft, previewed per network as you edit, with the 280-character limit on X counted live.
marketingos.studio
Autonomy settings: review everything, review by exception or autopilot, with per-platform overrides and the note that the most cautious setting always wins
Demo dataAutonomy per platform. The most cautious setting always wins.

Decisions

Publishing behind a provider interface

The app depends only on a PublishingProvider with a mock default. Per-profile fees from some publishing vendors, about $15 per customer a month, would have taken more than 30% of the $49 Starter plan it was first priced against, and about half of today's $29 Starter. So the vendor has to be swappable.

Autonomy is what the plans price

Basic AI is available on every tier. Higher tiers allow more autonomy, because that is the part a business pays to trust.

Not claimed

  • Only Instagram publishing was verified end to end. Other networks are not claimed.
  • No customers or revenue yet. Stripe runs in live mode.
  • Video reels are built and dormant until render keys are set.
  • Scheduling for a future date is built. In production only publish-now is verified.
  • The held posts in these screens are seeded. Approving one runs the real publish path against the mock provider, so nothing is posted.

Links