Changes for version 0.001000 - 2026-07-15
- Initial release.
- app { } block-scoped collector returning an assembled PAGI app value (no global state), built on PAGI::App::Router, PAGI::Middleware, PAGI::Lifespan, and PAGI::App::File.
- Routing verbs get/post/put/patch/del/any; group (prefix + shared middleware) and mount (nest any PAGI app); path placeholders (:name, {name}, {name:regex}, *splat) map to the handler signature.
- Return-value coercion: PAGI::Response as-is; hashref/arrayref to JSON (convert_blessed, so nested TO_JSON objects serialize); scalar to text/plain; undef/return; a loud 500. Thrown respond-ables are sent.
- enable (app-wide) and [\@middleware] (route/group) event-layer middleware; named middleware resolved like PAGI::Middleware::Builder.
- startup/shutdown lifecycle with app-lifetime shared state ($c->state).
- static file serving, custom not_found, websocket and sse (imperative), and streaming request/response bodies.
- $c->params strong parameters via PAGI::StructuredParameters (PAGI::Nano::Context::HTTP).
- Two run shapes: single-file app.pl and a lib/MyApp.pm modulino.
- Requires PAGI::Tools 0.002002 (extension-aware default WebSocket declines; stricter Test::Client lifespan-startup) and PAGI::StructuredParameters.
- Per-request service makers run at most once per service name per request even when they return undef; memoization is based on cache-key existence rather than value definedness.
- ServiceRegistry: a service builder that returns a Future croaks loudly at lifespan startup, naming the service, rather than silently storing the unresolved Future as the "service" (which fails cryptically later at $c->service). Service builders are synchronous by design; use a per-request maker (a plain coderef) or factory(...) for deferred or per-call construction.
- PAGI::Nano::resolve_service($app, $name): a test-facing seam to resolve an app-scoped service value after lifespan startup without issuing a request, via a private probe token on the assembled app coderef. Returns the raw app-scoped value (a per-request maker or factory marker comes back as-is, not per-request-resolved).
- Custom not_found responses emit protocol-valid decline events: SSE uses sse.http.response.*, and WebSocket uses websocket.http.response.* when the server advertises that extension. WebSockets without it bypass the handler and close for a portable body-less 403. Translated byte bodies may be buffered or streamed; SSE and WebSocket file/fh bodies fail loudly.
- Context uri_for percent-encodes decoded strings from UTF-8 bytes. Ordinary placeholders encode one segment and reject slash-containing values in favor of *splat routes; splats preserve separators while encoding each segment. Query keys and values remain sorted and use %20 for spaces.
Modules
A compact micro-framework front door over PAGI-Tools
Shared behavior for the contexts PAGI::Nano vends
The HTTP request context vended by PAGI::Nano
The SSE context vended by PAGI::Nano
The WebSocket context vended by PAGI::Nano
The per-app registry backing PAGI::Nano's service keyword
Examples
- examples/README.md
- examples/background-tasks/app.pl
- examples/bidirectional-websocket/app.pl
- examples/chat-showcase/app.pl
- examples/connection-introspection/app.pl
- examples/contact-form/app.pl
- examples/contact-form/public/index.html
- examples/custom-middleware/app.pl
- examples/custom-middleware/lib/Example/Middleware/ApiKey.pm
- examples/custom-middleware/lib/Example/Middleware/RequestTimer.pm
- examples/custom-send-events/app.pl
- examples/duplex-http-stream/app.pl
- examples/duplex-http-stream/probe.pl
- examples/error-handling/app.pl
- examples/flow-control/app.pl
- examples/full-demo/app.pl
- examples/game-of-life/app.pl
- examples/hello-http/app.pl
- examples/job-runner/app.pl
- examples/lifespan-state/app.pl
- examples/mini-framework/app.pl
- examples/mounted-stash-state/app.pl
- examples/named-routes/app.pl
- examples/periodic-events/app.pl
- examples/psgi-bridge/app.pl
- examples/quickstart/app.pl
- examples/request-body/app.pl
- examples/rest-resource/app.pl
- examples/sessions/app.pl
- examples/sse-broadcaster/app.pl
- examples/sse-custom-events/app.pl
- examples/sse-custom-events/probe.pl
- examples/static-file/app.pl
- examples/static-file/public/index.html
- examples/streaming-response/app.pl
- examples/strong-params-deep/app.pl
- examples/tasks-modulino/lib/MyApp.pm
- examples/utf8-echo/app.pl
- examples/websocket-echo/app.pl