Flash Messages
Flash messages are short notices a handler sets before a redirect — “Saved!”, “Could not delete”, etc. — that the next request reads and displays. After the next request, the message is gone automatically. It’s the classic pattern for post-redirect form feedback.
Keys are arbitrary strings — use whatever name makes sense for your app. Common ones are "success", "error", "notice", but nothing stops you from using "cart_added", "payment_failed", "onboarding_step_done".
Configuration
Section titled “Configuration”| Option | Type | Default | Description |
|---|---|---|---|
| (none) | Flash takes an empty FlashConfig today; behavior is governed by the surrounding session. |
Flash rides on the existing session middleware, so the session cookie lifetime controls how long an unread flash could theoretically survive (though they clear on first read). Messages are stored in the same in-memory assigns-backed session store — nothing hits the database.
Basic usage
Section titled “Basic usage”-
Register
sessionandflashin the pipeline — in that order, becauseflashreads from values the session middleware loaded intoctx.assigns.const App = pidgn.Router.define(.{.middleware = &.{pidgn.session(.{}),pidgn.flash(.{}),},.routes = &.{pidgn.Router.post("/posts", createPost),pidgn.Router.get("/posts/:id", showPost),},}); -
Set a flash before redirecting — call
ctx.putFlash(key, message)in the handler that finishes the write, then redirect.fn createPost(ctx: *pidgn.Context) !void {// ... save the post ...try ctx.putFlash("success", "Post created");ctx.redirect("/posts/42", .see_other);} -
Read it on the next request — in the redirect target,
ctx.getFlash(key)returns the message once, then it’s gone.fn showPost(ctx: *pidgn.Context) !void {const notice = ctx.getFlash("success"); // optionaltry ctx.render(ShowTemplate, .ok, .{.flash_success = notice orelse "",// ... other template fields});}
Naming your keys
Section titled “Naming your keys”Any string works. Some common patterns:
try ctx.putFlash("success", "Saved!");try ctx.putFlash("error", "Could not connect");try ctx.putFlash("notice", "Your session has expired");try ctx.putFlash("warning", "This profile is public");
// App-specific keys are fine too:try ctx.putFlash("cart_added", "Item added to your cart");try ctx.putFlash("payment_failed", "Your card was declined");try ctx.putFlash("onboarding_done", "You're all set!");ctx.putFlash returns an error (it allocates the compound key from the request arena), so remember the try.
Rendering in a template
Section titled “Rendering in a template”The handler is responsible for piping the flash into the template’s data struct — templates don’t reach into ctx.assigns directly. Render with a conditional:
{{#if flash_success}} <div class="alert alert-success">{{flash_success}}</div>{{/if}}{{#if flash_error}} <div class="alert alert-error">{{flash_error}}</div>{{/if}}A small helper keeps handlers tidy:
fn withFlash(ctx: *pidgn.Context, comptime keys: []const []const u8, base: anytype) @TypeOf(base) { var out = base; inline for (keys) |k| { @field(out, "flash_" ++ k) = ctx.getFlash(k) orelse ""; } return out;}
// usage:try ctx.render(Tmpl, .ok, withFlash(ctx, &.{"success", "error"}, .{ .title = "Home", .flash_success = "", .flash_error = "", // ...}));How it works
Section titled “How it works”The middleware maintains two naming conventions on top of the session store:
__flash_<key>— the pending value. Written byputFlashand persisted to the session so it survives the redirect.flash_<key>— the display value for the current request. Populated by the middleware at the start of each request (from the pending entry), cleared at the end so it doesn’t accumulate into the next request.
On each request, flash scans ctx.assigns for keys starting with __flash_, promotes each to its flash_<key> counterpart, zeroes the pending entry (so it doesn’t survive past this request), then runs the handler. After the handler, it clears the display keys so they don’t get persisted back into the session. Net effect: a pending flash becomes visible on exactly one subsequent request.
Related
Section titled “Related”- Sessions and CSRF Protection — the session middleware that flash depends on.
- Form builder — for the forms that typically trigger a flash message.