Skip to main content
“Plugins” in Pylon means two concrete things — and neither is a manifest.plugins: [...] list. There is no such array today.
  1. TS packages (@pylonsync/*) — installable npm packages that return a manifest fragment (entities, actions, queries, policies) plus handler factories. You compose the fragment into your buildManifest() call. Use these to add features the framework binary doesn’t already cover.
  2. Built-in runtime plugins — a small set compiled into the pylon binary and wired automatically from your schema or environment. You don’t name them anywhere; they activate when the relevant signal is present (a tenantId field, a .owner() annotation, an env var).
Features that are built into the framework binary already (no package, no plugin needed):
  • API keys/api/auth/api-keys routes for mint / list / revoke. See Auth → API keys.
  • TOTP / 2FA/api/auth/totp/* routes for enroll / verify / disable + backup codes. See Auth → TOTP.
  • Transactional emailPYLON_EMAIL_PROVIDER env (sendgrid / resend / stack0 / webhook) + ctx.email.send(). See Integrations → email.
  • Audit log/api/auth/audit + /api/auth/audit/tenant routes.
  • OrganizationsOrg / OrgMember / OrgInvite entities + /api/auth/orgs/* routes. See Auth → Organizations.

TS packages

Install with bun add, then spread the manifest fragment into buildManifest(): Each package exports a factory (e.g. stripe({...}), webhooks({...})) that returns { manifest, handlers, ... }. Pylon loads function handlers one-per-file, so you also add one-line wrapper files under functions/ — see each package’s page for the exact list.

Built-in runtime plugins

These live in crates/plugin/src/builtin/ and are registered by the runtime at boot. They are auto-wired, not enabled through a manifest list.

How built-ins hook in

Built-ins observe the request and data path at fixed points. The exact Rust hooks (see Writing your own):
A built-in can inspect or reject a request (on_request), mutate or reject a write (before_*), react after a write lands (after_*), add HTTP routes (routes()), or contribute manifest entities (entities()).

There is no plugins: [] array

Older drafts of these docs described enabling plugins through a pylon.manifest.json plugins list with per-plugin config. That mechanism does not exist. Built-ins are automatic; you influence them through your schema (add a tenantId field, annotate a field .owner()) and environment variables. App-specific cross-cutting logic goes in server functions and policies, not a plugin config block. pylon plugins list prints a roadmap catalog of plugin names (validation, slugify, versioning, cascade, MCP, and more). These are planned, not installable today — treat the list as a preview, not an API.

Plugins vs functions

Use a built-in when the behavior should apply to every call. Use a function when callers opt in by name.

Writing your own

There is no dynamic plugin loading yet. To add a Rust built-in you build a custom runtime that registers it; for TypeScript-side logic, use functions and policies. The SDK ships a definePlugin({ name, entities, hooks }) helper, but the runtime does not consume its output yet. See Writing your own plugin for the real Plugin trait and the honest state of extensibility.