Soma, for people and their agents
I built Soma to bring workout planning, logging, and training readiness into one app. Then I gave coding agents a way to work with the same training data, and built a model-powered workout builder inside the product.
Open Soma| My role | Product design and full-stack development |
|---|---|
| Built with | Next.js, TypeScript, Prisma, PostgreSQL |
| Agent and AI work | MCP, OAuth, structured model output |
Planning should lead into doing
Knowing what I did last time is only part of planning the next workout. I also want to account for my equipment, recent performance, and which muscle groups have recovered.
Soma brings those pieces together in a mobile-first tracker. A plan holds the prescription; a workout records what actually happened. Keeping them separate means a suggested set never becomes invented training history.
I built the experience, the underlying services and data model, and the deployment. Actual use keeps turning up the next useful improvement.
From a conversation to a workout plan
This is an existing workflow: Codex and Claude use Soma's MCP tools to read training data and create plans.
- 1Read the product data
The agent retrieves readiness, recent performance, and exercise records through MCP.
- 2Build the session
It uses that context and the user's request to choose a workout and create a plan.
- 3Continue in the app
The plan appears in Soma. The user starts the session and logs what they actually do.
A small, deliberate tool boundary
The OAuth-protected server binds access to a user. Read tools and plan mutations have separate scopes. Agents can create or revise plans; they cannot log sets, complete workouts, or rewrite history. The MCP server and dashboard share the same training-readiness model.
A proposal first, a plan after review
The in-app AI builder is a separate integration from MCP. It receives a limited training context and produces a structured workout proposal. The model has no database or tool access.
Application code checks the result against eligible exercises, load choices, equipment, and the session's duration budget. The user can review and refine the proposal; only explicit acceptance turns it into a plan.
Acceptance also checks whether the relevant training context changed. If a proposal has become stale, the app requires rebuilding it instead of silently saving an outdated prescription.
The API worked. The handoff didn't.
Codex created a workout plan through MCP while Soma was already open. The write succeeded, but the dashboard still showed its old state. I had to close and reopen the app to see the plan.
I added dashboard refresh when the app resumes. That bug made the product boundary clear: creating the right record is only useful if the person can find it when they return.
Observe the workflow without collecting its content
I instrumented product and MCP activity with PostHog. Server-side events use an outbox written in the same transaction as the change. Privacy checks keep prompts, generated prose, and credentials out of analytics.
The work spans the interface, service contract, model behavior, and operation of a deployed product. Each part has to make the next one usable.