c-copper: 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.
01 // Problem
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.
02 // Decisions
- Thread-per-request over an event loop. Simpler invariants, no callback state machines; throughput ceiling accepted consciously (measured below).
- Linked-list middleware chain (logging → static → rate-limit → CSRF → router) — each layer can short-circuit.
- Handlebars-style templates with {{key}}, #if, #each and a two-pass layout render — enough for real pages, nothing speculative.
- strtok_r pattern matching for routes with
{param}binding — thread-safe, first-match-wins. - Build-time assets: Tailwind compiled to a static 40KB file; browser interactivity is Lua compiled to WASM, loaded per route.
03 // Architecture
04 // Numbers
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.