Returns Gallery

Every Chirp return type on one page

Page actions AI-ready formats and sharing
Open LLM text
Share with AI
Ask Claude Ask ChatGPT Ask Gemini Ask Copilot

What It Teaches

Chirp expresses intent through the value a handler returns: the return type picks the response shape. This runnable example puts every return type on one page so you can see, side by side, which one to reach for. Browse the table to pick a shape, then read its route inapp.pyfor a one-paragraph "use when".

Route Return type Use when
GET / Template Full-page render with no htmx negotiation
GET /fragment Fragment A named block is always the response
GET /page Page Browser requests need a full page; htmx requests need a block
POST /oob OOB One action updates multiple targets
GET /stream Stream A response can flush sections as they complete
GET /suspense Suspense Initial render needs a shell first, then deferred blocks
GET /events EventStream Post-load updates should arrive over SSE
POST /validate ValidationError Invalid form data should re-render a 422 fragment
POST /mutate MutationResult One mutation supports multiple UX flows
GET /redirect Redirect The browser should navigate elsewhere

Run It

PYTHONPATH=src python examples/standalone/returns_gallery/app.py

Open http://127.0.0.1:8000/and click through the cards. Hit the same URLs with anHX-Requestheader to watch content negotiation pick the fragment over the full page.

What a route looks like

Each route returns a different type and carries a docstring naming when to reach for it.Pageis the workhorse — one URL that serves a full page to browsers and a named block to htmx:

@app.route("/page", name="page")
def page_demo():
    """Page — fragment for htmx requests, full page for browser navigation.

    Use when: the same URL must serve both a standalone page and an htmx
    swap. Same template, same data, the framework picks the right shape
    based on the HX-Request header.
    """
    return Page("gallery.html", "demo_page", value=random.randint(1, 100))

Source: examples/standalone/returns_gallery/app.py.

Template, Fragment, Page, OOB, ValidationError, and MutationResult all render against one template —templates/gallery.html, a single file of named blocks.Stream and Suspenseeach render their own full document, so they use side templates (gallery_stream.html, gallery_suspense.html). EventStream(SSE) is a post-load channel with no shell of its own.

Source