Welcome to rex-serve
This is a live, self-documenting demo of rex-serve — an HTTP server
that uses Rex scripts as edge functions.
Every page you see is powered by a .rex file. Walk through the tour below
to understand each feature.
Tip: add the header X-View-Source: 1 to any
request to see the raw Rex source that generated it.
Try curl -H 'X-View-Source: 1' http://localhost:4000/
Guided Tour
1 Static Files
CSS, images, and other assets are served directly alongside Rex handlers. This page's stylesheet is a static file.
2 Filesystem Routing
Files map to URLs. Dynamic segments like [slug].rex capture path params. This tour uses them.
3 Middleware
The _middleware.rex convention adds behavior to entire subtrees — auth, headers, the view-source tool.
4 Templates & Markdown
Rex handlers read markdown from _content/, render it to HTML, and inject it into layout templates.
5 JSON API
A CRUD API for articles — with auth middleware, request body parsing, and a SQLite-backed KV store.
6 Developer Experience
Reflections on building rex-serve: what worked well in the Rex language, and what was painful.
How It Works
The file tree below is the entire application. Rex handlers (.rex) are compiled to bytecode
on startup and executed per-request. Private directories starting with _ are readable by handlers
via fs.read() but never served directly.
routes/
_middleware.rex # Global: security headers, view-source tool
_layouts/page.html # HTML template used by all pages
_content/*.md # Markdown articles
style.css # Static CSS (dark/light mode)
index.rex # This page
health.rex # JSON health check
tour/
static-files.rex # Tour stop 1
routing.rex # Tour stop 2
middleware.rex # Tour stop 3
templates.rex # Tour stop 4
api.rex # Tour stop 5
experience.rex # Tour stop 6
api/
_middleware.rex # Auth for API routes
articles.rex # GET list / POST create
articles/[slug].rex # GET / PUT / DELETE
This Page's Source
The Rex program that generated this page:
/* Homepage — guided tour entry point */ res.headers.content-type = "text/html; charset=utf-8" layout = fs.read("routes/_layouts/page.html") unless layout do status = 500 return "layout not found" end self-source = fs.read("routes/index.rex") highlighted = when self-source do html.raw(html.highlight(self-source)) end body = html`<h1>Welcome to rex-serve</h1> <p>This is a live, self-documenting demo of <strong>rex-serve</strong> — an HTTP server that uses <a href="https://github.com/creationix/rex">Rex</a> scripts as edge functions. Every page you see is powered by a <code>.rex</code> file. Walk through the tour below to understand each feature.</p> <p style="color:var(--muted);font-size:0.9rem">Tip: add the header <code>X-View-Source: 1</code> to any request to see the raw Rex source that generated it. Try <code>curl -H 'X-View-Source: 1' http://localhost:4000/</code></p> <hr> <h2>Guided Tour</h2> <div class="grid"> <div class="card"> <h3><span class="badge badge-green">1</span> <a href="/tour/static-files">Static Files</a></h3> <p>CSS, images, and other assets are served directly alongside Rex handlers. This page's stylesheet is a static file.</p> </div> <div class="card"> <h3><span class="badge badge-green">2</span> <a href="/tour/routing">Filesystem Routing</a></h3> <p>Files map to URLs. Dynamic segments like <code>[slug].rex</code> capture path params. This tour uses them.</p> </div> <div class="card"> <h3><span class="badge badge-green">3</span> <a href="/tour/middleware">Middleware</a></h3> <p>The <code>_middleware.rex</code> convention adds behavior to entire subtrees — auth, headers, the view-source tool.</p> </div> <div class="card"> <h3><span class="badge badge-yellow">4</span> <a href="/tour/templates">Templates & Markdown</a></h3> <p>Rex handlers read markdown from <code>_content/</code>, render it to HTML, and inject it into layout templates.</p> </div> <div class="card"> <h3><span class="badge badge-yellow">5</span> <a href="/tour/api">JSON API</a></h3> <p>A CRUD API for articles — with auth middleware, request body parsing, and a SQLite-backed KV store.</p> </div> <div class="card"> <h3><span class="badge badge-blue">6</span> <a href="/tour/experience">Developer Experience</a></h3> <p>Reflections on building rex-serve: what worked well in the Rex language, and what was painful.</p> </div> </div> <hr> <h2>How It Works</h2> <p>The file tree below is the entire application. Rex handlers (<code>.rex</code>) are compiled to bytecode on startup and executed per-request. Private directories starting with <code>_</code> are readable by handlers via <code>fs.read()</code> but never served directly.</p> <pre>routes/ _middleware.rex # Global: security headers, view-source tool _layouts/page.html # HTML template used by all pages _content/*.md # Markdown articles style.css # Static CSS (dark/light mode) index.rex # This page health.rex # JSON health check tour/ static-files.rex # Tour stop 1 routing.rex # Tour stop 2 middleware.rex # Tour stop 3 templates.rex # Tour stop 4 api.rex # Tour stop 5 experience.rex # Tour stop 6 api/ _middleware.rex # Auth for API routes articles.rex # GET list / POST create articles/[slug].rex # GET / PUT / DELETE</pre> <h2>This Page's Source</h2> <p>The Rex program that generated this page:</p> <pre>${highlighted}</pre>` template.render(layout, { title: "Home" body: body footer: "Powered by Rex · <a href='/health'>Health Check</a>" })