Getting Started
JSONExpress turns a JSON file into a running REST and GraphQL API with zero configuration. When you outgrow it, you add TypeScript schemas, swap in a real database, or wire up authentication — without rewriting anything you already built.
Prerequisites
- Node.js 18+
- npm or pnpm
Option A — Zero-Config JSON Mode
The fastest path to a running API. No TypeScript, no config file, no setup.
1. Create a project and install the boot preset
mkdir my-api && cd my-api
npm init -y
npm install @json-express/boot@json-express/boot is a dependency-only preset that bundles the recommended stack: in-memory adapter, Express transport, REST API, console logger, and /docs. It is the only package you need for the quickstart. The runtime entrypoint — npx json-express — is shipped by @json-express/core (which boot pulls in transitively).
2. Create a data file
mkdir dataCreate data/posts.json:
[
{"id":"1","title":"Hello JSONExpress","published":true},
{"id":"2","title":"Building APIs the easy way","published":true},
{"id":"3","title":"Draft post","published":false}
]3. Start the server
npx json-express
# Server started on http://localhost:3000
# Collections: posts (3 records)JSONExpress scans ./data/ for JSON files and creates a collection from each one.
4. Use the API
List all posts:
curl http://localhost:3000/posts
# [{"id":"1","title":"Hello JSONExpress","published":true},{"id":"2",...},{"id":"3",...}]Get a single post:
curl http://localhost:3000/posts/1
# {"id":"1","title":"Hello JSONExpress","published":true}Create a post:
curl -X POST http://localhost:3000/posts \
-H "Content-Type: application/json" \
-d '{"title":"Second post","published":false}'
# {"id":"2","title":"Second post","published":false}Update a post:
curl -X PATCH http://localhost:3000/posts/1 \
-H "Content-Type: application/json" \
-d '{"published":true}'
# {"id":"1","title":"Hello JSONExpress","published":true}Delete a post:
curl -X DELETE http://localhost:3000/posts/1
# 204 No ContentThat's the full CRUD surface — all from a single JSON file.
Option B — TypeScript Schema Mode
For when you need types, validation, field-level access control, and auto-generated GraphQL.
1. Define your first model
Create models/posts.ts:
import { defineModel, types } from '@json-express/core';
export default defineModel({
name: 'posts',
fields: {
id: types.id(),
title: types.string({ required: true, unique: true }),
published: types.boolean({ default: false }),
views: types.number({ default: 0 })
},
access: {
read: 'public',
create: 'admin',
update: 'owner',
delete: 'admin'
}
});The access block is field-level security — it controls which roles can call each operation. 'public' means no token required. 'admin' and 'owner' are enforced automatically by the auth middleware when installed.
If a TypeScript model and a JSON file share the same name, the model wins.
2. Start and test
npx json-express
# Server started on http://localhost:3000
# Collections: postscurl -X POST http://localhost:3000/posts \
-H "Content-Type: application/json" \
-d '{"title":"My first typed post"}'
# {"id":"1","title":"My first typed post","published":false,"views":0}
curl http://localhost:3000/posts
# [{"id":"1","title":"My first typed post","published":false,"views":0}]Default values (published: false, views: 0) are applied automatically. Sending a duplicate title will return a 409 Conflict because of unique: true.
Option C — With Authentication
Full user accounts, JWT tokens, protected routes — from one preset install.
1. Add the identity preset
npm install @json-express/preset-identityThis dependency-only preset installs plugin-identity, middleware-auth, email-console, kv-memory, and queue-memory in one step.
2. Set your secret
Create a .env file:
jex.auth.secret=your-secret-key-min-32-chars
jex.auth.exclude=/authjex.auth.exclude tells the auth middleware not to require a token for /auth/* itself (so registration and login work). Lowercase jex.* is preferred. JEX__AUTH__SECRET (uppercase, double-underscore) is the same key, accepted as a fallback for cloud platforms that forbid dots or lowercase env vars.
3. Start the server
npx json-express
# Server started on http://localhost:3000
# Auth routes: POST /auth/register, /auth/login, /auth/refresh, /auth/logout, …plugin-identity registers five schemas (users, roles, refreshTokens, emailVerificationTokens, passwordResetTokens) and mounts the /auth/* route group automatically.
4. Register, login, and make an authenticated request
Register:
curl -X POST http://localhost:3000/auth/register \
-H "Content-Type: application/json" \
-d '{"email":"alice@example.com","password":"securepassword"}'
# {"accessToken":"eyJ...","refreshToken":"eyJ...","user":{"id":"1","email":"alice@example.com","role":"user"}}Login:
curl -X POST http://localhost:3000/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"alice@example.com","password":"securepassword"}'
# {"accessToken":"eyJ...","refreshToken":"eyJ...","user":{...}}Authenticated request:
curl http://localhost:3000/posts \
-H "Authorization: Bearer eyJ..."Routes with access: { read: 'public' } work without a token. Routes with create: 'admin' or update: 'owner' require a valid JWT — middleware-auth validates it automatically.
What's Next
- Presets — bundle a stack into a single npm package
- Schemas & Models — field types, relations, hooks, and access control in depth
- Database Adapters — swap to
adapter-jsonfor file persistence - Architecture — understand the kernel, IoC container, and plugin lifecycle
- Identity & Auth — refresh token rotation, JWKS, email verification, and more