phantomback
v2.0.2
Published
Two tools, one package. Fake Backend: drop in your API schema → instant stateful REST server with realistic data, JWT auth, pagination, filtering & sorting. Reality Mode: flip one flag → random failures, latency spikes, connection drops & corrupted respon
Maintainers
Readme
👻 PhantomBack
Instant Fake Backend · Chaos Engineering · Reality Mode
Two tools, one package — everything you need to build and harden frontends without a real backend.
Fake Backend — Drop in your API schema → get a fully functional REST server with realistic data, JWT auth, pagination, filtering, sorting, search, and nested routes in seconds.
Reality Mode — Flip one flag and your fake API starts behaving like a broken production server: random failures, latency spikes, connection drops, corrupted responses, and timeouts — so your error handling actually gets tested.
Documentation · Getting Started · Reality Mode · API Reference · Playground · GitHub
Why PhantomBack?
Fake Backend
| Pain point | PhantomBack fix | |---|---| | Backend not ready yet | Full REST API in one command | | Static JSON mocks feel fake | Stateful CRUD with realistic Faker data | | No pagination / filtering in mocks | Full query support out of the box | | Auth testing is painful | JWT auth simulation built-in | | Mock server setup takes time | One command or one line of code |
Reality Mode — Chaos Engineering
| Pain point | PhantomBack fix |
|---|---|
| Error handling never gets tested | Random 5xx failures on every request |
| Network issues are hard to reproduce | Configurable latency spikes and jitter |
| Connection drops catch you off guard | Simulated TCP drops via connectionDropRate |
| Bad JSON is untested | Malformed response injection via corruptionRate |
| Timeout handling is always skipped | Hanging responses via timeoutRate |
Quick Start
Install
npm install -g phantomback # CLI (global)
npm install --save-dev phantomback # Library (project)Zero-config — one command, full API
phantomback start --zeroYou now have a REST API at http://localhost:3777 with:
| Resource | Count | Auth |
|---|---|---|
| /api/users | 25 records | 🔒 Protected |
| /api/posts | 50 records | — |
| /api/comments | 100 records | — |
| /api/products | 30 records | — |
| /api/todos | 40 records | — |
Or bring your own schema
phantomback init # generates phantom.config.js
phantomback start # reads config and starts serverOr use as a library
import { createPhantom } from 'phantomback';
const server = await createPhantom({
port: 3777,
resources: {
users: {
fields: {
name: { type: 'name', required: true },
email: { type: 'email', unique: true },
role: { type: 'enum', values: ['admin', 'user'] },
},
seed: 25,
},
},
});
// server.stop() — shut down
// server.reset() — re-seed all data
// server.getStore() — export current stateOne-liner for zero-config:
import { createPhantomZero } from 'phantomback';
await createPhantomZero(); // Full demo API on port 3777Reality Mode — one flag, instant chaos
phantomback start --zero --chaosYour same fake API now randomly:
| What happens | How often (defaults) | |---|---| | Injects latency spikes (200–5000 ms) | ~30% of requests | | Returns a random 5xx error | 10% of requests | | Drops the TCP connection | 2% of requests | | Sends malformed / partial JSON | 2% of requests | | Hangs the response (~30 s) | 3% of requests |
Or enable with custom rates:
phantomback start --chaos --chaos-failure 0.2 --chaos-latency 300,2000Configuration
Create phantom.config.js in your project root:
export default {
port: 3777,
prefix: '/api',
// latency: 500, // fixed delay (ms)
// latency: [200, 800], // random range
auth: {
secret: 'my-secret-key',
expiresIn: '24h',
},
resources: {
users: {
fields: {
name: { type: 'name', required: true },
email: { type: 'email', unique: true },
age: { type: 'number', min: 18, max: 65 },
role: { type: 'enum', values: ['admin', 'user', 'moderator'] },
avatar: { type: 'avatar' },
isActive: { type: 'boolean' },
},
seed: 25,
auth: true, // protect with JWT
},
posts: {
fields: {
title: { type: 'title', required: true },
body: { type: 'paragraphs', count: 3 },
userId: { type: 'relation', resource: 'users' },
views: { type: 'number', min: 0, max: 10000 },
},
seed: 50,
},
},
};Full config reference → phantombackxdocs.vercel.app/docs/configuration
Supported Field Types
| Type | Generates | Options |
|---|---|---|
| name firstName lastName username | Names | — |
| email | Email | unique |
| phone | Phone number | — |
| avatar | Avatar URL | — |
| bio jobTitle | Profile text | — |
| sentence paragraph paragraphs | Text blocks | count |
| title description slug | Content | — |
| number float price rating | Numbers | min max precision |
| boolean | true / false | — |
| date pastDate futureDate | ISO dates | — |
| url image color | Misc | — |
| address city country | Location | — |
| product company | Business | — |
| enum | Random from list | values: [...] |
| relation | Foreign key | resource: '...' |
| uuid | UUID string | — |
Field Options
{
type: 'email',
required: true, // must be present on create
unique: true, // no duplicates allowed
min: 0, // number minimum
max: 100, // number maximum
}Auto-Generated Routes
Every resource gets full CRUD automatically:
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/users | List all (paginated) |
| GET | /api/users/:id | Get one |
| POST | /api/users | Create |
| PUT | /api/users/:id | Full update |
| PATCH | /api/users/:id | Partial update |
| DELETE | /api/users/:id | Delete |
Nested Routes
If posts has userId: { type: 'relation', resource: 'users' }, you automatically get:
GET /api/users/:id/posts → all posts by this userSpecial Routes
| Method | Endpoint | Description |
|---|---|---|
| GET | /api | List all endpoints |
| GET | /api/_health | Health check |
| POST | /api/auth/register | Register |
| POST | /api/auth/login | Login → JWT |
| GET | /api/auth/me | Current user (token required) |
Query Parameters
# Pagination
GET /api/users?page=2&limit=10
GET /api/users?offset=20&limit=10
# Filtering
GET /api/users?role=admin # exact match
GET /api/users?age_gte=18 # ≥
GET /api/users?age_lte=30 # ≤
GET /api/users?age_gt=18&age_lt=30 # range
GET /api/users?role_ne=admin # not equal
GET /api/users?name_like=john # contains
# Sorting
GET /api/users?sort=name # ascending
GET /api/users?sort=-name # descending
GET /api/users?sort=role,-age # multi-field
# Search
GET /api/users?q=john # full-text across all fields
# Field Selection
GET /api/users?fields=name,email,roleResponse includes pagination metadata:
{
"success": true,
"data": [ ... ],
"meta": {
"page": 2,
"limit": 10,
"total": 50,
"totalPages": 5,
"hasNext": true,
"hasPrev": true
}
}Authentication
# 1. Register
curl -X POST http://localhost:3777/api/auth/register \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]", "password": "secret123", "name": "John"}'
# 2. Login
curl -X POST http://localhost:3777/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]", "password": "secret123"}'
# 3. Use the token
curl http://localhost:3777/api/users \
-H "Authorization: Bearer <your-token>"Reality Mode — Chaos Engineering
PhantomBack's second core feature. Once your fake API works, flip Reality Mode on to test how your frontend actually handles broken backends.
Enable via CLI (quickest)
phantomback start --chaos # defaults
phantomback start --chaos --chaos-failure 0.2 # 20% failure rate
phantomback start --chaos --chaos-latency 500,3000 # 500–3000 ms jitterEnable via phantom.config.js (full control)
export default {
port: 3777,
resources: { /* your schema */ },
chaos: {
enabled: true,
latency: { min: 200, max: 5000 }, // random delay range (ms)
failureRate: 0.1, // 10% → random 5xx response
errorCodes: [500, 502, 503, 504], // which 5xx codes to use
connectionDropRate: 0.02, // 2% → TCP connection drop
corruptionRate: 0.02, // 2% → malformed JSON body
timeoutRate: 0.03, // 3% → response hangs ~30 s
scenarios: ['latency', 'failure', 'drop', 'corruption', 'timeout'],
},
};Chaos Scenarios
| Scenario | Config Key | Rate | What your frontend sees |
|---|---|---|---|
| latency | latency | ~30% | Slow response — spinner never ends |
| failure | failureRate | 10% | Random 500 / 502 / 503 / 504 |
| drop | connectionDropRate | 2% | Network error — socket closed mid-flight |
| corruption | corruptionRate | 2% | SyntaxError — invalid JSON received |
| timeout | timeoutRate | 3% | Request hangs — no response for ~30 s |
What to test with Reality Mode
- Loading states and spinners under slow networks
- Retry logic and exponential backoff
- Error boundaries and fallback UI
- Toast / notification error handling
- Request timeout cancellation (
AbortController) - Partial data rendering on corrupt responses
Full guide → phantombackxdocs.vercel.app/docs/reality-mode
CLI Reference
phantomback start # start with phantom.config.js
phantomback start --zero # zero-config demo mode
phantomback start --port 4000 # custom port
phantomback start --config ./my-api.config.js # custom config path
phantomback start --chaos # enable Reality Mode
phantomback start --chaos --chaos-failure 0.2 # 20% failure rate
phantomback start --chaos --chaos-latency 200,5000 # latency jitter range
phantomback init # generate starter config
phantomback --helpFull CLI docs → phantombackxdocs.vercel.app/docs/cli
Real-World Examples
export default {
resources: {
doctors: {
fields: {
name: { type: 'name', required: true },
specialization: { type: 'enum', values: ['Cardiology', 'Neurology', 'Orthopedics'] },
experience: { type: 'number', min: 1, max: 30 },
available: { type: 'boolean' },
},
seed: 15,
},
patients: {
fields: {
name: { type: 'name', required: true },
age: { type: 'number', min: 1, max: 100 },
bloodGroup: { type: 'enum', values: ['A+', 'A-', 'B+', 'B-', 'O+', 'O-'] },
doctorId: { type: 'relation', resource: 'doctors' },
},
seed: 40,
},
},
};export default {
resources: {
products: {
fields: {
name: { type: 'product', required: true },
price: { type: 'price' },
category: { type: 'enum', values: ['Electronics', 'Clothing', 'Books', 'Food'] },
inStock: { type: 'boolean' },
rating: { type: 'rating' },
},
seed: 100,
},
orders: {
fields: {
customerName: { type: 'name' },
total: { type: 'number', min: 10, max: 5000 },
status: { type: 'enum', values: ['pending', 'processing', 'shipped', 'delivered'] },
},
seed: 50,
},
},
};More examples → phantombackxdocs.vercel.app/docs/examples
Response Format
Success:
{
"success": true,
"data": { ... },
"meta": { "page": 1, "limit": 10, "total": 50, "totalPages": 5 }
}Error:
{
"success": false,
"error": { "status": 404, "message": "users with id \"abc\" not found" }
}Validation Error:
{
"success": false,
"error": {
"status": 400,
"message": "Validation failed",
"details": [{ "field": "email", "message": "\"email\" is required" }]
}
}License
MIT © Madhav Chaturvedi
Documentation · npm · GitHub · CLI Reference · Reality Mode · Playground
Made with ❤️ by Madhav Chaturvedi · LinkedIn · Instagram
