TL;DR
- Trigger. A scoping call with a consultancy that wanted a CRM in its own vocabulary — engagements and partners, not deals and reps — after another agency quoted six weeks.
- What shipped. Accounts, contacts, engagements, tasks; a pipeline view by stage; an overdue-tasks grid; an assignment workflow that emails the owner. Built as a tenant on the agency’s account.
- Outcome. The managing partner moved three real engagements through the pipeline on the Wednesday call. One license, no per-client meter. Onboarding figures belong to the verified story.
The trigger
The consultancy ran its pipeline in a spreadsheet and its follow-ups in memory. The managing partner had two conditions: it had to speak their language, and it could not take six weeks. The agency principal offered to show a working version the next morning.
For a two-person studio, that offer only works if the build costs nothing but the afternoon.
The 24 hours
- Tuesday · 10:00 AMScoping call. The managing partner: engagements, not opportunities; partners, not reps. Pipeline lives in a shared spreadsheet and who owns the follow-up is a weekly argument. Another agency had quoted six weeks.
- Tuesday · 11:00 AMFirst prompt. Client tenant selected on the agency's account. Groups Partners, Consultants, Ops. Objects accounts, contacts, engagements, tasks — crm_ prefix.
- Tuesday · 2:30 PMPipeline view: an object view joining accounts and engagements by stage; a grid of overdue tasks by owner. Preview diff read line by line.
- Tuesday · 4:00 PMAssignment workflow: assign a task, email the owner. Committed as v3. Published with only Ops in the drawer.
- Wednesday · 8:00 AMSecond pass from the client's overnight notes: stage names renamed to their five; a next-step field on engagements. Preview, commit, republish.
- Wednesday · 9:00 AMWorking software on the call. The managing partner moves three real engagements through the pipeline. Scoping becomes rollout.
The clock runs from the first prompt to working software on the call. Most of the elapsed time was the client’s — overnight notes, a morning review — not the platform’s.
What was built
Four objects, four forms, one object view, one workflow, two grids, twelve screens. The pipeline is an object view: SQL under the hood, joining accounts and engagements by stage, with the tenant filter injected on every query. Objects carry the crm_ prefix.
The first prompt:
Build a solution called Engagements CRM (prefix crm_) as a tenant for a management consultancy. Create groups Partners, Consultants, and Ops first. Objects: Account, Contact, Engagement, Task. They say engagement, never deal or opportunity. Engagements have a stage and a next step; tasks have an owner and a due date. Give me a pipeline view by stage and a grid of overdue tasks by owner. Preview before commit; do not publish yet.
And the workflow, after the client saw the first pass:
When a task is assigned, email the owner with the engagement name and due date. Show me the diff.
preview-solution-edit listed every entity the transaction would touch — four objects, four forms, one view, one workflow, twelve screens — before anything was saved. commit-solution-edit landed all of it as one save, v3.
Published to Ops, opened up on yes
The client is a tenant on the agency’s account: one app definition, the client’s rows isolated by tenant on every table, explicit tenant context on every write. publish-solution copies the working copy Current → Testing → Production in one shot, so the private preview is a group, not a tier: the first publish had only Ops in the drawer, and two people at the consultancy saw it.
The yes on Wednesday added Partners and Consultants to the drawer and republished. Nothing the agent did exceeded what the principal could have clicked — it ran in the principal’s session, with the principal’s permissions. Version 3 was one save on top of version 2, and version 2 stayed on record.
The agency remains the maintainer, which is what the client asked “who maintains this?” to hear.
Nothing was metered on the agency’s side either. No tokens. No credits. No meter. You bring the AI subscription you already pay for.
One organization license covers this client and the next one. The arithmetic is on the pricing page; what you keep if you walk away is on ownership.
Results
| Metric | Value | Source |
|---|---|---|
| Time to working software | 22 hours (example) | Builder log — sourced on sign-off |
| Builders involved | 1 | Builder-reported — sourced on sign-off |
| Consultants onboarded, first week | 35 (example) | Client-reported — sourced on sign-off |
| Quoted elsewhere | 6 weeks (example) | Client-reported, another agency's quote — sourced on sign-off |
| AI cost metered by CodeMonster | $0 | License terms — nothing is metered |
Caveats: values marked “(example)” are illustrative until the client confirms them. The six-week comparison is the client’s report of another agency’s quote, not our measurement, and it ships only with that source attached. Twenty-two hours is first prompt to working software, not contract to onboarding.
In their words
No quote yet. Quotes ship with the verified story: real words, real name and role, approved in writing before publication.
What the monster didn’t do
- It did not import the spreadsheet on day one. Bulk upserts exist; the client wanted to clean the data first, and that date belongs to the verified story.
- It did not sync email or calendars. Inbox integration was out of scope; a workflow can call Zapier, Make, n8n, or any HTTP endpoint when it is not.
- It did not build a reporting dashboard. When the renderer’s grids are not enough, a custom Vite/React frontend ships through its own gated chain — develop, staging, production, with production promote and rollback owner-only — and lands in the same audit trail. A later phase, if the client wants it.
- It did not give the client its own infrastructure. This is shared, governed multi-tenancy: one account, the client as a tenant, isolation at the row level. We say so on the security pages.
- It did not generate a codebase. It assembled platform primitives through named operations, which is why a two-person studio can maintain it.
Builder’s notes
- Groups first, drawer second. Partners, Consultants, and Ops existed before the first object, so every screen and action landed already gated. Publishing to Ops only is how you get a private preview on a platform app.
- One tenant per client.
list-tenants, thenuse-tenant, before the first write. The client’s data never shares a row with another client’s, and the app definition stays one thing to maintain. - Twelve screens is too many to eyeball. The entity-level diff put the wrong stage order on one line, before the managing partner ever saw it.
Build this yourself
The CRM-lite blueprint is the primitives map and the starter prompt for this app. Swap the vocabulary for your client’s; keep the shape.
Build a solution called Engagements CRM (prefix crm_) as a tenant for a professional-services client.
Create groups Partners, Consultants, and Ops first.
Objects: Account (name, sector, owner); Contact (account, name, email, role); Engagement (account, stage, next step, owner, value); Task (engagement, owner, due date, done).
Use the client's words — ask me if a term is ambiguous.
Give me a pipeline view by stage and a grid of overdue tasks by owner.
Add a workflow: when a task is assigned, email the owner.
Publish with only Ops in the drawer. Show me the preview diff before you commit. Then get the desktop app, connect the AI you already pay for, and start the clock on your next client’s process. See also the CRM-lite use case.