Taruvi app builder
Orchestrate end-to-end feature development on Taruvi. This skill sets context, routes to specialists, and verifies integration. For the actual provisioning / code-writing / UI-building work, this skill delegates to three specialists.
Core principles
- One layer at a time. Don't interleave MCP provisioning and Refine UI generation in the same step. Provision first, generate second, verify third.
- Always plan before executing. For any non-trivial feature, produce a short plan (entities, tables, policies, functions, pages) and have the user confirm before touching the platform.
- Verify against the platform, not memory. Call MCP tools (
getdatatableschema, manage_policies(action="get"), etc.) to inspect current state before assuming.
- The three specialist skills own the details. This skill is the orchestrator — it shouldn't duplicate specialist content. When in doubt about how to do something in a specific layer, route to the right specialist.
The three layers
See [references/architecture-overview.md](references/architecture-overview.md) for the full model.
| Layer |
Job |
Skill |
| MCP |
Provision backend resources: tables, roles, policies, functions, secrets, buckets |
taruvi-backend-provisioning |
| Python SDK |
Write function bodies that run inside Taruvi's function runtime |
taruvi-functions |
| Refine providers |
Build the React/Refine frontend that consumes Taruvi |
taruvi-refine-frontend |
Project-level context (conventions, commands, env) goes in the consuming app's AGENTS.md / CLAUDE.md — see [references/agents-md-template.md](references/agents-md-template.md) for the template.
Decision tree: which specialist?
Is the task single-domain?
├── Yes, backend only (tables, policies, roles, secrets, functions metadata)
│ → Activate taruvi-backend-provisioning, STOP here.
├── Yes, function body only (Python that will run in a function)
│ → Activate taruvi-functions, STOP here.
├── Yes, frontend only (Refine pages, hooks, UI)
│ → Activate taruvi-refine-frontend, STOP here.
└── No — the task spans two or more layers
→ Use the feature-add workflow below. Delegate to specialists in sequence.
Function or provider? (frontend routing)
When you're inside the frontend and wondering whether an operation should be a direct Refine call or a serverless function, use this rule:
Does the task touch more than one resource? (resources = datatables, storage buckets, users, secrets, analytics queries)
- No — single-resource CRUD → use Refine hooks directly via the right provider.
- Yes — 2+ resources, or any of the triggers below → use a Taruvi function.
| Trigger |
Why a function |
Where the skill detail lives |
| Multi-resource create/update/delete cascade |
Atomic, auditable, no race conditions |
taruvi-functions/references/scenarios.md Scenario 1–2 |
| Reacting to a data-change event (RECORD_CREATE, etc.) |
Runs server-side on the event |
taruvi-functions/references/scenarios.md Scenario 4 |
| Scheduled job (cron) |
No user triggers it |
taruvi-functions/references/scenarios.md Scenario 3 |
| External API call with a stored secret |
Don't leak credentials to the browser |
taruvi-functions/references/scenarios.md Scenario 5 |
| Long-running task (>30s) |
Async execution, task-id polling |
taruvi-functions/references/function-templates.md (async fan-out) |
| Public webhook receiver |
is_public=True endpoint |
taruvi-functions/references/scenarios.md Scenario 5 |
| Authorization-gated server-side logic |
Runs with service credentials, not user |
taruvi-functions/references/auth-patterns.md |
If the answer is "yes, it's a function," the workflow splits into two steps:
- Register the function metadata via
taruvi-backend-provisioning (managefunction(action="createupdate", ...)).
- Write the function body via
taruvi-functions, then re-register with the code field populated.
Greenfield scaffold workflow
For a new Taruvi app from scratch:
- Interview. Clarify: what does the app do? What entities? Auth model (email/pass, OAuth)? Who are the roles?
- Tenant setup (if fresh tenant). Usually handled outside this workflow by Taruvi admin; if not, use
create_tenant via Django management command (document in the app's README).
- Refine app scaffold. Create a new Refine project:
``bash npm create refine-app@latest my-app -- --template=vite-antd --template-features=typescript,tailwind ` Install Taruvi packages: `bash cd my-app npm install @taruvi/sdk @taruvi/refine-providers ``
- Wire providers. Replace
App.tsx provider wiring with the Taruvi providers — see [references/feature-workflow-examples.md](references/feature-workflow-examples.md) for a full snippet. Activate taruvi-refine-frontend for details.
- Provision the schema. Activate
taruvi-backend-provisioning. Define entities as a Frictionless Data Package, create the tables.
- Provision roles + policies. Still in
taruvi-backend-provisioning. Create roles, Cerbos policies, initial role assignments.
- Write functions (if needed). Register function metadata via
taruvi-backend-provisioning (manage_function), then activate taruvi-functions to write the bodies.
- Generate Refine pages. Activate
taruvi-refine-frontend. Generate list / show / edit / create pages for each resource, wire access control.
- Configure the app's AGENTS.md. Emit the template from [references/agents-md-template.md](references/agents-md-template.md) with the specifics for this app.
- Verify end-to-end. Run the Refine dev server, walk through the primary user flow, confirm auth + CRUD + policy enforcement.
See [references/feature-workflow-examples.md](references/feature-workflow-examples.md) for worked examples.
Feature-add workflow (existing app)
For adding a feature to an existing Taruvi app:
- Spec. Describe the feature in one paragraph. Identify: new entities, new policies, new functions, new pages.
- Plan — emit this structure for user review:
``` Feature: <name>
Backend (MCP): - Datatables: <new or modified> - Policies: <new rules> - Roles: <if new> - Functions (metadata): <slug + mode> - Secrets: <if new>
Functions (bodies): - <slug>: <one-line description>
Frontend (Refine): - Resources to add to Refine resources[]: <list> - Pages: list / show / edit / create for each - Access control: <rules>
Verification: - <what the user tests> ``` Get user confirmation before executing.
- Provision backend — delegate to
taruvi-backend-provisioning. Call MCP tools in order: schema → roles → policies → function metadata → secrets.
- Write function bodies (if any) — delegate to
taruvi-functions. After writing, re-register via managefunction(action="createupdate", code=<body>) in the backend-provisioning skill.
- Generate frontend — delegate to
taruvi-refine-frontend. Add Refine resources, generate CRUD pages, wire useCan and meta.allowedActions.
- Verify. Run the app locally. Confirm: tables are reachable, policies gate correctly, functions execute, Refine pages render.
Integration gotchas
See [references/integration-pitfalls.md](references/integration-pitfalls.md) for the full list. Top hits:
- Create policies before first write. If a policy is missing, the first insert to the table 403s. Policy → table materialization → first insert.
meta.idColumnName in Refine must match the Frictionless primaryKey. Non-id PKs need idColumnName on every hook. Or alias via meta.tableName with an id column aliased in an analytics view.
- Function metadata and body live in different surfaces. Use
managefunction (MCP) to register; write the body in taruvi-functions context; re-call managefunction(action="create_update", code=<body>) to deploy.
- Async functions return a task id, not a result. Refine's
useCustom with meta.kind: "function" expects a sync response. Either keep the function sync, or poll for the result client-side.
- Env vars are critical. The consuming app needs
TARUVIAPIURL, TARUVIAPIKEY, TARUVIAPPSLUG (front-end: REACTAPP or VITE_ prefix). See [references/env-setup.md](references/env-setup.md).
- Tenant schema matters in dev. Local dev often means pointing at a specific tenant subdomain or passing an
X-Tenant header. Document the dev setup in the app's AGENTS.md.
- JWT expiry cascades. If a Refine user's JWT expires, they get 401 →
authProvider.onError → forced logout. No silent refresh in the default flow. Long-lived sessions need refresh-token handling (outside default).
Verification checklist
After a feature lands, confirm:
Workflow diagram
flowchart TD
A[User request] --> B{Single-domain?}
B -- Yes: backend --> C[taruvi-backend-provisioning]
B -- Yes: function --> D[taruvi-functions]
B -- Yes: frontend --> E[taruvi-refine-frontend]
B -- No: cross-layer --> F[Spec + plan]
F --> G[User confirms plan]
G --> H[Provision backend via MCP]
H --> I[Write function bodies]
I --> J[Re-register functions with code]
J --> K[Generate Refine frontend]
K --> L[Verify end-to-end]
L --> M[Update AGENTS.md]
When you get stuck
- Architecture overview: [references/architecture-overview.md](references/architecture-overview.md)
- Feature workflow examples (3 worked): [references/feature-workflow-examples.md](references/feature-workflow-examples.md)
- AGENTS.md template for consuming apps: [references/agents-md-template.md](references/agents-md-template.md)
- Env var setup: [references/env-setup.md](references/env-setup.md)
- Integration pitfalls: [references/integration-pitfalls.md](references/integration-pitfalls.md)
- Deployment workflow (Frontend Workers): [references/deployment.md](references/deployment.md)
- For specialist detail, load the matching specialist skill's
SKILL.md and relevant reference files.