Skip to content

Getting Started

JSONExpress turns JSON files into a running REST and GraphQL API with zero configuration. When you outgrow the prototype, you can swap any layer of the stack (like swapping your memory adapter for Postgres, or Express for Fastify) — without changing your code.

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

bash
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

bash
mkdir data

Create data/posts.json:

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

bash
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:

bash
curl http://localhost:3000/posts
# [{"id":"1","title":"Hello JSONExpress","published":true},{"id":"2",...},{"id":"3",...}]

Get a single post:

bash
curl http://localhost:3000/posts/1
# {"id":"1","title":"Hello JSONExpress","published":true}

Create a post:

bash
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:

bash
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:

bash
curl -X DELETE http://localhost:3000/posts/1
# 204 No Content

That's the full CRUD surface — all from JSON files.


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:

typescript
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 JSON files share the same name, the model wins.

2. Start and test

bash
npx json-express
# Server started on http://localhost:3000
# Collections: posts
bash
curl -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

bash
npm install @json-express/preset-identity

This 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:

bash
jex.auth.secret=your-secret-key-min-32-chars
jex.auth.exclude=/auth

jex.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

bash
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:

bash
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:

bash
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:

bash
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-json for file persistence
  • Architecture — understand the kernel, IoC container, and plugin lifecycle
  • Identity & Auth — refresh token rotation, JWKS, email verification, and more