Remult
Build Full-stack, End-to-end Type-safe CRUD Apps without the Boilerplate
Remult
Remult is a TypeScript library for building full-stack apps without boilerplate. Define entities once and use them on the frontend, the backend, and in the database, with a single SSOT (Single Source of Truth) for schema, validation, permissions, and CRUD.
Core Concepts
- Entity - a TypeScript class decorated with
@Entity('key', options)is your SSOT: schema, REST API, validation, permissions, and lifecycle in one place. - Fields -
@Fields.string(),.number(),.boolean(),.date(),.json(),.uuid(),.cuid(),.autoIncrement(), plus@Relations.toOne()/.toMany()for entity links. - Repository (
repo(Entity)) - universal CRUD:.find(),.findFirst(),.findId(),.insert(),.update(),.delete(),.save(),.count(),.query(),.liveQuery(). Same API on frontend and backend. - Permissions - entity-level
allowApiRead/Insert/Update/Delete/Crudand per-fieldallowApiUpdate; values are boolean, role string, role array, or(entity, remult) => boolean. UseapiPrefilter/backendPrefilterfor row-level filtering. - Lifecycle hooks -
validation,saving,saved,deleting,deletedrun on the server before/after persistence;savingmutates the entity in place. - BackendMethod -
@BackendMethod({ allowed })exposes a server-only function callable from the client; runs in the server context withremult.userpopulated. - Live queries -
repo(X).liveQuery(options).subscribe(({ items, changes }) => ...)pushes inserts/updates/deletes to all connected clients over SSE. - Custom filters -
Filter.createCustom/SqlDatabase.filterToRawto express complex queries that round-trip to the server safely. - Validators - built-ins under
Validators.*(required,min,max,email,url,unique,regex,enum, ...) orvalidate: (entity) => string | undefinedfor custom logic. - Admin UI - turnkey
/api/adminpanel viaadmin: true(oradmin: { allow: 'admin' }) inremultApi(). - Stacks - frameworks: React, Angular, Vue, SvelteKit, Next.js, SolidStart, Nuxt. Servers: Express, Fastify, Hono, Elysia, Hapi, Koa, NestJS. Databases: PostgreSQL, MySQL, MongoDB, SQLite (better/sqljs/bun), MSSQL, Turso, DuckDB, Oracle, Cloudflare D1, JSON files.
Documentation
Getting Started
- Introduction: Introduction - fullstack CRUD framework deriving REST API, type-safe client, and query builder from TS model classes.
- Creating a project: Scaffold a new project with npm init remult@latest - 180+ framework/server/DB/auth combinations.
- Quickstart: Install remult and wire remultApi middleware into Express, Fastify, Next.js, SvelteKit, and friends.
- Example Apps: Gallery of example apps - TodoMVC, CRM, shadcn/TanStack tables, ready-to-play sandboxes.
Entities
- Entities: The SSOT class - schema, REST API, validation, and permissions in one @Entity decorator.
- Fields: Built-in @Fields decorators - string, number, integer, boolean, date, dateOnly, json, object, literal.
- Relations: @Relations.toOne / @Relations.toMany - define and navigate one-to-one, one-to-many, many-to-many associations.
- Filtering and Relations: Querying across one-to-many relations - inline where, nested filters, and reusable custom filters.
- Lifecycle Hooks: Entity hooks - validation, saving, saved, deleting, deleted - for custom logic at persistence boundaries.
- Migrations: Automatic ensureSchema sync vs. explicit migration files generated and applied via the migrations CLI.
- Generate from Existing DB: Generate entity classes from an existing database schema using remult-kit.
- Offline Support: Browser-side dataProviders - JsonDataProvider over localStorage, sessionStorage, IndexedDB, or OPFS.
- Active Record & EntityBase: Active Record pattern via EntityBase/IdEntity - mutable instances with save/delete methods bound to rows.
- Entity Backend Methods: @BackendMethod on entity instances - round-trips the full (possibly unsaved) entity state to the server.
- Mutable Controllers: @Controller classes with stateful fields that round-trip between client and server on BackendMethod calls.
Stacks
- React: React + Vite frontend integration with experimentalDecorators and a /api proxy to the API server.
- Angular: Angular frontend integration with proxy.conf.json forwarding /api calls to the separate API server.
- Vue: Vue + Vite frontend integration with experimentalDecorators and a /api proxy to the API server.
- Sveltekit: SvelteKit integration via a [...remult] +server.ts route using remultApi from remult/remult-sveltekit.
- Next.js: Next.js integration via a catch-all dynamic API route calling remultApi from remult/remult-next.
- SolidStart: SolidStart integration via a catch-all dynamic API route calling remultApi from remult/remult-solid-start.
- Nuxt: Nuxt integration via a server/api catch-all route using remultApi from remult/remult-nuxt.
- Express: Express integration via the remult-express middleware adapter.
- Fastify: Fastify integration via the remult-fastify plugin registered on the Fastify app.
- Hono: Hono integration via the remult-hono adapter mounted as a route on the Hono app.
- Elysia: Elysia integration via the remult/remult-hono adapter mounted on the Elysia app.
- Hapi: Hapi integration via the remult-hapi plugin registered on the Hapi server.
- Koa: Koa integration via createRemultServer with a middleware that delegates to api.handle.
- nest: Nest.js integration via app.use(remultApi({})) using the remult/remult-express adapter.
- Database: Database picker - defaults to a JSON file store in ./db when no dataProvider is configured.
- PostgreSQL: PostgreSQL via createPostgresDataProvider on the dataProvider option, or reuse an existing pg.Pool.
- MySQL: MySQL via createKnexDataProvider with the mysql2 client on the dataProvider option.
- MongoDB: MongoDB integration via MongoDataProvider on the dataProvider option, no schema migrations needed.
- SQLite3: SQLite3 via Sqlite3DataProvider wrapped in SqlDatabase on the dataProvider option, works on StackBlitz.
- Better SQLite3: Better-sqlite3 via BetterSqlite3DataProvider wrapped in SqlDatabase on the dataProvider option.
- sqljs: sql.js in-memory SQLite via SqlJsDataProvider wrapped in SqlDatabase on the dataProvider option.
- MSSQL: Microsoft SQL Server via createKnexDataProvider with the mssql client (tedious driver) on the dataProvider option.
- Bun SQLite: Bun:SQLite via BunSqliteDataProvider wrapped in SqlDatabase on the dataProvider option.
- Turso: Turso via TursoDataProvider over @libsql/client wrapped in SqlDatabase on the dataProvider option.
- DuckDb: DuckDB via DuckDBDataProvider wrapped in SqlDatabase on the dataProvider option.
- Oracle: Oracle via createKnexDataProvider with the oracledb client on the dataProvider option.
- D1: Cloudflare D1 via createD1DataProvider from remult/remult-d1 on the dataProvider option.
- Json files: JSON file storage via JsonDataProvider + JsonEntityFileStorage on the dataProvider option.
Server-side Code
- Backend Methods: @BackendMethod - typed RPC calls that auto-expose REST endpoints and run server-only logic.
- Server-only Dependencies: Keep Node-only deps (fs, etc.) out of client bundles via import.meta.env.SSR, dynamic import, or build aliases.
Guides
- Access Control: Entity-level (allowApi*), row-level (apiPrefilter), and field-level (includeInApi, allowApiUpdate) authorization patterns.
- Admin UI: Built-in /api/admin CRUD UI with entity diagram, gated by allow and configurable via the admin option.
- Modules: Modules system (3.0.6+) - bundle entities, controllers, and server code as local, library, or cloned packages.
- Community modules: Curated list of community modules - Better-Auth, ChangeLog, Cron, Mail.
Escape Hatches
- Custom/SQL Filters: Filter.createCustom - reusable, parameterized server-side filters callable from the frontend.
- Direct Database Access: Run raw SQL via SqlDatabase.getDb(), dbNamesOf for safe identifiers, and param() for bound parameters.
- Using in Non-Remult Routes: withRemult / withRemultAsync to use repo() and remult.user in custom routes outside the CRUD/BackendMethod flow.
- Avoiding Decorators: Define entities, controllers, and backend methods without decorators using describeEntity / describeClass / describeBackendMethods.
- Extensibility: Augment UserInfo, FieldOptions, EntityOptions, and RemultContext via TypeScript declaration merging.
Integrations
- Open API: Generate OpenAPI doc from entities and serve a Swagger UI for the REST API.
- GraphQL: Expose entities as a GraphQL schema via remultGraphql + graphql-yoga (Express, Next.js, SvelteKit).
- Standard Schema: standardSchema(repo(Entity)) - use entities as Standard Schema validators interoperable with zod, valibot, ArkType.
API Reference
- Entity
- Field
- ValueConverter
- Validation: Field validation - required/minLength shortcuts, custom validate functions, and the built-in Validators set.
- Validators
- Relations
- RelationOptions
- Remult
- ApiClient
- Repository
- RemultServerOptions
- EntityFilter: EntityFilter operators - $in, $ne, $gt/$gte/$lt/$lte, contains, $and/$or, $not - for where clauses.
- EntityMetadata
- FieldMetadata
- Allowed: The Allowed type - boolean, role, role array, or predicate - used by allowApi* and BackendMethod permissions.
- BackendMethod
- QueryResult
- Paginator
- LiveQuery
- LiveQueryChangeInfo
- Filter
- Sort
- SqlDatabase
- SubscriptionChannel
- generateMigrations
- migrate
- Async Hooks
- REST API Spec: Auto-generated REST endpoints per entity - GET/POST/PUT/DELETE with sort, filter, select, paging.
- EntityBase
- IdEntity
- EntityRef
- FieldRef
- getEntityRef
- getFields
Tutorials
Each framework tutorial walks through the same 10 lessons (Setup, Entities, Paging/Sorting/Filtering, CRUD, Validation, Live Queries, Backend methods, Auth, Database, Deployment) with framework-specific code samples.
React Tutorial (canonical)
- Setup: Bootstrap a React + Vite + Express + Remult todo app, via starter clone or step-by-step setup.
- Entities: Define the Task @Entity with @Fields.id, .string, .boolean, .createdAt and register it via remultApi.
- Paging, Sorting and Filtering: Apply server-side limit, orderBy and where options to repo.find() for paging, sorting and filtering.
- CRUD Operations: Wire repo.insert, repo.save and repo.delete to add, toggle, rename and remove tasks from the UI.
- Validation: Field-level Validators.required and custom validate arrow functions enforced on client and server.
- Live Queries: Replace repo.find with repo.liveQuery().subscribe in useEffect for realtime multi-user updates.
- Backend methods: Refactor a bulk client loop into a static @BackendMethod on a TasksController to run server-side.
- Authentication and Authorization: Gate entities and BackendMethods with allowApiCrud, Allow.authenticated and role-based rules via cookie-session.
- Database: Swap the JSON-file store for Postgres via createPostgresDataProvider in the remultApi config.
- Deployment: Deploy the unified React + Express app to railway.app with compression, helmet and DATABASE_URL.
Same tutorial, other frameworks
- Angular Tutorial: Same 10-lesson structure as the React tutorial above, with Angular-specific code samples.
- Vue Tutorial: Same 10-lesson structure as the React tutorial above, with Vue-specific code samples.
- SvelteKit Tutorial: Same 10-lesson structure as the React tutorial above, with SvelteKit-specific code samples.
- Next.js Tutorial: Same 10-lesson structure as the React tutorial above, with Next.js-specific code samples.
- SolidStart Tutorial: Same 10-lesson structure as the React tutorial above, with SolidStart-specific code samples.
Interactive Tutorial
Hands-on, browser-based tutorial at https://learn.remult.dev.
Basics
Introduction
- Welcome to the Remult Tutorial: Tutorial overview and what you'll build (a real-time todo app).
- Entity: Define the Task @Entity with @Fields.id, @Fields.string, @Fields.boolean, and @Fields.createdAt.
- Rest Api: Wire the Task entity into an Express server via remultApi({ entities: [Task] }).
- Insert Data on the Backend: Seed sample tasks in initApi using repo(Task).insert() when the table is empty.
- Display the Task List: Fetch tasks from the frontend with repo(Task).find() inside useEffect and render them.
Querying Data
- Paging: Page results server-side by passing limit and page to repo(Task).find().
- Sorting: Sort results server-side via the orderBy option of repo(Task).find().
- Filtering: Filter results server-side with the where option of repo(Task).find().
Manipulating Data
- Insert: Add a new task via repo(Task).insert() from the form submit handler.
- Update: Toggle completion via repo(Task).update() bound to the checkbox onChange.
- Delete: Delete a task via repo(Task).delete() wired to a Delete button.
Validation
- Required: Mark the title field required: true so the same rule runs on frontend and API.
- Built-In Validations: Apply built-in Validators (minLength, maxLength) and chain them with custom messages.
- Custom Validations: Write a custom validate function on a field that returns true or an error message.
Live Query
- Live Query: Demonstrate the stale-data problem when multiple users edit without real-time sync.
- Realtime Updates: Swap the one-shot find for repo(Task).liveQuery().subscribe and drop manual state updates.
Backend Methods
- Updating Multiple Tasks: Add a setAllCompleted loop on the client that updates every task one PUT at a time.
- Refactor to Backend: Move setAllCompleted into a @BackendMethod on TasksController and call it from the client.
Authentication & Authorization
- Authentication and Authorization: Gate CRUD with allowApiCrud: remult.authenticated and lock the @BackendMethod with allowed: remult.authenticated.
- Authentication: Build an AuthController with signIn/signOut @BackendMethods backed by cookie-session and getUser.
- Role-based Authorization: Restrict insert/delete to the 'admin' role via allowApiInsert and allowApiDelete, plus assign roles on signIn.
- Role-based Authorization on the Frontend: Conditionally render the form and Delete button using repo.metadata.apiInsertAllowed and apiDeleteAllowed.
Database
- Database: Switch storage from JSON file to SQLite by setting dataProvider to SqlDatabase with Sqlite3DataProvider.
In Depth
Relations
- Many to One: Many-to-one relations via @Relations.toOne on the child entity, with include and defaultIncluded for eager loading.
- One to Many: One-to-many relations via @Relations.toMany, with repo.relations(parent).child.find/insert for scoped operations.
- Id Based Relations: Expose the foreign key as a field and wire @Relations.toOne<Order, Customer> to it via the fields option.
- Many to Many: Many-to-many via a join entity with a composite primary key and @Relations.toOne on each side.
Advanced Filtering
- Custom Filter: Encapsulate reusable, parameterized server-side filters with Filter.createCustom and compose them via $and.
- Filter Based on Relation: Filter by related-entity fields with a custom filter that queries the related repo and feeds IDs into the parent query.
- Filter Based on Relation Using SQL: Custom filters that emit raw SQL via SqlDatabase.rawFilter, dbNamesOf, and filterToRaw for cross-table predicates.
- Sql Relations Filter: Filter by related entities declaratively with sqlRelationsFilter(...).relation.some(condition) compiled to SQL.
Sql Expression Entity Field
- Introduction: Computed fields via sqlExpression that aggregate from other tables and remain sortable and filterable.
- Getting a field from a relation: Pull a related-entity column into a sqlExpression field via subquery for inline sort and filter.
- Sql Relations: Derive fields from relations with sqlRelations, including .$count(filter) and .$subQuery for SQL aggregations.
Access Control
- Intro & Field-Level Authorization: Per-field access control with allowApiUpdate and includeInApi - booleans, roles, or row-aware arrow functions.
- Row-Level Authorization: Row-level CRUD permissions via allowApiRead/Insert/Update/Delete using booleans, roles, or row-aware functions.
- Filtering Rows Based on User Permissions: Scope API rows by user with apiPrefilter, and mirror to server code with backendPrefilter.
- Filtering Related Rows Based on User Permissions: Reuse a static custom filter (allowedTasks) across apiPrefilter on parent and child entities, with a rawFilter SQL variant.
- Sql Relations Filter for User Permissions: Row-level access control on related entities via sqlRelationsFilter(...).relation.some(allowedFilter()).
Entities as a single source of truth
- Field Metadata: FieldMetadata for label and displayValue - drive consistent UI from repo(...).fields anywhere in the app.
- Forms and Validation: Bind ErrorInfo.modelState to per-field error UI and render dynamic forms from FieldMetadata and getValueList.
- Lifecycle Hooks: Entity lifecycle hooks - saving, saved, deleting, deleted, validation - with e.isNew, e.fields, and field.valueChanged().
- Select Fields: Define a slimmer read-only entity over the same table via dbName to fetch only a subset of columns.
- Extend Entity (add fields): Split a wide entity into a base plus an extension entity sharing the same dbName for opt-in extra fields.
Testing
- Introduction to Testing with Remult: Swap remult.dataProvider to InMemoryDataProvider or in-memory SQLite (with ensureSchema) for fast entity tests.
- Testing Api Rules: Test API rules by wrapping a data provider with TestApiDataProvider and toggling remult.user across cases.
Examples
Validations
- Extending Existing Validations: Compose built-in validators (e.g. Validators.unique) inside a field's validate function for conditional rules.
Agent Skill
- Remult Skill: Install with
npx skills add https://remult.devso AI agents (Claude Code, Cursor, ...) know Remult conventions - @Entity, repo(), lifecycle hooks, permissions, ValueList enums, the dual-entity pattern.
Meet the modern standard for public facing documentation. Beautiful out of the box, easy to maintain, and optimized for user engagement.
Search through billions of items for similar matches to any object, in milliseconds. It’s the next generation of search, an API call away.
Build and deploy reliable background jobs with no timeouts and no infrastructure to manage.
Get the simple developer experience of SQLite in production, and scale your multi-tenant backend with unlimited databases.
Upstash is a serverless data platform providing low latency and high scalability for real-time applications.
One-click deployments built for teams, tuned for Laravel, loaded with tools and goodies you're going to love.