Plugins
Runtime plugins with scaffold-owned schema extensions and user-owned runtime files.
Plugins are first-class in kitcn. Install the runtime package, scaffold local files with kitcn add, then keep customizing those local files.
Runtime vs schema
First-party plugins are split on purpose:
- Runtime package: middleware, helpers, and types
- Local schema extension:
convex/lib/plugins/<plugin>/schema.ts - Local runtime files:
convex/functions/plugins/<plugin>.tsandconvex/lib/plugins/<plugin>/...
Schema is app-owned and uses defineSchemaExtension(...):
import { defineSchemaExtension } from 'kitcn/orm';
export function myExtension() {
return defineSchemaExtension('my-plugin', {}).relations(() => ({}));
}Discovery model
defineSchema(...).extend(...) is the source of truth for installed schema capabilities:
import { defineSchema } from 'kitcn/orm';
import { resendExtension } from '../lib/plugins/resend/schema';
export default defineSchema(tables).extend(resendExtension());Extension composition rules:
- Extension
relations(...)merge before apprelations. - Extension
triggersmerge before apptriggers. - Duplicate relation fields and trigger hooks throw.
Ownership model (shadcn-style)
- Packages own stable runtime helpers.
- The CLI owns scaffold templates.
- Your app owns scaffolded schema and runtime files.
kitcn add <plugin>creates or refreshes local plugin files.- If
paths.envis missing,kitcn add <plugin>also bootstrapsconvex/lib/get-env.tsand writespaths.envintoconcave.json. kitcn diff <plugin>previews scaffold drift.- Installed plugin state is tracked in
<functionsDir>/plugins.lock.json.
Codegen behavior:
- Installed extension keys drive generated plugin typing.
- Plugin runtime modules stay scaffold-owned.
- Stale
generated/plugins/**artifacts are removed automatically.
Available plugins
| Plugin | What it gives you |
|---|---|
ratelimit | Convex-native rate limiting with middleware + React hook support |
resend | Durable queued email delivery, batching, webhook status ingestion, and cleanup APIs |
Built-in internal extensions
These are always active and do not require explicit registration:
| Extension | Purpose |
|---|---|
aggregate | Aggregate storage + runtime support |
migration | Migration state + runtime support |