Engine Modes
Programmatic vs Admin UI mode.
superapp supports two engine modes that control how permissions and connections are managed. Choose the mode that matches your team's workflow.
Side-by-Side Comparison
| Feature | programmatic | admin_ui |
|---|---|---|
| Permissions defined in | Code (createEngine config) | Admin UI (stored in metadata DB) |
| Connections defined in | Code (createEngine config) | Admin UI (stored in metadata DB) |
| Roles defined in | Code (createEngine config) | Admin UI (stored in metadata DB) |
| Version control | Git-tracked, PR-reviewed | Database-stored, audit-logged |
| Admin UI | Read-only dashboard (view-only access to config defined in code) | Full editing capabilities (create, edit, and delete permissions, connections, and roles) |
| Deployment | Config changes require redeploy | Changes take effect immediately |
| Default | Yes | No |
| Best for | Engineering teams, CI/CD pipelines | Non-technical admins, rapid iteration |
Programmatic Mode
In programmatic mode, permissions, connections, and roles are defined entirely in your createEngine configuration. The source code is the single source of truth.
const engine = createEngine({
mode: 'programmatic', // this is the default
connections: {
main: { type: 'postgres', url: process.env.PG_URL! },
},
permissions: {
view_own_orders: {
name: 'View own orders',
table: 'main.orders',
operations: { select: true },
columns: ['id', 'amount', 'status', 'created_at'],
filter: { customer_id: { $eq: '$user.customer_id' } },
},
edit_own_orders: {
name: 'Edit own orders',
table: 'main.orders',
operations: { update: true },
columns: ['amount', 'status', 'notes'],
filter: { customer_id: { $eq: '$user.customer_id' } },
check: { status: { $in: ['draft', 'active'] } },
preset: { updated_by: '$user.id' },
},
},
roles: {
viewer: ['view_own_orders'],
editor: ['view_own_orders', 'edit_own_orders'],
},
})How It Works
- You define permissions and roles in TypeScript.
- Changes go through your normal code review process (PR, CI, tests).
- The admin UI (if accessed) shows permissions in read-only mode for visibility.
- The engine reads the config once at startup. Changes require a restart or redeploy.
When to Use Programmatic Mode
- Your team uses git-based workflows and wants permissions in version control.
- You want PR reviews on permission changes.
- You need reproducible deployments where the same code always produces the same behavior.
- You have a CI/CD pipeline that deploys config changes.
- Security is paramount and you want to audit permission changes in git history.
Admin UI Mode
In admin_ui mode, the admin UI becomes the primary interface for managing permissions, connections, and roles. Changes are stored in the metadata database and take effect immediately — no code changes or redeployments needed.
const engine = createEngine({
mode: 'admin_ui',
superapp_db: process.env.TURSO_URL ?? './superapp.db',
masterKey: process.env.SUPERAPP_MASTER_KEY!,
auth: betterAuthProvider({ /* ... */ }),
// No permissions or roles here — they live in the admin UI
})How It Works
- Start the engine with
mode: 'admin_ui'and amasterKey. - Access the admin UI (served by the engine on the
/adminroute). - Add connections, define permissions, and assign roles visually.
- Changes are persisted to the metadata database and applied immediately.
- All admin actions are audit-logged.
Admin UI Capabilities
In admin_ui mode, the admin UI provides:
- Connection management -- Add, edit, and test database connections.
- Permission editor -- Visual builder for filter, columns, check, and preset rules.
- Role management -- Create roles and assign permissions with one click.
- User management -- View users, assign roles, manage sessions.
- Audit log viewer -- Browse query and admin action logs.
- Schema browser -- Explore attached database tables and columns.
When to Use Admin UI Mode
- Non-technical team members need to manage access rules.
- You want to iterate on permissions without redeploying.
- You are building a multi-tenant platform where customers configure their own access rules.
- Rapid prototyping where you are still figuring out the permission model.
Switching Between Modes
You can switch from programmatic to admin_ui mode at any time. When switching to admin_ui mode, any permissions defined in code are imported into the metadata database as a starting point.
Switching from admin_ui back to programmatic requires exporting your current permissions from the admin UI and adding them to your createEngine config.
// Start in programmatic mode during development
const engine = createEngine({
mode: 'programmatic',
permissions: { /* ... */ },
roles: { /* ... */ },
})
// Later, switch to admin_ui mode for production
const engine = createEngine({
mode: 'admin_ui',
masterKey: process.env.SUPERAPP_MASTER_KEY!,
// permissions from code are imported into the metadata DB on first run
})Hybrid Approach
Some teams use programmatic mode in production with admin_ui mode in staging. This lets you:
- Prototype permission changes in the staging admin UI.
- Export the tested configuration.
- Add it to your codebase and deploy through CI/CD.
const engine = createEngine({
mode: process.env.NODE_ENV === 'production' ? 'programmatic' : 'admin_ui',
permissions: {
// These are always available as a baseline
view_own_orders: { /* ... */ },
},
roles: {
viewer: ['view_own_orders'],
},
masterKey: process.env.SUPERAPP_MASTER_KEY!,
})