npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

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

Readme

👻 PhantomBack

Instant Fake Backend · Chaos Engineering · Reality Mode

npm version downloads license node

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 --zero

You 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 server

Or 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 state

One-liner for zero-config:

import { createPhantomZero } from 'phantomback';
await createPhantomZero(); // Full demo API on port 3777

Reality Mode — one flag, instant chaos

phantomback start --zero --chaos

Your 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,2000

Configuration

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 user

Special 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,role

Response 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 jitter

Enable 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 --help

Full 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