Nerack is a declarative, protocol-agnostic framework for asynchronous networking applications in C, built around self-contained systems.
- Self-contained systems: an app is a set of self-contained modules whose boundaries the compiler enforces.
- Durable tasks and events: both are persisted. After a crash, incomplete tasks resume at the step where they stopped and undelivered events replay.
- Developer experience: compilation, hot code reloading, and an HMR feedback loop, with no build scripts. Write code and save. The only dependency is Docker.
- Memory, concurrency, and I/O managed by the framework: application code does not call malloc/free or manage threads, mutexes, or locks.
- Observability: pipeline steps emit OpenTelemetry spans, logs, and errors automatically.
- Protocols: HTTP, RNS, LXMF, NomadNet, Gemini, Finger, SMTP, or any other; one app can serve several at once.
- Databases: SQLite, Postgres, MySQL, Redis, DuckDB, or any other; multi-tenancy is built in, and one app can use several at once.
- Authentication: cookie and session auth are bundled; WebAuthn, OTP, or any other.
- Bundled modules: HTML, Markdown, and Micron templates; Datastar, HTMX, Tailwind, DaisyUI; HTTP, RNS, SQLite; pub/sub; background and cron tasks.
- Quick Start
- Philosophy
- Tooling
- Built With
- License
- Documentation
Everything runs in Docker.
mkdir myapp && cd myapp
wget https://docker.nightshadecoder.dev/nerack/compose.yml
# Dev server on :3000, telemetry on :4000
# Includes file watching, auto compilation, hot code reloading, HMR
docker compose upCreate hello_world.c with the example below. Nerack watches for changes and hot-reloads on save. Edit it with your own editor, the built-in TUI, or the web editor; see Development Environment for all three.
#include <nerack.h>
#include <http.h>
module(hello_world){
context("hello", "Hello, world");
http("home", "/", .mime = mime_text, .get = {http_response("hello")});
}A module is any .c file declaring module(name){...}; hello_world.c declares the hello_world module. context() seeds the context key hello from a string literal instead of a file; http() declares the home resource mapping / to a GET pipeline that sends that value with http_response(), as text/plain because of .mime. http() comes from http.h; the core itself has no notion of HTTP. See the Guide for a step-by-step walkthrough.
An application is a data transformation: input arrives, is transformed, and leaves as output. Nerack arranges the work into pipelines: ordered lists of steps that turn a request into a response.
Steps are the primitive; a pipeline is an ordered list of them. A step is declarative: it describes what should happen, not how. Each step is self-contained: it may run synchronously or asynchronously, but the pipeline treats it as a single synchronization point, and the next step starts only once it resolves. A step guarantees that when it finishes, context holds the values it promised; if it cannot, it raises an error instead, handled by an error or repair pipeline. Each step is its own OpenTelemetry span, logs itself, and counts its own performance.
The assets are standard formats: SQL, JSON, Markdown, HTML, CSS, JS, Micron. Business logic is plain C. The tooling is standard too: LLDB for debugging, Playwright and Criterion for testing, OpenTelemetry for observability.
The web is text: HTTP, RNS, Micron, HTML, Markdown, JSON, SQL. The pipeline context stores and passes data as strings. Strings are interpolated into SQL, templates, and URLs with {{context_key}}.
Four principles:
- (C)omposable: small, independent steps chain into feature pipelines.
- (L)ocality of Behavior: behavior is apparent from reading the code. SQL, templates, and logic for a feature live together, not spread across model, view, and controller trees.
- (A)utonomous: each module owns its schemas, migrations, seeds, resources, UI, and logic, and the compiler enforces the boundaries.
- (D)omain Based: each module owns one slice of the app. A
todosmodule defines everything related to todos and nothing else.
Inspired by:
- Data Oriented Design
- A Philosophy of Software Design
- CUPID
- Self-Contained Systems
- Locality of Behavior
Nerack apps can be built three ways: the web editor, the built-in TUI, or your own editor. The folder holding compose.yml is the project root; module .c files and assets (SQL, HTML, and so on) live there, as shown in the Guide and Reference. The three are not exclusive: mix and match freely.
The built-in web editor represents modules, resources, pipelines, and databases as graphical widgets instead of raw text, with a code editor for step bodies. It generates module .c files and assets into the project root; saving a change compiles and hot-reloads it like any other edit. A module/asset viewer shows what was generated, and a server console shows requests and errors.
http://localhost:3000/___dev___
The built-in TUI is a terminal editor with auto-compilation, hot reloading, an LSP, and a server console for requests and errors.
docker compose attach nerackNerack watches the project root regardless of editor. Edit .c files and assets with any tool; Nerack compiles and hot-reloads on save.
docker compose attach server # server console: requests and errorsBuilt-in runners for unit and end-to-end testing; no external framework setup required.
unit_tests # fast, criterion-based tests
e2e_tests # playwright-powered browser testsThe debug commands are pipeline-aware: halt on a step, step through execution, and inspect the full context, including nested tables and records.
app_debug # interactive debugger in the TUINerack deploys as a standard Docker container. It does not terminate TLS; production deployments place Nerack behind a reverse proxy or load balancer (Nginx, Caddy, AWS ALB) to handle HTTPS.
app_build # outputs a minimal production Docker imageapp_build runs each module's asset scan once (see Assets) and compiles the results into that module's binary. The production image excludes the file watcher and /__dev__.
Each pipeline step emits OpenTelemetry spans. Logs, traces, errors, and auto-profiling are visualized on the telemetry server at port 4000. No manual instrumentation required.
| C | Language standard |
| Docker | Development environment, production images, stack orchestration |
| libuv | Event loops, async I/O, file watching, shared thread pool |
| libmicrohttpd | HTTP server, used by the http protocol module |
| Mustach | Templating and string interpolation, used by html()/markdown() |
| Jansson | JSON parsing and generation, used by json() and http_fetch() |
| curl | HTTP client, used by http_fetch() |
| Reticulum | Mesh networking stack, used by the rns protocol module |
| LXMF | Message transfer protocol over Reticulum, used by the lxmf protocol module |
| Fresh | TUI editor |
| clangd | Language server |
| LLDB | Debugger |
| Criterion | Unit testing |
| Playwright | End-to-end testing |
| SigNoz + OpenTelemetry | APM, traces, logs, errors, dashboards |
Nerack is licensed under the LGPL. Your application code can use any license; it is a Nerack plugin.
