A web framework in C, from the socket up.
The page you're reading was routed, rendered, and sent by ~1,600 lines of C99 with zero runtime dependencies.
Not because C is the right tool for a portfolio — because owning every layer from accept()
to template interpolation is the most honest way to show what "full stack" means.
Every framework hides the interesting parts.
After years of shipping on .NET and Angular, the question was: can I build the whole request lifecycle myself — socket loop, thread dispatch, routing, middleware, templating, static files — small enough to hold in one head, robust enough to run in production on Cloud Run?
Constraints: C99 + pthreads only. No libevent, no framework, no runtime dependencies. Every byte of the HTTP response is assembled by code in this repo.
One thread per request, one linked list per concern.
The socket loop accepts and dispatches to a pthread. The request walks a middleware chain — logging, static
files, rate limiting, CSRF — then the router, then a controller ACTION, then a two-pass
template render into the layout's body slot.
Thread-per-request over an event loop
Simpler invariants, no callback state machines. The throughput ceiling was accepted consciously and measured below — it is nowhere near this site's bottleneck.
A template engine with three directives
Substitution, #if, #each, and a two-pass layout render. No partials, no filters, no expression language — enough for real pages, nothing speculative.
Linked-list middleware chain
Logging → static → rate-limit → CSRF → router. Each layer can short-circuit, and the order is readable at the call site in main.c.
Build-time everything
Tailwind compiled to a static file; articles are markdown compiled to HTML; diagrams are mermaid rendered to SVG. Browser interactivity is Lua compiled to WASM, loaded per route. The server's job stays brutally simple.
Benchmark: hey, 50 concurrent connections, 10s runs (median of 3), Intel N100 (4 cores) under WSL2 — laptop-class hardware, not the Cloud Run deployment. Numbers are for honesty, not bragging: a thread-per-request C server on a small box outruns what this site will ever need.