Minimal backend to create, list, and close tickets. Built as a Cursor / vibe-coding experiment: good practices, small iterations, and strict MVC on a monolithic stack. Storage started as an in-memory array to validate the layering; the same flow works with SQLite (or any DB), so the structure stays solid when you swap the repository.
- Create a ticket
- List tickets
- Close a ticket
Nothing else. Priority: clean, evolutive architecture over features.
- Node.js + Express + TypeScript
- SQLite for persistence (repository layer; in-memory implementation available for quick runs)
Request flow: route → controller → service → repository → DB
| Layer | Role |
|---|---|
| routes | Map HTTP to controllers |
| controllers | Handle req/res only; no business logic |
| services | Business logic (create, close, etc.) |
| repositories | Data access only (read/write) |
| models | Domain entities (e.g. Ticket) |
| db | DB connection config (SQLite) |
Controllers never talk to the DB; all business logic lives in services.
src/
index.ts # Express entry point
routes/ # HTTP route definitions
controllers/ # HTTP handlers (req/res)
services/ # Business logic
repositories/ # Data access (in-memory or SQLite)
models/ # Entities (Ticket, etc.)
db/ # DB config
| Method | Path | Description |
|---|---|---|
| GET | /health |
Health check, returns OK |
| POST | /tickets |
Create ticket (body: { "title": "..." }) |
| GET | /tickets |
List all tickets |
| PATCH | /tickets/:id/close |
Close ticket by id |
Responses are JSON. Ticket shape: { "id", "title", "status", "createdAt" }.
Prerequisites: Node.js (v18+), npm
npm install
npm run devServer listens on http://localhost:3000 (or PORT env var).
Production: npm run build then npm start (output in dist/).
MIT