|
1 | | -# 📘 Schematica: Modern Collaborative API Documentation Platform |
| 1 | +# 📘 Schematica Frontend |
2 | 2 |
|
3 | | - |
| 3 | + |
4 | 4 |
|
5 | | -This repository contains the **frontend source code** for Schematica. |
| 5 | +[](https://react.dev/) |
| 6 | +[](https://www.typescriptlang.org/) |
| 7 | +[](https://vitejs.dev/) |
| 8 | +[](https://tailwindcss.com/) |
| 9 | +[](https://opensource.org/licenses/MIT) |
6 | 10 |
|
7 | | -This is a personal project of mine that I developed a few years ago. It is an API documentation platform based on OpenAPI (similar to Swagger), but developed with a few more features and a better UI (IMHO), written from the ground up. |
| 11 | +**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. |
8 | 12 |
|
9 | | -The goal of this project was to automate a lot of the hassle of maintaining OpenAPI documentation and reduce the friction between backend and frontend teams. Please read the [✨ Features & Quirks](#-features--quirks) section to get an understanding of this project. |
| 13 | +> This repository contains the **Single Page Application (SPA)** source code. |
| 14 | +> Backend code as available at: https://github.com/Amir-Zouerami/schematica-api |
10 | 15 |
|
11 | | -</br> |
| 16 | +> **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. |
12 | 17 |
|
13 | | -## 🔗 Documentation |
| 18 | +--- |
14 | 19 |
|
15 | | -For a full documentation please visit the repository containing the backend code: |
| 20 | +## ✨ Key Features |
16 | 21 |
|
17 | | -- [Schematica's backend](https://github.com/Amir-Zouerami/schematica-backend) |
| 22 | +* **Design-First Editor:** robust form-based editor for OpenAPI specs (Paths, Methods, Schemas) without needing to write raw YAML/JSON manually. |
| 23 | +* **Real-Time Concurrency Control:** Implements a WebSocket-based locking mechanism (`Socket.IO`) to prevent race conditions when multiple developers edit the same endpoint. |
| 24 | +* **Smart cURL Import:** Paste a cURL command, and the system auto-generates the OpenAPI path, parameters, and request body schema using WASM-powered parsing. |
| 25 | +* **Optimistic UI:** Interactions feel instant. The UI updates immediately while the server processes the request in the background, rolling back gracefully on errors. |
| 26 | +* **Type-Safe Schemas:** Uses auto-generated TypeScript definitions derived directly from the backend OpenAPI spec, ensuring frontend-backend contract alignment. |
| 27 | +* **Dark Mode Native:** Built with a "dark-first" aesthetic using Tailwind CSS v4 and Shadcn UI. |
18 | 28 |
|
19 | | -</br> |
| 29 | +--- |
20 | 30 |
|
21 | | -<small>Created in a hurry by Amir Zouerami</small> |
| 31 | +## 🏗 Architecture & Tech Stack |
| 32 | + |
| 33 | +This codebase was architected with scalability and maintainability in mind, moving away from "spaghetti code" towards a structured, domain-driven approach. |
| 34 | + |
| 35 | +### 1. Feature-Sliced Design (FSD) Adaptation |
| 36 | +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**: |
| 37 | + |
| 38 | +* **`app/`**: Global providers, styles, and store initialization. |
| 39 | +* **`pages/`**: Route-level components (lazy loaded). |
| 40 | +* **`widgets/`**: Compositional layers that combine features (e.g., `EndpointDetail`, `AuditTrail`). |
| 41 | +* **`features/`**: User interactions that bring value (e.g., `create-project`, `edit-endpoint`). Contains the form logic and UI triggers. |
| 42 | +* **`entities/`**: Business entities (User, Project, Endpoint). Contains the data fetching logic (queries/mutations) and types. |
| 43 | +* **`shared/`**: Reusable UI primitives (buttons, inputs), generic hooks, and utility libraries. |
| 44 | + |
| 45 | +### 2. Core Technologies |
| 46 | + |
| 47 | +* **React 19 & Vite 6:** Leveraging the latest React features and the blazing fast build times of Vite. |
| 48 | +* **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. |
| 49 | +* **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. |
| 50 | +* **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. |
| 51 | +* **Monaco Editor:** Embedded VS Code experience for editing raw JSON schemas. |
| 52 | +* **Biome:** Used for lightning-fast linting and formatting, replacing the slower ESLint/Prettier combo in parts of the workflow. |
| 53 | + |
| 54 | +--- |
| 55 | + |
| 56 | +### 🔍 Type Safety Philosophy |
| 57 | + |
| 58 | +**`any` is strictly forbidden.** |
| 59 | + |
| 60 | +This project uses a dual-layer typing strategy: |
| 61 | +1. **Generated Types:** `src/shared/types/api-types.ts` is auto-generated from the Backend's Swagger JSON. This ensures that if the Backend changes a DTO, the Frontend build fails immediately. |
| 62 | +2. **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`. |
| 63 | + |
| 64 | +--- |
| 65 | + |
| 66 | +## 🛠 Technical Deep Dives |
| 67 | + |
| 68 | +### ⚡ WASM-Powered cURL Parsing |
| 69 | +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)**. |
| 70 | + |
| 71 | +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. |
| 72 | + |
| 73 | +* **Implementation:** The WASM files (`tree-sitter.wasm`, `tree-sitter-bash.wasm`) live in the `public/wasm` directory. |
| 74 | +* **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. |
| 75 | +* **Loader Trick:** You might notice `src/curlconverter-wasm-loader.ts`. This file patches the global scope to tell the `curlconverter` library exactly where to find our static `.wasm` assets, bypassing its default behavior of fetching from a CDN. |
| 76 | + |
| 77 | +### 🔒 Optimistic Concurrency & Locking |
| 78 | +To handle multi-user collaboration, we implement a two-layer concurrency strategy: |
| 79 | + |
| 80 | +1. **Optimistic Locking (HTTP):** |
| 81 | + Every "Update" request sends a `lastKnownUpdatedAt` timestamp. The backend compares this against the database record. |
| 82 | + * *Scenario:* User A opens an endpoint. User B opens the same endpoint and saves a change. User A tries to save. |
| 83 | + * *Result:* The API returns `409 Conflict`. |
| 84 | + * *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. |
| 85 | + |
| 86 | +2. **Pessimistic Locking (Socket.IO):** |
| 87 | + When a user clicks "Edit Endpoint", the frontend emits a `lock_acquire` event. |
| 88 | + * *Effect:* Other connected clients viewing that endpoint immediately see a "Locked by [User]" badge and the edit button becomes disabled. |
| 89 | + * *Auto-Release:* The lock is automatically released via the `useBeforeUnload` hook if the tab is closed, or if the socket disconnects. |
| 90 | + |
| 91 | +### 🧩 Dynamic Schema Resolution |
| 92 | +OpenAPI specs are full of `$ref` pointers (e.g., `"$ref": "#/components/schemas/User"`). Rendering these raw is useless to a human. |
| 93 | + |
| 94 | +We implemented a recursive resolver in `src/shared/lib/schemaUtils.ts` that: |
| 95 | +* Traverses the JSON structure deeply. |
| 96 | +* Resolves local references instantly. |
| 97 | +* 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. |
| 98 | + |
| 99 | +--- |
| 100 | + |
| 101 | +## 🚀 Installation & Setup |
| 102 | + |
| 103 | +This frontend is designed to be served statically by the backend in production, but runs independently during development. |
| 104 | + |
| 105 | +### Prerequisites |
| 106 | +* **Node.js 20+** |
| 107 | +* **Bun** (Preferred package manager, though `npm`/`pnpm` work) |
| 108 | +* **Backend Running:** You need the API running locally. [Get the Backend Here](https://github.com/Amir-Zouerami/schematica-api). |
| 109 | + |
| 110 | +### Development Mode |
| 111 | + |
| 112 | +1. **Clone the Repo:** |
| 113 | + ```bash |
| 114 | + git clone https://github.com/Amir-Zouerami/schematica-frontend.git |
| 115 | + cd schematica-frontend |
| 116 | + ``` |
| 117 | + |
| 118 | +2. **Install Dependencies:** |
| 119 | + ```bash |
| 120 | + bun install |
| 121 | + ``` |
| 122 | + |
| 123 | +3. **Environment Setup:** |
| 124 | + Create a `.env` file in the root: |
| 125 | + ```env |
| 126 | + VITE_API_URL=http://localhost:3000 |
| 127 | + VITE_WEBSOCKET_URL=http://localhost:3000 |
| 128 | + VITE_BRAND_NAME=Schematica |
| 129 | + ``` |
| 130 | + |
| 131 | +4. **Run Development Server:** |
| 132 | + ```bash |
| 133 | + bun dev |
| 134 | + ``` |
| 135 | + The app will be available at `http://localhost:8080`. |
| 136 | + |
| 137 | +--- |
| 138 | + |
| 139 | +## 📦 Production Build Strategy |
| 140 | + |
| 141 | +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. |
| 142 | + |
| 143 | +### Side-by-Side Directory Assumption |
| 144 | +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: |
| 145 | + |
| 146 | +```text |
| 147 | +/workspace |
| 148 | + ├── schematica-api/ <-- NestJS Backend |
| 149 | + └── schematica-frontend/ <-- This Repo |
| 150 | +``` |
| 151 | + |
| 152 | +### Building for Deployment |
| 153 | + |
| 154 | +When you run the build command: |
| 155 | + |
| 156 | +```bash |
| 157 | +bun run build |
| 158 | +``` |
| 159 | + |
| 160 | +Vite will: |
| 161 | +1. Compile the TypeScript/React code to optimized ES2022 JavaScript. |
| 162 | +2. Chunk vendor libraries (React, Monaco Editor) separately for better caching. |
| 163 | +3. **Output the files directly into `../schematica-api/public`**. |
| 164 | + |
| 165 | +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. |
| 166 | + |
| 167 | +> **⚠️ Important regarding WASM:** |
| 168 | +> The build process expects the `.wasm` files to be present in the public assets. If you change the build pipeline, ensure `public/wasm/*.wasm` files are copied correctly to the final dist folder, or the cURL converter will fail silently. |
| 169 | + |
| 170 | +--- |
| 171 | + |
| 172 | +## 🤝 Contribution Policy |
| 173 | + |
| 174 | +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. |
| 175 | +
|
| 176 | +**However, I am not accepting Pull Requests at this time.** |
| 177 | +
|
| 178 | +This repository serves two primary purposes: |
| 179 | +1. **A Portfolio Piece:** It demonstrates my architectural decisions, coding standards, and approach to complex frontend engineering. |
| 180 | +2. **An Archive:** It preserves the state of an internal tool I built for a specific company context. |
| 181 | +
|
| 182 | +While I won't be merging external code, I am happy to discuss the architecture or answer questions in the [Issues](https://github.com/Amir-Zouerami/schematica-frontend/issues) tab. |
| 183 | + |
| 184 | +--- |
| 185 | + |
| 186 | +## 📄 License |
| 187 | + |
| 188 | +This project is [MIT](https://opensource.org/licenses/MIT) licensed. |
| 189 | + |
| 190 | +<br /> |
| 191 | + |
| 192 | +<div align="center"> |
| 193 | + <sub>Built with 💙, in a hurry, and with way too much caffeine.</sub> |
| 194 | +</div> |
0 commit comments