Introduction
One schema. Typed backend. Auto forms. Zero boilerplate.
What is noboil?
noboil is a fullstack framework that generates your entire backend from a Zod schema. Define your tables once — get CRUD, real-time subscriptions, file uploads, typesafe forms, multi-tenancy, and more. All type-safe, all zero-config.
Pick a database when you scaffold (Convex or SpacetimeDB), then write code against the noboil API. The docs show one snippet per concept; the Convex vs SpacetimeDB page lists the small set of places where the underlying database constraints surface.
From zero to CRUD in 60 seconds
bunx noboil@latest init my-app
cd my-appPick your database, choose whether to include demo apps, and you have a working app with auth, typed CRUD, real-time subscriptions, and file uploads.
Define a schema, get an API
import { schema, file, files } from 'noboil/convex/schema'
import { array, boolean, object, string, enum as zenum } from 'zod/v4'
export const s = schema({
owned: {
blog: object({
title: string().min(1, 'Required'),
content: string().min(3),
category: zenum(['tech', 'life', 'tutorial']),
published: boolean(),
coverImage: file().nullable().optional(),
tags: array(string()).max(5).optional()
})
}
})import { noboil } from 'noboil/convex/server'
// ...
export const api = noboil({ ...config, tables: ({ table }) => ({
blog: table(s.blog, { rateLimit: { max: 10, window: 60_000 }, search: 'content' })
}) })That's it. Five endpoints (create, update, rm, list, read) with auth, ownership, Zod validation, file upload, cursor pagination, rate limiting, and conflict detection — all generated. create, update, and rm accept single or bulk input (up to 100 items).
Add a table in one command
noboil convex add todo --fields="title:string,done:boolean"
# or
noboil stdb add todo --fields="title:string,done:boolean"This generates a Zod schema, CRUD endpoints, and a React page component. Every field name is type-checked — misspell title and TypeScript catches it.
Table types: owned (user-scoped), org (multi-tenant), singleton (one per user), cache (external API), child (nested under parent).
Ship with prebuilt components or go headless
Prebuilt UI — 16 typed form fields, multi-step wizards, editor management, error boundaries, and access control guards. Pass a Zod schema and get a working form:
import { Form, useFormMutation } from 'noboil/convex/components'
const form = useFormMutation({ mutation: api.blog.create, schema: s.blog })
<Form form={form} render={({ Text, Choose, Toggle, Submit }) => (
<>
<Text name="title" />
<Choose name="category" />
<Toggle name="published" />
<Submit>Create</Submit>
</>
)} />Headless hooks — Every component's logic is available as a standalone hook. Use useStepper without StepForm, useList without any UI, useBulkSelection for multi-select state, useSearch for debounced search. Bring your own design system.
What you get from one schema
| Feature | What happens |
|---|---|
| CRUD endpoints | list, create, update, rm with auth, pagination, and rate limiting |
| Real-time | Live subscriptions out of the box — ~39ms latency on SpacetimeDB |
| Type safety | End-to-end from database to UI. Misspell a field name → compile error |
| Forms | Auto-generated with validation, file uploads, conflict detection, auto-save |
| Multi-tenancy | Organizations, roles, invites, join requests, per-item ACL |
| File uploads | Drag-and-drop with compression, progress tracking, and storage cleanup |
| Soft delete | Built-in with undo toast and restore |
| DevTools | Schema playground, query inspector, subscription monitor |
CLI tooling
Three CLIs ship with noboil:
| CLI | Purpose |
|---|---|
noboil | Project scaffolding (init), health checks (doctor), upstream sync (sync), eject (eject) |
noboil convex | Add tables, validate schema, migrate, visualize, generate docs |
noboil stdb | Add tables, validate schema, local dev workflow, switch targets, generate docs |
See CLI Reference for the full command reference.
Eject anytime
noboil is designed for incremental ejection. Replace one factory at a time while the rest of your app keeps running. See Ejecting.