Skip to content
WorkExperienceAboutContact
Request my CVOpen to work

StillKoi pond

Layer some sounds while you read

Sounds from StillKoi →

Name More!

Name an animal. The rarer, the better.

  • lion
  • elephant
  • giraffe
  • axolotl98

Open the game →

To do

  • Build my own OS
  • Ship my own products
  • Find my next team
  • More mint tea

Agency Ops

Agency Ops

DeployedSole engineer

OverviewWhat it replacesProductFinance, calendar, clientsEngineeringPermissions, portal, moneyDecisionsTrade-offs and testsNext projectStillKoi →

Architecture

One model, one deployable

A single full-stack Nuxt application on PostgreSQL. Every route, page and navigation item consults the same permission policy, and every request body is validated against shared Zod contracts.

architecture / overview

Nuxt UI

Interfaces

  • Staff workspace
  • Client portal
  • ⌘K command palette
  • Role-aware navigation
→

Nitro

API

  • Central permissions
  • Zod contracts
  • Transactions
  • Audit history
→

PostgreSQL · Drizzle

Data

  • Relational model
  • Versioned migrations
  • Integer-cent money
  • Soft deletion

Integrations

Services

  • Stripe webhooks
  • Email + PDFs
  • Scheduled jobs
  • File uploads

Docker Compose with the app, PostgreSQL and Caddy · GitHub Actions running unit tests and a real-PostgreSQL integration suite

Authorization

One permission model, enforced everywhere

With every API route touching client data, money or staff records, one forgotten check is all it takes to leak something. So permissions are not written route by route. A single policy defines who can do what, and the same policy is used by the server middleware, the client-side route guards and the navigation that decides what each person even sees.

Global features are the easy place to leak data, so they are built around the policy too. Search and the calendar pull from many domains, so each data provider declares the permission area it belongs to, and aggregation only queries what the current user is allowed to read.

  • ↳

    Invite-only accounts

    Better Auth with admin and member roles, invitations instead of open sign-up, and optional TOTP two-factor authentication.

  • ↳

    Audit trail

    Business records are soft-deleted and their history is kept, so operational evidence is never silently erased.

  • ↳

    Abuse limits

    Uploads and public intake forms have explicit size and rate limits.

Client portal

Clients see their work, and nothing else

Clients sign in to the portal through magic links. Tokens are stored only as hashes and work once. A portal session is scoped to exactly one client, so every query is bound to that client before it runs.

When a client asks for something that belongs to another client, the API returns 404, not 403, so the response doesn’t even confirm that the resource exists. Integration tests try to cross that boundary deliberately to prove it holds.

  • ↳

    Review & approval

    Clients review design boards and approve work in the portal instead of in email threads.

  • ↳

    Shared, but bounded

    Projects, boards and invoices are exposed to the portal through dedicated routes, never the staff API.

Money & workflows

State changes that can’t half-happen

Money is stored as integer cents throughout, so totals, tax and payments never drift through floating-point rounding. Workflows that touch several records, such as turning a quote into an invoice or moving tasks, run inside database transactions, so a failure leaves nothing half-written.

Stripe webhooks verify their signatures and are idempotent, so a retried event never records a payment twice. Recurring invoices are drafted and reminders sent by scheduled jobs, which keeps billing running without anyone having to remember it.

  • ↳

    Task dependencies

    Tasks can depend on each other, and adding a dependency runs a graph traversal that rejects cycles, so the project plan stays valid under any edit.

  • ↳

    Delivery

    Projects with milestones, list, board and timeline views, time tracking with approvals, and leave management.

  • ↳

    Reporting

    Profitability, utilization, capacity, forecasting and tax reports, built on logged time, cost rates and invoices.