Introduction
What Cataract is, what it refuses to be, and how the pieces fit together.
Cataract is a full-stack web framework for Chapel. It gives a Chapel program file-system routing, server-side rendering, partial hydration and an HTTP/1.1 server on raw BSD sockets — all compiled into a single binary with no runtime dependencies.
There is no template language. Markup is written in Chapel with a typed builder, and the framework's job is to make that safe rather than to add a second syntax to learn.
The shape of an application
A page is a module that exports page. Where the file lives decides the URL it answers.
module PageIndex {
use Cataract;
proc page(ctx: Context, ref meta: PageMeta): string {
meta.title = "Posts";
var h = new MarkupBuilder();
h.el("h1", "Posts");
for post in PostStore.all() do
h.el("a", post.title, "href", "/posts/" + post.id);
return h.done();
}
}That file at app/routes/index.chpl answers /. Move it to app/routes/posts/index.chpl and it answers /posts. Nothing else has to be registered, imported or wired.
What the framework provides
| Layer | What it does |
|---|---|
cataract-cli | Scans app/, generates Chapel sources, invokes chpl |
cataract-runtime | HTTP parsing, routing, middleware, rendering, static files |
| Generated code | One handler class per route, plus main and the middleware stack |
The CLI and the runtime share only the generated code. Your application never sees a socket, a buffer or a C pointer.
What it deliberately does not provide
Cataract has no TLS termination, no session store, no ORM, no authentication and no rate limiter. It expects a reverse proxy in front of it for TLS, and it expects authentication to be middleware you write. The security model is explicit about the boundary.
The public API is not stable yet. Version 0.1.0 is usable and honest about its gaps.
Where to go next
- Installation — the toolchain, and nothing else
- Your first application — from
cataract newto a served page - File-system routes — how the directory tree becomes a route table
- Islands — shipping JavaScript only where behaviour lives