index / work / prasso
Building Prasso
A directory of UK studio locations teaching yoga, pilates, reformer and wellness, built around a private record of the classes you take. The directory gets people in; the record is what brings them back.
Live at prasso.co.uk, and unannounced. The app has served the domain since 8 August 2026; no testers have been invited yet, so nothing on this page is a traction number. These are counts of things that exist.
Disclosure: I co-founded The Reset Rooms, a pilates and wellness studio in Crouch End that trades today and that appears in the directory, including in the screenshot below. It is a separate venture, not a Lyon Empire product.
| role | sole designer and engineer |
|---|---|
| stack | Nuxt 3 SSR, TypeScript, Prisma, Supabase Postgres, Fly.io |
| models | 37 |
| routes | 126 |
| tests | 1,719 assertions in 95 files1 |
| decisions | 127 logged |
The mechanism
three parts, one of which does the work
The directory
Studios, disciplines and locations, kept accurate enough to be worth searching. Necessary, and treated as such.
The record
What you did, where, and how often. Private by default, exportable, and the only reason anyone returns after the first search.
The aggregate
Medians drawn across the records, sold back to studios as market insight. Never a named class, never an identifiable person.
A directory is copyable. A record made of real behaviour is not.


Decisions
drawn from the log
No advertising, ever.
Listings and studio insight pay for the product. The moment attention is what is being sold, ranking stops being a service to the reader and becomes inventory. That removed the easiest revenue line on the table before it existed.
No timetables and no bookings.
Every request for this is a request to become a booking platform: live integrations with a dozen studio systems, a support burden, and a fight with incumbents on their ground. Prasso records what happened; the studio owns what is next. It is the feature people ask for first.
The importer doesn't guess.
An unmapped string goes to a queue and renders as unclassified, never as a default, because a catch-all row is a bin and bins fill. 63 records sit in that queue today, each with the reason it was held. A lenient importer would have produced a bigger directory.
No number without its denominator.
Nothing appears in the product or on this page without its sample, period and method. It kills the round ones and it cost several charts outright.
What it actually took
the migration, plainly
The first generation of the data was scraped, and scraped data is wrong in ways that only show up at scale: a missing postcode, a discipline the taxonomy does not recognise, two records claiming one slug. The importer refuses all of it and writes down why, rather than cleaning it quietly.
Correcting that first generation and publishing the studios that followed took a weekend, spread across a few. A directory of this size is a weekend's work for anyone with the same sources, which is why the directory was never the thing being built. The months went into what the record is allowed to hold, and what the directory is not allowed to do.
The scraper proposes. It never assigns.
The bead
where the craft is, if it is anywhere
Each attended class earns a bead, and each bead is a five-channel code: form, hue, value, core, ring. Five is a cap set in the schema rather than a guideline, and a channel is spent, never shared. Intensity, duration, load, reps and springs have no channel and never will: the record does not quantify the body. That is a decision with a number on it, not an omission.
| channel | encodes | why it survived the cut |
|---|---|---|
| form | discipline | Circle yoga, square pilates and other movement, pentagon meditation and sound. The one thing people scan a year of practice for. |
| hue | style, scoped to its discipline | 33 styles assigned by hand around three bases. A hash gave stability without relation; neighbours have to look like neighbours. |
| value | time of day | Four steps. A month reads as a rhythm with no legend attached. |
| core | landing recorded | Presence, never degree. The graded core drew the body as a magnitude and was removed twice. |
| ring | teacher named | Fine amber, absent when no teacher was given. It once meant four things at once. |
A field existing in the schema does not entitle it to a channel.
Position carries nothing. An unearned position renders as a plus rather than a pale bead, so the grid shows what has not happened yet without pretending it has.

What is not done
known gaps, stated plainly
- The coverage claim is a claim. What is published is a count of rows that passed the importer, and no page on the site says "every studio in the UK" because that is not true yet. The count itself is off this page until its unit is settled and the country labels in production have been audited: the recorded figures disagree with each other, and a number that cannot survive being asked how it was made does not go up.
- Nobody outside the build has used it. The app has served prasso.co.uk since 8 August 2026, payments are flagged off and no invitation has been sent. Everything I believe about the record habit is a hypothesis with a decision number attached, not a finding.
- Studio-side pricing is unproven. The insight product is built and priced, and no studio has paid for it yet. If it turns out they will not, the model changes and the log records why.
- Accessibility is partial. Keyboard paths and contrast are done; the bead grid still needs a proper non-visual equivalent, and a data visualisation without one is unfinished.
Sources
- 37 Prisma models, 126 Nitro routes and 1,719 passing assertions across 95 test files, counted from the repository at the same commit. 127 numbered decisions in the log, February to September 2026.