Schematica is a modern, collaborative API documentation platform built to bridge the gap between backend implementation and frontend consumption. It serves as a visual editor and viewer for OpenAPI 3.0 specifications, featuring real-time collaboration locks, optimistic UI updates, and a design-first philosophy.
This repository contains the Single Page Application (SPA) source code. Backend code as available at: https://github.com/Amir-Zouerami/schematica-api
Note: This project serves as a technical showcase. It was originally developed as an internal tool to solve specific workflow friction points in my previous engineering team.
- Design-First Editor: robust form-based editor for OpenAPI specs (Paths, Methods, Schemas) without needing to write raw YAML/JSON manually.
- Real-Time Concurrency Control: Implements a WebSocket-based locking mechanism (
Socket.IO) to prevent race conditions when multiple developers edit the same endpoint. - Smart cURL Import: Paste a cURL command, and the system auto-generates the OpenAPI path, parameters, and request body schema using WASM-powered parsing.
- Optimistic UI: Interactions feel instant. The UI updates immediately while the server processes the request in the background, rolling back gracefully on errors.
- Type-Safe Schemas: Uses auto-generated TypeScript definitions derived directly from the backend OpenAPI spec, ensuring frontend-backend contract alignment.
- Dark Mode Native: Built with a "dark-first" aesthetic using Tailwind CSS v4 and Shadcn UI.
This codebase was architected with scalability and maintainability in mind, moving away from "spaghetti code" towards a structured, domain-driven approach.
The project structure is loosely based on Feature-Sliced Design. It avoids the trap of organizing by "file type" (components/hooks/utils) and instead organizes by business domain:
app/: Global providers, styles, and store initialization.pages/: Route-level components (lazy loaded).widgets/: Compositional layers that combine features (e.g.,EndpointDetail,AuditTrail).features/: User interactions that bring value (e.g.,create-project,edit-endpoint). Contains the form logic and UI triggers.entities/: Business entities (User, Project, Endpoint). Contains the data fetching logic (queries/mutations) and types.shared/: Reusable UI primitives (buttons, inputs), generic hooks, and utility libraries.
- React 19 & Vite 6: Leveraging the latest React features and the blazing fast build times of Vite.
- TanStack Query v5: Handles server state, caching, invalidation strategies, and optimistic updates. This effectively removes the need for a global client-state store for API data.
- Zustand: Used sparingly for actual client state (e.g., UI preferences, active server selection) that doesn't belong in the URL or the Server Cache.
- React Hook Form & Zod: Schema-based form validation. We define the shape of the data once in Zod, and it drives the form validation and type inference.
- Monaco Editor: Embedded VS Code experience for editing raw JSON schemas.
- Biome: Used for lightning-fast linting and formatting, replacing the slower ESLint/Prettier combo in parts of the workflow.
any is strictly forbidden.
This project uses a dual-layer typing strategy:
- Generated Types:
src/shared/types/api-types.tsis auto-generated from the Backend's Swagger JSON. This ensures that if the Backend changes a DTO, the Frontend build fails immediately. - Strict Bridging: We use TypeScript interfaces to "bridge" the gap between the loose OpenAPI JSON structure (which allows arbitrary keys) and our strict React component props, ensuring runtime safety without casting to
any.
One of the standout features of Schematica is the ability to "Paste cURL" to generate an endpoint. Instead of using a heavy JS-based parser or regex that breaks easily, we use WebAssembly (WASM).
We utilize tree-sitter compiled to WASM to parse the Bash AST of the cURL command. This allows us to extract headers, body params, and URLs with the same robustness as a compiler.
- Implementation: The WASM files (
tree-sitter.wasm,tree-sitter-bash.wasm) live in thepublic/wasmdirectory. - Why WASM? Parsing complex shell commands with nested quotes and escaped characters is CPU intensive and error-prone in pure JavaScript regex. WASM provides near-native parsing speed and accuracy.
- Loader Trick: You might notice
src/curlconverter-wasm-loader.ts. This file patches the global scope to tell thecurlconverterlibrary exactly where to find our static.wasmassets, bypassing its default behavior of fetching from a CDN.
To handle multi-user collaboration, we implement a two-layer concurrency strategy:
-
Optimistic Locking (HTTP): Every "Update" request sends a
lastKnownUpdatedAttimestamp. The backend compares this against the database record.- Scenario: User A opens an endpoint. User B opens the same endpoint and saves a change. User A tries to save.
- Result: The API returns
409 Conflict. - UI Handling: A specialized "Conflict Resolution" dialog appears, showing a diff of User A's changes vs. the new Server State, allowing User A to overwrite or discard.
-
Pessimistic Locking (Socket.IO): When a user clicks "Edit Endpoint", the frontend emits a
lock_acquireevent.- Effect: Other connected clients viewing that endpoint immediately see a "Locked by [User]" badge and the edit button becomes disabled.
- Auto-Release: The lock is automatically released via the
useBeforeUnloadhook if the tab is closed, or if the socket disconnects.
OpenAPI specs are full of $ref pointers (e.g., "$ref": "#/components/schemas/User"). Rendering these raw is useless to a human.
We implemented a recursive resolver in src/shared/lib/schemaUtils.ts that:
- Traverses the JSON structure deeply.
- Resolves local references instantly.
- Detects Circular Dependencies (e.g., A User has a Team, which has Users...) and halts recursion gracefully to prevent stack overflows, rendering a
[Circular Reference]badge instead.
This frontend is designed to be served statically by the backend in production, but runs independently during development.
- Node.js 20+
- Bun (Preferred package manager, though
npm/pnpmwork) - Backend Running: You need the API running locally. Get the Backend Here.
-
Clone the Repo:
git clone https://github.com/Amir-Zouerami/schematica-frontend.git cd schematica-frontend -
Install Dependencies:
bun install
-
Environment Setup: Create a
.envfile in the root:VITE_API_URL=http://localhost:3000 VITE_WEBSOCKET_URL=http://localhost:3000 VITE_BRAND_NAME=Schematica
-
Run Development Server:
bun dev
The app will be available at
http://localhost:8080.
To simplify deployment, Schematica is designed to be served directly by the NestJS backend. We avoid the complexity of maintaining two separate production servers (Frontend vs. Backend) by compiling the SPA into static assets.
The vite.config.ts is configured with a specific outDir strategy. It assumes you have cloned the frontend and backend repositories side-by-side in the same parent directory:
/workspace
βββ schematica-api/ <-- NestJS Backend
βββ schematica-frontend/ <-- This Repo
When you run the build command:
bun run buildVite will:
- Compile the TypeScript/React code to optimized ES2022 JavaScript.
- Chunk vendor libraries (React, Monaco Editor) separately for better caching.
- Output the files directly into
../schematica-api/public.
Once built, you simply start the Backend, and it serves the Frontend at the root URL (/). This creates a monolithic-feeling deployment artifact while maintaining a decoupled development experience.
β οΈ Important regarding WASM: The build process expects the.wasmfiles to be present in the public assets. If you change the build pipeline, ensurepublic/wasm/*.wasmfiles are copied correctly to the final dist folder, or the cURL converter will fail silently.
This project is open-source under the MIT License, and I highly encourage you to fork it, tear it apart, and rebuild it to fit your own team's workflows.
However, I am not accepting Pull Requests at this time.
This repository serves three primary purposes:
- A Portfolio Piece: It demonstrates my architectural decisions, coding standards, and approach to complex frontend engineering.
- Helping The Community: It gives back to the community i hold so dearly, the open-source community. If you need such a platform for you company, feel free to use it.
- An Archive: It preserves the state of an internal tool I built for a specific company context.
While I won't be merging external code, I am happy to discuss the architecture or answer questions in the Issues tab.
This project is MIT licensed.
