A CRUD API with real-time notifications, built with an OpenAPI-first approach.
| Layer | Technology |
|---|---|
| API server | Fastify + TypeScript |
| Routing | openapi-backend (routes derived from openapi.yml) |
| Database | PostgreSQL 16 |
| ORM | Drizzle ORM |
| Messaging | NATS (fire-and-forget pub/sub) |
| Frontend | SvelteKit (Svelte 5) |
| Tests | Vitest |
openapi-postgres/
server/ # Fastify backend
openapi.yml # OpenAPI 3.0.3 spec (single source of truth)
app.ts # App factory (Fastify + openapi-backend wiring)
index.ts # Entry point (starts server)
handlers.ts # Route handlers (CRUD + health)
db.ts # Postgres pool + Drizzle instance
schema.ts # Drizzle table definitions
nats.ts # NATS connection, publish, subscribe
__tests__/ # Vitest unit tests
web/ # SvelteKit frontend
src/lib/api.ts # Typed API client
src/lib/Toast.svelte # Real-time notification toast (SSE)
src/routes/ # Pages
docker-compose.yml # Postgres + NATS
drizzle/ # Generated migrations
# 1. Clone and install
npm install
cd web && npm install && cd ..
# 2. Copy env and adjust if needed
cp .env.example .env
# 3. Start Postgres and NATS
docker compose up -d
# 4. Run migrations
npm run db:migrate
# 5. Start both backend + frontend concurrently
npm run dev
Open http://localhost:5173 to use the app.
| Script | Description |
|---|---|
npm run dev |
Start backend + frontend together |
npm run dev:server |
Start backend only |
npm run dev:web |
Start frontend only |
npm run build |
Build backend + frontend |
npm start |
Run compiled backend |
npm test |
Run Vitest unit tests |
npm run db:up |
Start Postgres container |
npm run db:down |
Stop all containers |
npm run db:generate |
Generate a Drizzle migration |
npm run db:migrate |
Apply migrations |
npm run db:studio |
Open Drizzle Studio |
web/)| Script | Description |
|---|---|
npm run dev |
Start SvelteKit dev server |
npm run build |
Build for production |
npm run check |
Run svelte-check |
Defined in server/openapi.yml. Key endpoints:
| Method | Path | Description |
|---|---|---|
GET |
/health |
Health check (DB + NATS) |
GET |
/items |
List items (paginated) |
POST |
/items |
Create an item |
GET |
/items/:id |
Get item by ID |
PATCH |
/items/:id |
Partially update an item |
DELETE |
/items/:id |
Delete an item |
GET |
/events |
SSE stream (NATS events) |
When an item is created, the backend publishes to NATS on items.created. The /events SSE endpoint subscribes to items.* and streams events to connected browsers. The frontend Toast component listens and shows a notification + refreshes the list.