Alvaro Guzman Résumé ↓
← Work
Systems · frameworks and languages

From the socket up.

c-copper is the C framework serving this page. Around it: Lunar, a typed superset of Lua with its own compiler and LSP; Cobre, the opinionated successor framework; and Axon, the archived first pass at an LLM gateway.

~3,500
LINES OF C
src/, .c + .h
21
HTTP ROUTES
registered, 4 are 301s
6
TEMPLATE
directives
0
FRAMEWORK DEPS
libcurl for email · zlib for gzip
Live source

src/router.c — thread-safe pattern matching.

Literal routes short-circuit on strcmp. Parameterised routes tokenise both pattern and path with strtok_r, binding {param} segments onto the request. First match wins.

src/server.csocket loop / pthread dispatch
src/router.cpattern match + param bind
src/middleware.clinked-list chain
src/static.c/static/* → public/*
src/view.chandlebars-style engine
src/response.chtml / json / bytes
// src/router.c (abridged: comments trimmed)
static int match_pattern(const char* pattern, const char* path, Request* req)
{
    if (!strchr(pattern, '{'))
        return strcmp(pattern, path) == 0;

    char pat_copy[256], path_copy[256];
    pat_copy[0] = '\0';
    path_copy[0] = '\0';
    strncat(pat_copy, pattern, sizeof(pat_copy) - 1);
    if (strlen(path) >= sizeof(path_copy)) return 0;
    strncat(path_copy, path, sizeof(path_copy) - 1);

    char *save1, *save2;
    char* p_seg    = strtok_r(pat_copy,  "/", &save1);
    char* path_seg = strtok_r(path_copy, "/", &save2);

    while (p_seg && path_seg) {
        if (p_seg[0] == '{') {
            // copy the name between { and } → bind it to the path segment
            char param[64] = {0};
            int i = 1;
            while (p_seg[i] && p_seg[i] != '}' && i - 1 < (int)sizeof(param) - 1) {
                param[i - 1] = p_seg[i];
                i++;
            }
            if (req) request_set_param(req, param, path_seg);
        } else if (strcmp(p_seg, path_seg) != 0) {
            return 0;
        }
        p_seg    = strtok_r(NULL, "/", &save1);
        path_seg = strtok_r(NULL, "/", &save2);
    }
    return (p_seg == NULL && path_seg == NULL);
}

Request pipeline

Five stages, each one a file you can read.

socket()
accept + read
middleware
log · static · ratelimit · csrf
router
match + bind
controller
ACTION()
view
render + layout

Template directives (6)

{{ key }}interpolate, HTML-escaped
{{{ key }}}interpolate raw
{{#if x}} ... {{else}} ... {{/if}}conditional
{{#each rows}} ... {{/each}}iterate
@layoutlayout marker, stripped
@csrfsigned hidden token

Adjacent systems

01

Cobre — Razor-pages-inspired web framework in C

In development

.cob source files transpile to .gen.c, then compile to .so and hot-load. Arena allocator with a Str type, goto cleanup error handling, TOML config. The opinionated successor to c-copper.

Ctranspilerarena allocator.so hot-load
02

Lunar — statically-typed superset of Lua

Active

Compiler, LSP, bundler, test framework — all in Go. TypeScript-for-Lua, end to end. Types on top of Lua semantics, so a codebase that outgrows plain Lua stays readable for the next person.

GocompilerLSPbundlersource →
03

Axon — self-hosted LLM gateway

Archived

First pass at an on-premise LLM gateway in C#. Routing, request shaping, prompt template layering. Useful exercise in API surface design and provider abstraction; stays in the archive.

C#gatewaypredecessor