Live·2025 – present

Focal

A Nigeria-first operating system for creative businesses — booking, proposals, payments and delivery, in one place.

Solo founder & full-stack engineer

Live at runonfocal.com and in active development. Formerly CreativeOS — renamed in September 2026 because the old name clashed with existing products.

Stack

  • Next.js 16
  • React 19
  • TypeScript
  • Drizzle ORM
  • Neon Postgres
  • Better Auth
  • Paystack
  • Cloudflare R2 · Stream · Workers
  • Vercel AI SDK · AI Gateway
  • Upstash Redis · QStash
  • Google Calendar API
  • Resend
  • PostHog
  • PWA
Focal dashboard — pipeline and money totals, Studio Copilot, cashflow, and what needs attention

The problem

Freelancers and small creative studios in Nigeria run their businesses across WhatsApp, Instagram DMs, Google Drive and spreadsheets. Proposals get lost in chat, approvals are verbal (and unenforceable), invoicing is manual, and finished work goes out as a Drive link with nothing tying it to payment.

The tools that solve this abroad (HoneyBook, Bonsai, Dubsado) assume US/EU payment rails, tax rules, and a client who will happily create an account. None of that fits the Nigerian market.

Constraints that shaped it

Clients won't sign up. Any flow that requires the client to create an account dies on arrival — approving, paying and downloading all had to work with zero client login while still producing a legally meaningful record.

Clients live on WhatsApp, on budget Android phones over patchy 4G. Every client-facing page is server-rendered so links preview properly in WhatsApp, and the approval page has to stay under 1 MB.

Money is local. Invoicing had to speak naira, VAT and TIN, and settle through Paystack — not Stripe.

Multi-tenant from day one. Every studio's data must be strictly isolated, enforced at the database layer, not just in application code.

Approach & architecture

The spine is one client workflow — Lead → Quoted → Approved → In Progress → Delivered → Paid — modelled as explicit stages backed by a stage-event log, so the whole business is queryable and auditable. Studios work it as a list or a drag-and-drop board.

Client approval happens on a no-login page opened from WhatsApp. Each approval writes a record — timestamp, IP, user agent, a hash of the exact document and an email echo — inside a single database transaction, giving the studio a defensible record without ever asking the client to register.

Tenant isolation is enforced twice: every query goes through a tenant-scoped repository layer, and Postgres row-level security sits behind it as a backstop. CI runs "forgotten filter" tests as the restricted database role, so a query that skips the tenant scope fails the build instead of leaking data.

Focal pipeline board — Lead, Quoted, Approved, In Progress, Delivered and Paid, each with a naira total
The pipeline as a board: six fixed stages with running ₦ totals, and cards that age from the day they really moved.

Money on local rails

Clients pay deposits and invoices online through Paystack split payments: the money settles straight into the studio's own subaccount, so the platform never holds funds. On the free plan a 1% fee comes out of the split — never added on top of what the client was quoted — and paid plans waive it. Money is integer kobo end to end.

Retainers bill themselves: a studio marks an invoice as repeating, the client consents once, and a scheduled job charges the saved card each cycle — with retries, notifications, and pause, skip and cancel controls. Studio subscriptions (Free, Pro, Agency) run on the same rails.

A proposal in the Afterhours theme — three packages with one chosen, and a sticky total with Approve and book
The redesigned client proposal, rolling out now: pick a package, see the true total and today's deposit, approve — no account needed.

From booking to delivery

A public booking page takes deposits and checks the studio's Google Calendar for clashes; calendar sync runs both ways over Google's push webhooks.

Every project gets a no-login client portal: a timeline of where things stand, the one thing the client needs to do next, and inline payment. Finished work is delivered there too — uploaded in resumable chunks to private Cloudflare R2 storage, previewed with watermarks burned in on the server (Cloudflare Stream for video, low-bitrate tagged previews for audio), and unlocked only once the client has approved and paid. Downloads use short-lived signed URLs, and a Cloudflare Worker streams "Download all" as a zip.

Paid studios can white-label all of it on their own domain. Domains are provisioned through Vercel's API, and an incoming host only resolves to a studio through a verified domain record — never on the Host header alone.

The no-login client portal — project timeline with editing progress, payments, and a WhatsApp contact
One link per project: where things stand, what the client owes, and nothing they need to sign up for.
A client's delivered gallery in Focal — unlocked wedding photos with Download all and Share with guests
The same portal delivers the work: watermarked previews until the client approves and pays, then everything unlocks for download.

An assistant that asks first

Studio Copilot answers questions about the business — revenue trends, collection rate, overdue invoices, what's coming up — and drafts proposals, invoices and client messages. It has ten read tools and ten write tools, and every write comes back as a proposed action the studio confirms before anything changes.

The workspace ID is fixed on the server before the model runs, never a tool input, so no prompt can point Copilot at another studio's data. It runs through the Vercel AI SDK and AI Gateway: a small model handles routing and reads, and a stronger one is reserved for writing.

Studio Copilot answering a revenue question with a trend chart and a top-clients chart

Trade-offs

No-login access means I traded classic account-based identity for a link-plus-audit-trail model: unguessable 128-bit links with expiry and revocation, an optional PIN on the portal, and a record of every approval. That took careful thought about link security and non-repudiation, but it was the only design the market would actually adopt.

Row-level security adds complexity to every migration and query path, and makes some queries harder to write — accepted deliberately, because a single cross-tenant data leak would be fatal for a multi-studio product.

The pipeline is fixed: six stages, no custom columns, even on the board view. Configurable boards are where tools like Dubsado lose people, and Focal's users want an opinionated flow, not a project-management tool.

Building on Paystack (not Stripe) narrows the platform to Nigeria for now, but that focus is the product's entire reason to exist.

Where it stands

Focal is live and is my most active project: 2,100+ commits, 166 merged pull requests, 55 database tables across 50+ hand-reviewed migrations, and around 2,000 automated tests.

It's production-hardened the unglamorous way: a per-request nonce CSP, passkeys and authenticator-app 2FA, bot protection on sign-up and the AI route, PostHog analytics and error tracking with source maps, and nightly encrypted database backups with a monthly automated restore test. It installs as a PWA, so studios can run it like a native app on cheap Android hardware.

Right now I'm rebuilding the proposal builder into a themed, block-based document editor that works as well on a phone as on a desktop, with on-device face detection so a cropped photo never cuts off a face. It's the piece I'm proudest of — not a clone of an existing app, but a product designed around a market the existing tools ignore.

Next

SEO Content AI