Sign In

specshot

Package Overview
Dependencies
Maintainers
1
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

specshot

Fire an OpenAPI spec, get strictly-typed TypeScript code and a robust API mock server — zero-dependency, Zod-validated, and highly customizable.

latest
Source
npmnpm
Version
3.0.9
Version published
Maintainers
1
Created
Source

SpecShot Logo

SpecShot

One command. Zero dependencies. 100% type-safe API client.

Drop an OpenAPI spec in, get production-ready TypeScript out. No SDKs to install. No generated bloat to maintain. You own every line — like shadcn/ui, but for your API layer.

Why SpecShot?

Instead of...You get...
Vendor lock-in SDKsCode you own, edit, and extend
Black-box generators100% customizable Handlebars templates
Hardcoded architectureBring your own patterns (Classes, Hooks, Functions)
Untyped fetch()Strictly typed endpoints and models

What you get

  • Template-Driven Engine — SpecShot doesn't dictate your architecture. It ships with robust built-in presets (class, functional), but you can easily eject and modify the Handlebars templates to match your exact team standards.
  • Custom Code Preservation — Write your own custom methods directly inside the generated files using magic comments (// --- CUSTOM CODE START ---). Your code survives the next generation.
  • 100% Code Ownership — Generate it once, own it forever. No proprietary libraries or hidden runtime dependencies injected into your project unless your chosen template requires them.
  • Built-in Mock Server — Instantly spin up a local Mock API dashboard that serves realistic data generated from your OpenAPI spec.

30 Seconds

# 1. Scaffold the core
npx specshot init

# 2. Point at your spec
npx specshot generate --url http://localhost:8080/openapi.json

# 3. Use it
import { clientApi, defaultClient } from "./lib/api/default";

// Override the base URL if needed
defaultClient.options.baseUrl = "https://api.myprod.com";

// Everything is typed — no generics, no casting
const { data, error, ok } = await clientApi.pets.listPets();
const { data: pet } = await clientApi.pets.getPet("abc123");
const result = await clientApi.pets.createPet({
  name: "Buddy",
  species: "dog",
});

That's it. No config files. No code generation pipelines. Just typed API calls.

Commands

1. init (One-time setup)

Creates a specshot.config.mjs configuration file with your preferences. No files are installed — generate handles all installation.

Interactive mode:

npx specshot init

Non-interactive mode (CI/CD friendly):

npx specshot init \
  --preset class \
  --url http://localhost:8080/openapi.json
FlagDescription
--preset <name>Preset: class, functional, or community/custom
--templates, -t <dir>Custom Handlebars templates directory
--url, -u <url>OpenAPI JSON URL to save in config for later generation

2. generate (Run repeatedly on API updates)

Installs the API core infrastructure (if missing), then reads your OpenAPI spec to generate strictly-typed API services, Zod schemas, and models.

Presets

Choose a built-in code style with --preset:

PresetStyleDependenciesResult pattern
class (default)BaseService + ApiClient + ZodzodPromise<{ data, error, ok }>
functionalStandalone async function + native fetch()nonePromise<T> (throws on error)
npx specshot generate --preset functional

Or set it in config:

export default {
  preset: "functional",
  apis: { ... }
};

If you already provided a --url during init (which saves it to specshot.config.mjs), you can simply run:

npx specshot generate

(No flags or prompts required! Perfect for an npm run api:sync script.)

Or, if you want to override the source:

npx specshot generate --url http://localhost:8080/openapi.json

Auto-install: When using built-in templates, generate automatically installs the API Core (ApiClient, BaseService, types) and Provider skeleton (client.ts, plugins, hooks) if they don't already exist. When using custom templates, infrastructure installation is skipped.

generate options

FlagDescription
--url, -u <url>Remote OpenAPI spec URL
--file, -f <path>Local OpenAPI JSON file
--output, -o <dir>Output directory
--alias, -a <alias>Import alias (e.g. @/lib/api)
--config, -c <path>Custom config file path
--templates, -t <dir>Custom Handlebars templates (partial override)
--preset <name>Built-in preset: class, functional
-w, --watchWatch for changes and auto-regenerate
--dry-runPreview without writing files
--mswGenerate MSW mock handlers
--force-scaffoldForce regenerate scaffold files, overwriting existing ones

3. templates (Manage Handlebars templates)

Subcommands for template management:

templates eject

Copies a built-in or community preset to your project as a custom preset so you can customize it. Only the templates you edit will override the built-ins — missing files automatically fall back to defaults.

npx specshot templates eject class
npx specshot templates eject functional --output ./my-templates
FlagDescription
--output, -o <dir>Output directory (default: .specshot/templates/presets/)
--generator-onlyEject only generator templates
--msw-onlyEject only MSW templates

templates list

Shows all available templates and their current override status (built-in / dir override / per-file override).

npx specshot templates list

templates context <name>

Shows all available variables and naming helpers for a specific template.

npx specshot templates context service
npx specshot templates context models

templates install <package>

Install a community preset from npm or GitHub:

npx specshot templates install github:user/my-preset

templates uninstall <preset>

Remove an installed community preset:

npx specshot templates uninstall my-preset

templates validate

Validate preset structure and _preset.json for community templates:

npx specshot templates validate

Then generate with your custom templates:

npx specshot generate --templates ./my-templates

Template structure

my-templates/
  models.hbs              # Generator: shared Zod schemas + types
  types.hbs               # Generator: per-tag request/response types
  service.hbs             # Generator: per-tag service class
  index.hbs               # Generator: provider index + clientApi export
  plugins-index.hbs       # Generator: plugin auto-wiring
  msw/
    handlers.hbs          # MSW: per-tag http.<method>() handlers
    index.hbs             # MSW: handler barrel export
    browser.hbs           # MSW: setupWorker entry

Partial override

You don't need to copy all templates. Place only the files you want to customize in your override directory. Any missing file will use the built-in default automatically.

For example, to customize only the service template:

my-templates/
  service.hbs    # Your custom version
npx specshot generate --templates ./my-templates
# models.hbs, types.hbs, index.hbs → built-in defaults
# service.hbs → your custom version

Template context

Templates use standard Handlebars syntax. Key variables available:

TemplateContext variables
models.hbsschemas (shared), version, customCode
types.hbstag, imports, specificSchemas, operations, customCode
service.hbsclassName, tagPrefix, exportsToReExport, operations, corePath, customCode
index.hbsservices, corePath, pluginsPath, customCode
handlers.hbstag, tagLowerCase, handlers, typeImports, usesFaker, typesImportPath

Each generated file preserves a // --- CUSTOM CODE START --- / // --- CUSTOM CODE END --- block so your hand-written code survives regeneration.

Handlebars naming helpers

Custom templates can use built-in naming helpers:

HelperExample inputOutput
capitalizepetsPets
camelCasepet-storepetStore
pascalCasepet-storePetStore
kebabCasePetStorepet-store
snakeCasePetStorepet_store
toLowerCasePetStorepetstore
toUpperCasepetstorePETSTORE
ifEq{{#ifEq tag "pets"}}...{{/ifEq}}Conditional block
ifNeq{{#ifNeq tag "users"}}...{{/ifNeq}}Negated conditional

File naming configuration

Control generated file names via fileNaming in config:

export default {
  apis: {
    petstore: {
      openapiUrl: "./openapi.json",
      fileNaming: {
        models: "schemas", // → schemas.ts
        service: "{{pascalCase tag}}Service", // → PetsService.ts
        types: "{{pascalCase tag}}Types", // → PetsTypes.ts
        index: "index", // → index.ts
      },
    },
  },
};

Custom output paths

Control WHERE generated files go via outputPaths in config:

export default {
  apis: {
    default: {
      openapiUrl: "./openapi.json",
      outputPaths: {
        models: "src/models",
        services: "src/services",
        types: "src/types",
        index: "src/api",
      },
    },
  },
};

Import paths between files are computed automatically. See docs/template-variables.md for full reference.

Editor autocompletion

SpecShot provides autocompletion for both config files and templates:

Config files (specshot.config.mjs):

/**
 * @typedef {Object} TemplateData
 * @property {"react-query" | "swr" | "none"} [hook] - Hooks framework
 * @property {("bearer" | "logger" | "request-id" | "circuit-breaker")[]} [pluginNames] - Plugins to generate
 * @property {"types-only" | "zod-schemas" | "zod-runtime"} [validation] - Validation strictness mode
 */
/** @type {import('specshot').SpecshotConfig<TemplateData>} */
export default {
  // Autocompletion works in VS Code with the TypeScript language server
  preset: "functional",
  apis: {/* ... */},
  templateData: {
    hook: "none",
    pluginNames: [],
    validation: "zod-runtime",
  },
};

For JSON config files (specshot.config.json), add a $schema reference:

{
  "$schema": "https://specshot.dev/config.schema.json",
  "preset": "functional"
}

Template files (.hbs):

  • Run specshot templates context <name> to see available variables in the CLI
  • See docs/template-variables.md for the full reference

mock (Zero-config API Mocking)

SpecShot includes a powerful built-in mock server and Web Dashboard. No MSW or complex setup required.

npx specshot mock --web --proxy http://localhost:3000
FlagDescription
--webLaunch the interactive Web Dashboard (SPA)
--proxy, -p <url>Proxy un-mocked requests to a real backend
--port <number>Port for the mock API server (default: 3457)
--no-openPrevent opening the browser automatically

🎛️ Mock Dashboard Features

When you run with --web, SpecShot opens a beautiful dashboard where you can:

  • Toggle Endpoints: Turn mock responses on/off per endpoint.
  • Set Latency & Errors: Simulate slow networks or 500/400 error states instantly.
  • Customize Data (Faker.js): Use the searchable dropdown to map specific JSON fields to Faker.js functions (e.g., internet.email, image.url).
  • Manual Overrides: Write custom JSON payloads directly in the browser.
  • WebSocket Mocking: Configure WebSocket endpoints and push events to connected clients in real-time from the dashboard.

(Mock configurations and overrides are automatically saved to .specshot/mocks.json so your team can share the same mock state!)

specshot.config.mjs

/**
 * @typedef {Object} TemplateData
 * @property {"react-query" | "swr" | "none"} [hook] - Hooks framework
 * @property {("bearer" | "logger" | "request-id" | "circuit-breaker")[]} [pluginNames] - Plugins to generate
 * @property {"types-only" | "zod-schemas" | "zod-runtime"} [validation] - Validation strictness mode
 */
/**
 * @typedef {Object} Overrides
 * @property {string} [dir]
 * @property {string} [browser]
 * @property {string} [core]
 * @property {string} [handlerPerTag]
 * @property {string} [index]
 * @property {string} [plugins]
 * @property {string} [provider]
 * @property {string} [servicePerTag]
 * @property {string} [typesPerTag]
 */
/** @type {import('specshot').SpecshotConfig<TemplateData, Overrides>} */
export default {
  preset: "class", // class or functional
  templates: "src/lib/api/templates", // string (dir) or object (per-file)

  // Custom Faker.js plugins for mock generation
  fakerPlugins: [
    {
      name: "custom-image",
      match: (ctx) => ctx.path.endsWith("imageUrl"),
      generate: (faker) => faker.image.url(),
    },
  ],

  // Template data passed to all templates
  templateData: {
    hook: "swr", // swr, react-query, or none
    pluginNames: ["bearer", "logger"], // plugins to generate
    validation: "zod-runtime", // strict runtime data validation
  },

  // Define your APIs
  apis: {
    petstore: {
      // openapiUrl supports:
      // 1. Backend URL (e.g., "http://localhost:8080/openapi.json")
      // 2. Local File (e.g., "./openapi.json")
      openapiUrl: "http://localhost:8080/openapi.json",
    },
    payment: {
      openapiUrl: "http://api.staging.com/payment/openapi.json",
    },
  },
};

Examples

ExampleWhat it shows
examples/local-fileGenerate from a openapi.json on disk
examples/remote-urlFetch from a running backend + mock server
examples/real-or-fakeFull-stack usage with the mock server
examples/design-patternsSingleton, Factory, Observer, Builder service patterns

Development

npm install
npm run build
npm test
npm run lint

Built by the open-source community

Keywords

openapi

FAQs

Package last updated on 31 Jul 2026

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts