ADR 001 Server Framework - steilerDev/cornerstone GitHub Wiki
ADR-001: Server Framework
Status
Accepted
Context
Cornerstone needs a Node.js HTTP server framework to serve the REST API and static client assets. The framework must support:
- TypeScript-first development
- Plugin architecture for modular feature registration (auth, database, routes)
- JSON schema validation for request/response
- Static file serving for the bundled SPA
- OIDC authentication middleware (or ecosystem support)
- Session/cookie management
- Proxy capabilities (for Paperless-ngx API)
- Good performance for <5 concurrent users (not a hard requirement given scale)
Alternatives Considered
Express (v4/v5)
- The most widely used Node.js framework with the largest ecosystem
- Weak TypeScript support; types are community-maintained and often lag behind
- Middleware-based architecture can lead to ordering bugs
- No built-in validation; requires additional libraries (Joi, Zod, etc.)
- Express v5 is still not fully stable
- Performance adequate for this scale
Hono
- Lightweight, fast, excellent TypeScript support
- Designed for edge runtimes (Cloudflare Workers, Deno, Bun) but works with Node.js
- Smaller ecosystem; fewer battle-tested plugins for OIDC, sessions, and database
- Less mature for traditional server-side Node.js applications
- Static file serving and SPA fallback require more manual setup
Fastify (v5)
- Excellent TypeScript support with typed plugins and decorators
- Plugin system enforces encapsulation and modularity
- Built-in JSON schema validation (using AJV) and serialization
@fastify/staticfor serving SPA assets with SPA fallback- Rich ecosystem:
@fastify/cookie,@fastify/session,@fastify/oauth2,@fastify/reply-from(proxy) - Actively maintained with predictable release cycles
- Slightly higher learning curve than Express due to plugin encapsulation model
Decision
Use Fastify v5 as the server framework.
Consequences
Positive
- Type-safe route definitions reduce runtime errors
- Plugin encapsulation keeps auth, database, and route concerns separated
- Built-in validation eliminates the need for a separate validation library
- The
@fastify/staticplugin handles SPA serving with fallback out of the box - The
@fastify/reply-fromplugin provides Paperless-ngx API proxying - Structured logging (pino) is built in
Negative
- Smaller community than Express; fewer Stack Overflow answers
- Plugin encapsulation model requires understanding scopes (can be confusing initially)
- Some Express middleware is not directly compatible (must use Fastify equivalents)