Solutions
Application → development and build → production runtime → optional deployment services.
Start directly with npm run dev, or build and serve with npm run build then npm run start. Docker, Traefik and Varnish are optional.
Nesting shows composition within each layer. Dependencies across layers are stated explicitly. “In use” describes this repository; it does not claim a comparative benchmark or complete verification.
Application — what runs in the browser
The application is built from React components. Infrastructure is outside this layer.
React — In use
Provides: Reusable components, UI state and hydration of generated HTML.
Depends on: React DOM and a browser for client execution; the build also renders public pages in Node.js.
React Router — In use; also integrates with the build
Provides: Routes, SPA navigation, metadata integration, lazy route modules, error boundaries and build-time page rendering. Vite alone does not provide this complete integration.
Depends on: React; its Vite integration and Node.js during development/build. A permanent SSR process is not required by the current setup.
Development and build — Node.js runs the tools
npm run dev starts development directly. npm run build produces HTML, JavaScript, CSS and the Node.js server. Docker, Traefik and Varnish are not prerequisites.
Node.js + npm — Required by the current toolchain
Provides: The runtime and package workflow used to install dependencies, run development tools and build the application.
Depends on: The supported Node.js version, package.json and the lockfile. Our Vite toolchain runs on Node.js, not inside the browser or Docker itself.
Vite — In use through React Router
Provides: A development server with HMR, module and asset processing, production bundles and code splitting. It covers these needs without a custom build pipeline; it is not the production HTTP server.
Depends on: Node.js, source modules and configuration. React Router supplies routing and prerendering; a comparison against other build tools has not been documented.
Linaria + WyW Vite plugin — In use; focused verification continues
Provides: Styled-component references inside selectors while extracting CSS during the build. This styling requirement exists now, which is why Linaria was introduced now.
Depends on: The Vite transform and statically extractable styles. Page and layout wrappers use Linaria styled components with CSS extracted during the build. Cross-file selectors, dynamic values, HMR, hydration and lazy CSS delivery still need focused verification; fewer dependencies alone would not make CSS Modules an equivalent substitute.
TypeScript — In use
Provides: Checks component props and integration contracts; compiles the production server. Type checking is a separate command, not an automatic guarantee of Vite bundling.
Depends on: Node.js, type definitions and TypeScript configuration. It does not replace runtime validation.
Storybook — Optional; configured
Provides: An isolated environment for inspecting component states without navigating full pages.
Depends on: React/Vite integration and component stories. Scripts and configuration exist; the story catalog remains to be populated.
ESLint, Prettier and Node.js HTTP tests — In use
Provides: Code checks, consistent formatting and HTTP contract checks alongside type checking and builds.
Depends on: Project configuration and a running target for HTTP tests. Varnish assertions require the cache path; repeatable browser automation remains to be added.
Production — serve the finished build
Minimal current path: npm run build → npm run start → Node.js + sirv. The browser receives build artifacts. No Docker, reverse proxy or cache is required for this direct path.
Node.js HTTP process — In use
Provides: Runs the production service with npm run start. No Vite development server or request-time React renderer is needed.
Depends on: A completed build, Node.js, production dependencies and a reachable port.
sirv + a small HTTP policy wrapper — In use
Provides: Serves generated pages and assets, with cache headers, GET/HEAD support and intentional 404 responses. A general backend framework is unnecessary for these file-serving requirements.
Depends on: The Node.js HTTP server, built files and routing/error policies. HTML uses a 60-second shared-cache lifetime; hashed assets can be cached immutably.
Process supervision — for example PM2 — Optional alternative; not configured
Provides: A possible way to supervise the Node.js service instead of running it as a foreground npm process.
Depends on: A supervisor installation and deployment-specific startup/restart configuration. PM2 is an example, not an adopted or verified project dependency; containers are another deployment choice.
Optional deployment environment — around the application
These are independent operational choices, not application prerequisites. The configured production path is Traefik → Varnish → Node.js + sirv. Compose groups services; it is not another hop in that request path.
Docker — Optional; configured
Provides: Packages the service environment into container images for repeatable execution.
Depends on: A Docker runtime, images, storage and networking. Native Node.js execution remains possible.
Docker Compose — Optional; configured
Provides: Describes and starts the app, cache and proxy services together, with environment-specific configuration.
Depends on: Docker and Compose, images, environment variables, networks and ports. It organizes peer services rather than placing the proxy or cache inside the app process.
App service container — Configured
Provides: A container boundary around the Node.js process. Development runs the Vite toolchain; production runs the built sirv service.
Depends on: The Dockerfile and selected environment configuration. Development mounts source files; production uses the built artifact and server dependencies.
Cache service container — Configured for production
Provides: Runs Varnish as a separate service in front of the origin.
Depends on: The Varnish configuration described below and a reachable app service.
Proxy service container — Configured
Provides: Runs Traefik as a separate entry-point service.
Depends on: The Traefik configuration described below and reachable upstream services.
Traefik — Optional; configured
Provides: A shared entry point and routing to the app or cache. It is useful when deployment needs proxy routing or TLS termination rather than direct access to a Node.js port.
Depends on: Routing, network and upstream configuration; TLS additionally needs domains and certificates. It does not inherently require Docker or Varnish. Our optional development environment uses it in front of Vite; direct npm run dev does not need it.
Varnish — Optional; configured for production
Provides: Caches eligible public responses to avoid repeated origin requests. This is an additional delivery capability, not a requirement for React, Vite or Node.js.
Depends on: An HTTP origin, cacheability headers and VCL rules. The current rules bypass requests with cookies or authorization. It is bypassed in normal development; publication freshness and invalidation procedures still need documentation.
Optional observation — evidence about the running system
Usage analytics and cache measurements answer different questions. Neither is necessary to build or serve the application.
Betterlytics — Optional integration
Provides: A configured script hook for website usage analytics.
Depends on: A site ID, external service and collection policy. The hook does not prove collection is working and does not measure Varnish origin traffic.
Request/cache measurement solution — Implementation open
Provides: Would show cache hits and origin requests using measured data instead of the homepage illustrations.
Depends on: An agreed metric, collection source and observation window. No measurement technology has been selected.
Future branches — technology choices still open
These remain requirement areas until a concrete solution is selected. They do not form a mandatory sequence of additions.
Standalone API — Open
Provides: Server operations or integrations beyond static delivery and browser-only interactions.
Depends on: An actual operation, an API contract, validation and a service runtime. No backend framework has been selected.
Persistent storage — Open
Provides: Durable shared data where needed.
Depends on: A data model, access boundaries, backups and migrations. No database has been selected; an API does not automatically require a database.
Typed API/data contracts — Open
Provides: Consistent contracts across a growing application, beyond current component type checks.
Depends on: Actual API/data boundaries, runtime validation and a shared or generated contract approach.
Payments and transactions — Open
Provides: Transactional workflows when a real product requirement calls for them.
Depends on: A business flow, provider, trusted processing, durable state and recovery. No payment technology has been selected.
Formal solution composition — Open
Provides: Could check solution compatibility and dependency obligations automatically.
Depends on: A useful schema and enough complexity to justify maintenance. This list does not require a runtime framework or graph database.