Why Nerack
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.
Table of Contents
- Quick Start
- Philosophy
- Tooling
- Built With
- License
- Documentation
Quick Start
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 up
Create 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.
Philosophy
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
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.
Built on Standards
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.
Everything is a String
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}}.
CLAD
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
Tooling
Development Environment
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.
Web Editor
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___
TUI
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 nerack
Bring Your Own
Nerack 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 errors
Testing
Built-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 tests
Debugging
The 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 TUI
Deployment
Nerack 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 image
app_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__.
Observability
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.
Built With
| 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 |
License
Nerack is licensed under the LGPL. Your application code can use any license; it is a Nerack plugin.
