Getting Started: Build a Live Guestbook
Build a guestbook app with http-nu, step by step. By the end you will have a server with composable HTML, persistent storage, and real-time updates powered by Datastar and server-sent events.
Step 1: Hello World
http-nu takes a Nushell closure and serves it over HTTP. The closure receives the request as its argument. Whatever it returns becomes the response.
Test it:
The string is returned as text/html by default. Return a record and it
becomes application/json automatically.
Step 2: The HTML DSL
One-liners are fun, but let's build a real page. Create a file called
serve.nu:
use -nu/html *
Run it:
Tags are uppercase Nushell commands: H1, P, UL, DIV. The first
argument can be an attribute record: {class: "intro"}. Everything after
that is children -- strings, other tags, or lists. Plain strings are
auto-escaped for XSS protection.
HTML prepends <!DOCTYPE html>. class accepts a list:
{class: [bold italic]}. Boolean attributes work too: {disabled: true}.
Step 3: Routing
Every request currently hits the same handler. Let's add proper routing with the built-in router module.
use -nu/html *
use -nu/router *
dispatch tests routes in order -- first match wins. Each route takes a
test (a record for matching, or true for catch-all) and a handler closure.
The handler receives the request and a context record.
You can match on method, path, or both. For dynamic segments use
path-matches:
Step 4: The Store
Time to persist messages. http-nu embeds
cross.stream, an append-only event store. Enable it
with --store, and add -w for watch mode so the server reloads when you
edit the script:
use -nu/html *
use -nu/router *
Add some messages:
Refresh the page -- your messages are there. Restart the server -- still
there. The store persists to ./store on disk.
Notice message-card and page. In http-nu, reusable HTML fragments are
just Nushell def commands. Each returns an {__html: ...} record that
other tags accept as children without re-escaping. Composition is just
function calls.
Step 5: Datastar -- Live Updates
Now for the payoff. Datastar is a lightweight hypermedia framework that connects your HTML to the server via server-sent events. http-nu ships with a built-in Datastar SDK and serves the JS bundle directly.
use -nu/html *
use -nu/router *
use -nu/datastar *
Open http://localhost:3001 in two browser tabs. Sign the guestbook in
one -- the message appears instantly in both. No page refresh.
Here is what is happening:
- Reactive signals:
data-signalsdeclares client state (nameandmessage).data-bindtwo-way binds the inputs to those signals. - Server actions:
data-on:submit.preventintercepts the form and sends signals as JSON via@post('/sign'). The server stores the message and responds withto datastar-patch-signalsto clear the form. - Live feed:
data-on:loadopens an SSE connection to/feed. New messages stream throughto datastar-patch-elements, which tells Datastar exactly which DOM element to update and how (appendmode). - Streaming:
.cat messages --follow --newis a long-lived stream. Each new entry flows througheach, gets wrapped as an SSE event, and reaches the browser immediately.
No client-side JavaScript. No virtual DOM. No build step. Just HTML fragments streamed over SSE.