An offline-first, browser-based developer workbench for designing, validating, documenting, testing and shipping OpenAPI / Swagger API specifications. It runs entirely in the browser nothing is uploaded, no server is required, and all data lives in your browser's IndexedDB.
- Highlights
- Feature guide
- Keyboard shortcuts
- Tech stack
- Getting started
- Scripts
- Architecture
- Project structure
- Data & storage
- Tests
- Build notes
- Zero backend. Parsing, validation, generation and testing all run in the browser.
- Offline-first PWA. Installable, cached by a service worker, works without a connection.
- Multi-spec projects. Each project can hold several YAML/JSON spec files with a designated main file.
- Local-first persistence. Projects, environments, request history and revisions are stored in IndexedDB.
- Full lifecycle tooling. From editing → validating → documenting → testing → security review → codegen, all in one place.
The landing screen shown when no project is open:
- Create a project — name it and pick a starter template:
minimal- blank specpetstore- classic Petstore examplecrud- CRUD example with common resource patternsauth- OAuth2 / API-key secured examplemicroservice- larger service-oriented exampleecommerce- storefront API example
- Import project (.zip) - restore a previously exported project.
- Export all projects - downloads a ZIP bundle of every project.
- Recent projects - list of stored projects with detected spec version, file sizes, and delete (with confirmation).
- Stats: number of projects, total spec files, total storage size, template count.
Monaco-based YAML/JSON editor with:
- Live, debounced validation and linting; problems are shown as editor markers and in the Problems pane (open via the toolbar,
Ctrl+Shift+M). - Jump to a problem line directly from the Problems pane.
- Word wrap, minimap, tab size and font size controls (from Settings).
- Format to YAML — re-serializes the active file (JSON input included) as pretty YAML.
- Export current file — downloads the active spec in its native format.
- Multiple open files via editor tabs; files can be created from the Explorer or the command palette.
- Auto-re-analyze on every edit (debounced) so docs, tests, quality and codegen stay in sync.
A read-only overview of the whole API surface:
- All tags and their operations.
- Each operation's method, path, summary, parameters and responses.
- Security schemes referenced across the API.
- Generates a full Markdown reference from the active spec: info, servers, endpoints grouped by tag, parameters, request bodies and responses.
- Rendered in-app with
marked+dompurify(sanitized HTML), so it is safe to view. - Export Markdown downloads
api-docs.mdfor use in docs sites, wikis or CI publishing.
Send requests from inside the browser:
- Request builder with tabs for Query params, Headers, Body and Auth.
- Environment variables — define environments per project; values are interpolated into the request (e.g.
{{baseUrl}}). - Load request from spec — populate the tester from any endpoint of the active spec (path, method, parameters).
- Send executes the request in-browser (fetch-based); inspect status, time, size and the response body.
- curl preview — shows the equivalent
curlcommand for the current request. - Request history — past requests per project, with the ability to re-run them.
- Browse every component schema in the spec.
- Example generation — generate realistic example payloads from a schema in multiple modes (sample values, minimal, full/randomized).
- Inspect schema properties, types and constraints.
- Compare the active spec against another pasted spec or against a selected revision.
- Uses a structured
diffSpecsanalysis — shows added, removed and changed endpoints, operations and schema-level changes. - Also usable to diff two arbitrary snippets by pasting a comparison spec.
Automated security review of the active spec:
- Findings for common security gaps (missing auth, insecure defaults, weak schemes, sensitive fields, etc.) with severity (critical / high / medium / low / info) and remediation hints.
- Secret scanning - detects possible hard-coded secrets (keys, tokens, passwords) in the spec text.
- Security schemes - summarizes the auth methods defined in the spec.
- Validation security diagnostics from the validator are surfaced too.
- Computes a quality score from structural, completeness, consistency and security inputs.
- Shows a grade plus a prioritized list of recommendations to raise the score.
Three generation modes:
- Client - from the active spec, target list includes:
- Languages: TypeScript, JavaScript, Python, Java, C#, Go, Kotlin, Swift, PHP, Ruby
- Frontend modules:
fetchAPI, Axios, TanStack React Query - Servers: Spring Boot, Express, NestJS, FastAPI, ASP.NET Core, Django, Go
- Options: package name, namespace/class, base URL, generate types, use Axios.
- Mock server - generates an in-browser runnable mock server (Node, Express, FastAPI, Python) returning responses derived from your spec.
- CI - generates pipeline configs for GitHub Actions, GitLab CI, Jenkins and Azure DevOps.
Every generated file can be previewed and downloaded individually, or all at once (Download all).
- Converts between Swagger 2.0, OpenAPI 3.0 and OpenAPI 3.1.
- Rewrites
$refs, security scheme and version-specific structures automatically. - Side-by-side view: source spec → converted result, with a Download button for the result.
- Only offers targets that are valid for the detected source version.
- Every save of the active project records a revision snapshot.
- View the revision list (newest first), open a diff against the current spec, and restore or delete any revision.
- Theme: dark, light, system, one-dark, high-contrast.
- Editor: font size, tab size, default format (YAML/JSON), word wrap, minimap.
- Validation: lint toggle + per-rule enable/disable for the spectral-style rules, debounce interval, max auto revisions.
- Shortcuts: view and customize key bindings (stored per profile).
- Layout: explorer / problems panel visibility and panel widths.
- Read-only JSON preview of the full settings object.
| Shortcut | Action |
|---|---|
Ctrl/Cmd+K |
Open command palette |
Ctrl/Cmd+S |
Save project |
Ctrl+N |
New file |
Ctrl+Shift+N |
New project |
Ctrl+Shift+M |
Go to problems |
Shift+Alt+F |
Format active file |
Ctrl+Shift+E |
Export current file |
Shortcuts are customizable in Settings and remapped from there.
| Area | Technology |
|---|---|
| UI | React 19, TypeScript, Vite 8 |
| State | Zustand |
| Editor | Monaco (@monaco-editor/react, monaco-editor 0.56) |
| Validation | AJV (ajv, ajv-draft-04, ajv-formats) + @apidevtools/openapi-schemas |
| Parsing | yaml (YAML ⇄ JS) |
| Persistence | IndexedDB via idb |
| Rendering docs | marked + dompurify |
| Diff | diff |
| ZIP import/export | jszip |
| Testing | Vitest + jsdom |
| PWA | vite-plugin-pwa (workbox, auto-update) |
| Layout | react-resizable-panels, react-router-dom |
| Icons | lucide-react + custom inline icon set |
npm install
npm run devOpen http://localhost:5173, create a project from a template (or import a .zip), and start editing the spec. Validation, docs, tester, quality and codegen update live from the active file.
Production build:
npm run build
npm run preview| Script | Description |
|---|---|
npm run dev |
Start the Vite dev server |
npm run build |
Type-check (tsc) then build |
npm run preview |
Preview the production build |
npm run typecheck |
Run tsc --noEmit |
npm run lint |
Run ESLint |
npm test |
Run tests once (Vitest) |
npm run test:watch |
Run tests in watch mode |
┌──────────────────────────────────────┐
│ App │
│ TopBar · ActivityBar · Explorer │
│ Main area (12 views) · StatusBar │
└───────────────┬──────────────────────┘
│
┌─────────────────────┼─────────────────────┐
│ │ │
┌──────────▼─────────┐ ┌─────────▼─────────┐ ┌─────────▼─────────┐
│ projectStore │ │ analysisStore │ │ testerStore │
│ projects, files, │ │ doc, report, │ │ requests, history │
│ environments, │ │ stats, quality │ │ env vars, send │
│ revisions, save │ │ analyze() │ │ │
└──────────┬─────────┘ └─────────┬─────────┘ └─────────┬─────────┘
│ │ │
┌──────────▼─────────────────────▼─────────────────────▼─────────┐
│ services/ db.ts │
│ IndexedDB persistence (projects, revisions, history) │
└───────────────────────────────────────────────────────────────┘
│
┌──────────▼─────────────────────────────────────────────────────┐
│ core/ (pure engine, no UI) │
│ openapi/ detect · inspect · validate · lint · diff · security │
│ quality · converter · docs · example · codegen · mock│
│ pipeline · yaml │
└────────────────────────────────────────────────────────────────┘
- Zustand stores hold UI state and orchestration:
projectStore(projects/files/environments/save),analysisStore(parse + validate + lint + quality on every edit),testerStore(requests + history),settingsStore(user prefs, theme, shortcuts, lint rules),uiStore(toasts, modals, panels, palette). core/is a pure engine — no React imports — so parsing, validation and generation logic is unit-testable in isolation.services/bridge the stores to IndexedDB, run HTTP requests, and expose the project service (naming, formatting helpers).- Themes are driven by CSS custom properties (
theme.css) and toggled viadata-theme/data-high-contrastattributes on<html>.
openapi-workbench/
├── index.html
├── vite.config.ts # Vite, React, PWA, vitest, worker alias
├── package.json
├── README.md
└── src/
├── main.tsx # entry point, CSS imports
├── App.tsx # shell: routing between views, global shortcuts
├── components/
│ ├── editor/ # MonacoEditor, monacoSetup (themes, workers)
│ ├── layout/ # TopBar, ActivityBar, Explorer, StatusBar, EditorTabs, ProblemsPane
│ ├── ui/ # primitives, Icons, Modal, Toast, Tabs, Tree, Tooltip
│ └── CommandPalette.tsx
├── core/ # pure engine
│ ├── openapi/ # detect, inspect, validate, lint, diff, security, quality, converter, generator/
│ ├── generator/ # docs, example, codegen, mock, pipeline
│ ├── utils/ # misc helpers
│ └── yaml.ts
├── features/ # feature pages (one per view)
│ ├── Workspace.tsx # editor view (tabs + Monaco + problems)
│ ├── Dashboard.tsx # project landing
│ └── Docs, Tester, Schemas, ApiMap, DiffTool, Security,
│ Quality, Codegen, Converter, History, Settings, FeatureShell
├── services/ # db (IndexedDB), requestRunner, exportService, projectService
├── stores/ # Zustand stores
├── styles/ # theme.css · components.css · app.css
├── templates/ # starter project templates (minimal, petstore, crud, auth, …)
├── types/ # shared TypeScript types
├── test/ # vitest setup
└── vite-env.d.ts
- IndexedDB (via
idb) stores:- Projects (name, description, files, main file, environments, timestamps).
- Revision history snapshots per project (created on save).
- Tester request history.
- ZIP import/export (
jszip) lets you back up or move projects between browsers/machines. - Privacy: no telemetry, no remote calls during editing; the only outbound requests are ones you explicitly send from the API Tester.
npm testUnit tests cover the core engine (YAML round-trip, version detection, validation of minimal specs, and more) using Vitest with jsdom.
- The build intentionally raises the PWA workbox
maximumFileSizeToCacheInBytes(to 12 MiB) because Monaco's TypeScript worker chunk (~7 MiB) exceeds the default 2 MiB precache limit. vite.config.tscontains a smallmonaco-worker-resolveplugin:monaco-editor'sexportsmap maps subpaths to./esm/vs/*.js(producing the doubled pathesm/vs/esm/vs/...), so the two worker imports (editor.worker?worker,json.worker?worker) are pre-resolved to their real files.- Languages (YAML/JSON) are auto-registered by importing the
monaco-editorroot entry;monacoSetup.tsonly defines the customow-dark/ow-lightthemes and the workerMonacoEnvironment.