What ConvexCompose is
ConvexCompose is a contract for business-domain modules built on Convex.dev (the get-convex project, not the unrelated convex.com CRM). The seminal idea is a single asymmetry: be opinionated about the module contract and unopinionated about the host app. Prescribe how a module is shaped, so modules compose with each other and port across targets. Prescribe nothing about the consumer's framework, router, styling system, or platform.
The split lives at the module level
Two things are deliberately held apart inside every module and must never collapse into each other.
- The agnostic core. A Convex Component plus headless React hooks plus a manifest. It carries the invariant business meaning of a domain and assumes no framework, router, styling engine, or platform. This is the thing that ports, and it is what you always get. It appeals to any Convex developer on any stack: Next, Remix, TanStack Start, Expo, or web-only.
- The optional reference UI. Each module ships its own OPTIONAL reference UI: one fully worked, batteries-included way to consume the core, offered as a convenience and never as a requirement. Take it as-is, or take the Component and hooks and build your own surface. There is no single reference app; anyone can build any consumer, and the reference UIs are per-module and optional.
The second wave of Convex Components
Convex Components gave the backend a real module system. The first wave is infrastructure primitives that live below your application: rate limiter, aggregate, agent, workpool, crons. Convex's own Stack writing pointed past that first batch to a "second wave" of components filling the application layer above the primitives and below your routes: the business domains themselves, an LMS, a booking system, a mail module. Business-domain modules are exactly that second wave, authored from outside.
So ConvexCompose is an extension of the Convex Components ecosystem, not a competitor to it. A business-domain module is not parallel to Convex's primitives; it is a consumer of them, composing the rate limiter and the aggregate that Convex already ships rather than reinventing them. The stack used here is the stack Convex itself points to: it sponsors TanStack and recommends Better Auth. This is not a rival to Convex's Chef app-builder or to Templates. It is just the next set of modules.
The three-layer model
Every module is structured in three layers, ordered most-portable to most-consumer-specific.
- Layer 1: a Convex Component. convex.config.ts plus schema plus functions, isolated and app.use()-installable, transactional by construction. Same everywhere.
- Layer 2: headless React hooks. useX() over Convex's React hooks. No router import, no styling system, navigation expressed as callbacks the consumer supplies. Runs under any React renderer, DOM or React Native.
- Layer 3: thin route wrappers. Roughly five lines each, binding Layer 2 into the consumer's actual router and chrome. This is the only layer the consumer is expected to write.
Beside Layer 2 and 3, clearly labeled OPTIONAL, each module ships its own reference UI package (for example an RN plus NativeWind kit). Drop it in for batteries included, or ignore it and lose nothing but the convenience.
A real production story, told honestly
The contract was extracted from a system in production. A production deployment runs 50+ portals on one Convex deployment, used daily by a working college professor for real classes (an LMS with assignments, attendance, and grades; bookings; mail). A live federated portal runs on its own subdomain, consuming the shared deployment by name. One shared component renders on web (react-native-web) and on mobile (Expo) from a single source. app.use(betterAuth) and app.use(posthog) are live Convex Components in production.
Being honest about the gap matters as much as the proof. No ConvexCompose module is a published, installable package today. The domains above run in a production deployment as plain function modules on one deployment; they are mid-extraction into conforming Components. convex-garden is the first module being extracted to the full contract and is the lead worked example. What exists is the contract, a real proving ground, and the first module in extraction; not ten products available now.