what this site runs on
Stack
The technologies the project runs on, and what each one is there for.
browser
- React 19
One component tree: the server renders finished HTML and the browser picks it up through hydration.
- TypeScript
Everything is typed, and the API types are shared by the client and the server.
- React Router
One routing table for the server and the browser. Lazy pages are loaded before the render starts.
- TanStack Query
The data is fetched up front at the route level, and after hydration the page reads a cache that is already there.
- Zustand
Only the local state of the interface, such as whether the modal is open. Server data stays in TanStack Query.
- i18next
Russian and English with SSR support: the server decides the language, and after hydration the client carries on with the same one.
- Sass
SCSS and CSS Modules. The colors live in design tokens, so no stylesheet carries a stray value and the whole palette is run from one place.
server
- Bun
The runtime and the package manager of the monorepo. It runs TypeScript directly, so the server code needs no build step of its own.
- Fastify
The web server behind SSR, the sessions and the /api proxy. Every request gets its own CSP nonce.
- Hono
The API layer. Every route keeps its schema next to its handler, so the validation and the OpenAPI document come from one source.
- Zod
The schemas that validate the requests and the data. The OpenAPI document is generated from the same schemas, so no rule is written twice.
- Redis
The session store in production. A session no longer lives in the memory of one process, so it survives a restart of the app.
- PostgreSQL
The database behind the notes and the rest of the content. It lives in the cluster, run by the CloudNativePG operator.
- Drizzle
The schema and the queries to Postgres in TypeScript. The types come from the same schema the migrations are built from.
- WebAuthn
Passkey sign-in for the admin: no password anywhere, and the signature is checked on the server.
delivery
- Vite
It builds the client and the server, and in development it plugs into Fastify and runs the dev server and HMR.
- PurgeCSS
It strips the unused styles out of the production build. Kebab-case classes get their own extractor, so no CSS that is needed is dropped by mistake.
- Vitest
The unit tests sit next to the code and run in CI. Coverage has a threshold, and the build fails below it.
- Biome
The linter and the formatter of the whole monorepo. One config at the root sets the same rules for every app.
- Stylelint
It checks the stylesheets the way Biome checks the code: property order, nesting depth, and no literal color where a token belongs.
- Knip
It finds the dead code: files, exports and dependencies nobody uses. It runs in CI with the rest of the checks.
- Docker
Both apps build into their own images straight from the monorepo. The API image ends up tiny and carries no node_modules at all.
- k3s
A light Kubernetes for one small ARM box at Hetzner. It is enough to deploy and run the services without any extra infrastructure.
- GitLab
The repository and the CI/CD live here. Before a deploy it runs the same checks I run locally, so the two never drift apart.
- Cloudflare
DNS and a tunnel in front of the cluster. The traffic comes in through Cloudflare, so the box opens no port to the outside.
- Sentry
It collects the errors from the browser and from the server in one place, so I see the whole picture of the app.