Skip to content

Shared modules

A feature earns a module by being needed twice.

Everything else stays inside the app that needed it. These five came out because they kept reappearing — and once something is here, the next tool starts closer to done.

ai-object

28

consumers

The substrate behind every studio: an AI edits a structured object through tool calls instead of regenerating it.

Written once for Doc Studio. By the third app it was obvious the object type was the only thing changing — the block model, the planner and the chat surface were identical every time. It now carries fifteen apps, and a Python twin held to identical output by parity vectors — the planner has no randomness in it, so the two propose the same edits for the same sentence or a test goes red.

What ships

  • block model
  • deterministic mock planner (intent → edit ops)
  • chat + edit-event UI
  • pure exporters

Used by

crm

01

consumer

Contacts, pipeline and activity — headless, embeddable, or standalone.

Started as an app. Turned out every tool that touches people wants the same pipeline and activity feed, so the app became a thin wrapper around a module anyone can mount.

What ships

  • Convex schema factory
  • pure pipeline & rollup logic
  • props-driven React UI kit
  • MCP tool descriptors

Used by

changelog

01

consumer

Changelog and roadmap as a public status page that also embeds anywhere.

Every app eventually needs a 'what's new'. Building it per app was the obvious waste — this runs standalone and drops in as a widget.

What ships

  • Convex schema factory
  • grouping & semver logic
  • changelog feed, roadmap board, embeddable widget
  • MCP tool descriptors

Used by

lab-languages

15

consumers

One language registry for every surface that answers in a language — real languages, and fictional ones only a fake AI can offer.

It was extracted the moment three places had grown their own trimmed copies of the same table: the faker, the Convex AI engine and the Python port. That is the exact shape of a drift bug waiting to happen. The data lives here now; everything else reads from it, and the one copy that genuinely cannot import it — the dependency-free Convex engine — is held to the registry by a test that names the missing language.

What ships

  • 13 real languages, including RTL Arabic and unspaced Japanese
  • 9 fictional: Klingon, Elvish, Dothraki, Pirate, Minionese, Simlish, Orcish, Machine, Lorem
  • per-language typography — joining, terminators, capitalisation, direction
  • forgiving resolution: codes, BCP-47 tags, names, endonyms, Accept-Language
  • generators that emit the Python data and its parity vectors

Used by

studio-core

13

consumers

An AI object studio, minus the web framework — vocabulary, block store and the AI turn.

Doc Studio was written first, at eight hundred lines, then reduced to forty-three by extracting the generic half. That extraction was a Flask package — and the split between what a studio *is* and how it is *served* was sitting inside it unmarked: three modules with no framework imports, next to three with them. Making that a package boundary is what let a Django studio be an adapter rather than a second implementation.

What ships

  • StudioSpec — the vocabulary that is the only thing a studio changes
  • SQLite block store with float ordering and subtree deletes
  • the AI turn: plan → resolve generation requests → apply → record
  • no web framework, and no provider — offline and deterministic

Used by

flask-studio

12

consumers

The Flask adapter for studio-core — blueprints and Jinja templates.

Contributes request handling and templates, and nothing else. Everything it serves comes from studio-core — twelve studios now run on it, each one a vocabulary of thirty-eight to forty-three lines.

What ships

  • blueprint factories for the API and the editor
  • Jinja templates driven by the spec

Used by

django-studio

01

consumer

The Django adapter for studio-core — views, URLconf and templates.

The second adapter, and the reason the core can be called framework-free rather than merely untested elsewhere. Flask and Django disagree about request objects, routing, CSRF and templating; nothing in the core needed a special case for either. Seven tests run both adapters against the same request and assert the responses are identical — if they ever diverge, one of them has grown logic that belongs in the core.

What ships

  • view and URLconf factories, bound to a spec and store
  • Django templates — the same design, in Django's syntax
  • CSRF-exempt API with a test that the exemption holds

Used by

phantom-core

16

consumers

Faker for AI responses — deterministic, provider-shaped fakes across models and modalities.

Every app in the lab needs fake AI responses; none of them should own the faking. It ships twice — TypeScript and Python — and the two are held byte-identical for a given seed by parity vectors, so "the same faker in two languages" is a checked claim rather than a hopeful one.

What ships

  • provider response shapes
  • seeded determinism
  • modality coverage
  • latency & cost modelling

Used by

phantom

00

consumers

Remote client and drop-in provider shims over phantom-core.

Splitting the client from the core meant the same fakes work offline locally and behind an HTTP API remotely, without the apps knowing which.

What ships

  • provider shims
  • remote HTTP client
  • offline fallback

Not yet shared

17 tools own all of their machinery. That is not a backlog — most of them are the only thing that will ever need it. A few are candidates: Media Manager keeps rebuilding the same library screen the media tools want, and it should probably graduate next.