Tech Stack
How this site is built, how publishing works, and why these tools were chosen.
Architecture overview
This site has two interfaces: public pages for readers and a private dashboard for publishing. Both run on Cloudflare Workers, use the same backend APIs, and share a PostgreSQL database. Uploaded images live in Cloudflare R2.
- Reading
- Profile pages and published articles arrive as HTML. Writing lists load in the browser, with search and filters saved in the URL so readers can share or revisit their results.
- Publishing
- The author signs in with GitHub, edits content in Tiptap, and saves it through authenticated APIs. Draft previews use signed, expiring links. Publishing makes a post public; unpublishing returns it to draft, while archiving retains it privately.
- Delivery
- GitHub Actions checks each change. Develop deploys to Preview; a reviewed release pull request promotes it to main, which deploys to Production when deployment is enabled.
Interface
React Router 8.4 · React 19 · TypeScript · Tailwind CSS 4
The home, resume, and Stack pages arrive as server-rendered HTML, as do published articles. Writing lists load in the browser; the home page shows recent posts as a row you can scroll sideways. The admin is a separate React app that shares the public site’s styles and accessible UI components.
Data fetching & navigation
TanStack Query · TanStack Table · Ky · react-top-loading-bar
TanStack Query keeps API results fresh for one minute and refreshes affected data after a save. Ky handles API requests. In the admin, posts show as cards or as a TanStack Table, and the browser remembers the choice; selecting a column header asks the server to sort every post, not just the current page. A top progress bar shows navigation in progress; loading, empty, and error states explain what is happening.
Content
Tiptap · Shiki · rehype · React PDF · cf-workers-og
The author writes in Tiptap. Published articles are sanitized and rendered on the server, with Shiki highlighting code blocks. React PDF builds the resume only when Download is selected; cf-workers-og creates images for shared links.
Data
PostgreSQL · Drizzle ORM · Neon HTTP · Cloudflare KV / D1 / R2
PostgreSQL stores posts, tags, series, and sign-in sessions. Drizzle defines typed queries and migrations; the Neon HTTP driver connects the Worker to the database. Cloudflare KV caches public content, D1 tracks cache revisions and analytics quotas, and R2 stores uploaded images. Draft previews and private API responses are not cached.
Author access
Better Auth · GitHub OAuth
Better Auth handles GitHub sign-in and database-backed sessions. Only the allowed GitHub account can use private APIs to edit posts, preview drafts, or upload images. Edge rate limits protect API traffic before database work; security headers restrict scripts and image sources.
Local development
Node.js · npm · Docker Compose · PostgreSQL · Neon HTTP proxy
npm run dev starts the public React Router / Vite server and an independent admin build watcher. Both apps and database tools share .env.local. Docker Compose supplies local PostgreSQL and a Neon-compatible HTTP proxy; local uploads use an isolated R2 bucket served at /local-media. Setting DEV_PUBLIC_URL serves the same setup through a local HTTPS address such as indrax.uk.test.
Quality
TypeScript · Vitest · Playwright · axe · ESLint · Prettier
Prettier and ESLint check formatting and code quality; TypeScript checks types. Vitest covers application behavior and PostgreSQL integration. Playwright tests browser journeys against the built Worker, including accessibility checks with axe and a separate development hydration check.
CI/CD
GitHub Actions · Vite · Wrangler
GitHub Actions runs two checks for pull requests and pushes to develop or main. The check job validates formatting, lint, types, unit tests, and both environment builds. The e2e job runs database and browser tests with a seeded local database, plus uploads against isolated R2 storage. When deployment is enabled and both jobs pass, develop deploys to Preview and main deploys to Production.
Deployment
Cloudflare Workers · React Router
Vite builds the public server-rendered app and static admin assets into one Cloudflare Worker deployment. Wrangler defines the domains and service bindings. Production and develop use separate KV, D1, and R2 resources; only explicitly allowed public settings reach browser bundles.
Measurement & monitoring
PostHog · Workers logs · structured server logs
After consent, PostHog measures site use through a same-origin Worker gateway at /analytics with shared monthly quotas in D1. Withdrawing consent stops capture and clears stored identifiers. Structured server errors and Cloudflare Workers logs help investigate failures.
Sources
Explore the implementation and the workflow that builds, tests, and deploys it. The linked guides explain the framework, data fetching, hosting, image storage, and monitoring tools used here.