Request Bodies & Forms
Time for the classic: an HTML form POSTing to the server — no fetch, no JS, progressive enhancement’s favorite child.
<form method="post"> <input name="name"> <button>Join</button></form>On the receiving side, a POST handler declares how to read the body
with the form option (its sibling json handles JSON requests).
With either configured, context.body becomes a promise for the
parsed — and validated — body:
export const POST = Run.POST( { form(value) { return { name: String(value.name || "").trim() }; }, }, async (context, next) => { const { name } = await context.body; if (!name) return next({ error: "Name required" }); subscribers.push(name); return next({ welcomed: name }); },);The last piece is what next() means in a POST with a page present:
it renders the page — so the same URL can respond to the
submission with HTML, showing errors or success with full state. (The
other classic ending, redirect-after-post, is one
context.redirect("/thanks") away; both are legitimate, this lesson
uses render.)
The signup form on the right posts into the void — a 404, since no handler accepts POST:
- Fill in the handler as above (skeleton provided; the
subscribersarray is module-level, your first in-memory “database”). - Submit empty → the page renders the error from
$global.data. Submit a name → welcomed, and the count grows. Refresh — the count persists for the server’s lifetime. All without one line of client JavaScript.
- Installing dependencies
- Starting dev server