C
ConvexCompose
Modules
← Docs

The 3-Layer Portability Model

Every ConvexCompose module is built in three layers. The key insight: each layer has different portability properties, and you only pay the framework-coupling cost at the very top.

L4
Your App
Routes, layouts, your business logic
L3
ConvexCompose Modules
Mail · Tasks · LMS · Inventory · Booking · …
L2
Convex Components
Rate Limiter · Workflow · Crons · Aggregate
L1
Convex Core
Reactive database, functions, auth, scheduling

Layer 1: Convex Core (100% portable)

The Convex schema and functions. Pure TypeScript with zero framework dependencies. This is where your data lives, your queries run, and your mutations execute.

Layer 2: React Components (~90% portable)

Standard React components that consume the Convex hooks (useQuery, useMutation). They are framework-agnostic — no router imports, no next/link, no TanStack Link. Navigation happens through callback props that the host app wires up.

Layer 3: Route Wrappers (framework-specific)

Thin shells — usually about 5 lines each — that adapt the React components to your specific router. ConvexCompose ships templates for TanStack Start, Next.js, and Remix.

// apps/web/src/routes/mail.tsx (TanStack Start)
import { createFileRoute } from '@tanstack/react-router';
import { MailInbox } from '@convexcompose/mail/react';

export const Route = createFileRoute('/mail')({
  component: () => <MailInbox onOpen={(id) => Route.navigate({ to: `/mail/${id}` })} />,
});

Why this matters

If you swap routers (or even rewrite your frontend in a different framework entirely), you only rewrite Layer 3. Your data, your queries, and 90% of your UI come along for the ride.