The Platform

A self-hosted platform that runs a portfolio of AI-powered apps — and delivers changes to them. Designed solo, built spec-first with AI coding agents.

A design-studio mission in the platform console: a staged design spine with review gates, a coverage matrix, rejection rounds carrying binding owner direction, and generated theme propositions.
An earlier capture of the platform console overview: fleet health, month-to-date AI spend against its ceiling, kill-switch state, CI status, and per-repository cards.

Problem

Shipping several small AI-powered products as one engineer means every app re-solves the same problems: AI provider access, cost control, deployment, monitoring, conventions. And LLM APIs bill by usage — one runaway loop in a hobby app can cost real money. The goal: run many small apps without rebuilding infrastructure each time, never let AI spend go unmetered — and get changes from idea to reviewed, running software without hand-carrying each one.

Solution

A personal platform of small single-purpose services — more than thirty repositories, each self-describing, all sharing one version-pinned contracts library and governed by a written log of over a hundred architecture decisions. Every AI call passes through one gateway that alone holds the provider keys, so cost control cannot be bypassed. Every repository is built by a coding agent from a written spec, and a human decides what ships: a change counts as done only when the owner has accepted it on a running review environment, never because an agent said so. Software about running AI, built with AI — in three layers below.

Features

  • Runtime — one AI gateway holding all provider keys, with synchronous budget pre-flight checks and automatic downshift to a free local model near a ceiling
  • Runtime — Claude subscription usage metered as its own provider, and per-call model and effort choice with separate metering per backend
  • Runtime — live platform state streamed over server-sent events; a GPU job queue with VRAM-aware admission for local image and 3D generation
  • Build plane — an agent runner dispatching coding-agent sessions: a subscription-authenticated Codex CLI by default, Claude Code selectable, local-model profiles, and a hosted provider only through the gateway
  • Build plane — cross-repo coordination through a gated demand protocol; every repository adopts the same operational memory, with session files instead of hand-written handoffs and scheduled audits
  • Build plane — a design studio: interview-first missions, design regimes, versioned design systems, binding owner rejection direction and a coverage gate
  • Build plane — a documentation hexagon with a decision index, and a launcher that detects stale builds and rebuilds in one click
  • Delivery plane — task-driven delivery: backlog issue, owner-approved plan, implementation pull request into the development branch only, required checks, a review environment, and owner acceptance before the issue resolves
  • Delivery plane — parked work: an agent waiting on CI, a merge or an owner decision ends its run with a structured wait condition and is resumed by a new run instead of idling
  • Delivery plane — a SonarQube quality gate enforced as a required merge check on the development branch (pilot app), local code measurement, and an AI backlog planner with a preview-then-confirm gate
  • Delivery plane — a ship-clean rule (apps born by the platform carry no platform traces) and a console with a native task-delivery view

Architecture

  1. Owner intent — Harvest · registry · backlog
  2. Factory — task delivery (plan → PR → checks → review)
  3. Demand coordinator
  4. Agent runner — coding agents
  5. Apps
  6. AI gateway — sole key holder
  7. Budget pre-flight · usage over Kafka
  8. Live state feed → console

Tech

  • Java
  • Spring Boot
  • Angular
  • Python
  • Kafka
  • PostgreSQL
  • Docker Compose
  • Server-Sent Events
  • Hexagonal architecture
  • AI coding agents
  • Claude Code
  • Codex
  • Local LLMs
  • SonarQube

Challenges

  • Making cost enforcement impossible to bypass rather than merely discouraged — solved structurally: only the gateway holds provider keys, so there is no path around metering.
  • Keeping dozens of small repositories consistent as a solo engineer — solved with a conventions library, repo templates and a compliance validator.
  • Evolving shared contracts across many consumers without breakage — solved by publishing them as a pinned, versioned package.
  • Coordinating changes that cross repository boundaries when every agent works inside exactly one repo — solved with the demand protocol: requests are files, dispatch is a service, approval is human.
  • Trusting work done by agents — solved by keeping the facts separate: agent exit, tests, checks, review environment and owner acceptance are recorded independently, and none of them alone marks an outcome complete.
  • Not paying for agents to wait — solved by parking: a run that needs CI or a decision ends with a structured wait and a new run picks up from there.

Lessons

  • Boundaries enforced by structure beat boundaries enforced by discipline: a rule the filesystem enforces cannot rot.
  • Spec-first, agent-built development works when the spec is the source of truth and a human holds the review gate.
  • Metering belongs at the choke point, not in every app.
  • "Done" is a claim, not a verdict — the evidence has to come from something other than the thing that did the work.
  • Retire machinery that stopped earning its keep: the earlier mission-style workflow and the app studio are parked in favour of simpler task-driven delivery.

Future work

  • Run the platform hosted rather than local-first — its first product, Planotell, is already live in production
  • Bring more apps from idea to repository through Harvest, the registry, backlog and task delivery
  • A richer live visualization of platform state