Block-fetch dispatcher — URL-addressable blocks for any route.
GET/_frag{path}?_b=\{block} matches the underlying route for \{path},
invokes its handler, and returns only the named kida block. Makes every block
of every page a first-class, cache-friendly resource without requiring the
handler to know about fragment addressing.
URL scheme (RFC 0.2):
/_frag/prefix is reserved and collision-checked atapp.check()time.- Block name is a query param
_bso the{path:path}doesn't swallow it. - Trailing-slash variants are attempted transparently (
/fooand/foo/).
Why a query string? The underlying path may itself be a{path:path}
catch-all (/docs/{slug:path}) — encoding the block as a suffix segment
would be ambiguous. Query strings are CDN-friendly withoutVaryconfig.
Handler result coercion:
Template/Page/LayoutPage→ re-packed asFragmentwith the requested block name and handler context.Fragment→ returned as-is (handler already scoped to one block).- Anything else → 400; the block-fetch URL is not meaningful for it.
No live-block registration is required at this layer — this is the raw
mechanism. Sprint 2's@app.live_blockdecorator adds the allowlist +
freeze-time rewriting that turns a regular block into a true live block.
server.fragment_dispatch
| Name | Type | Default | Description |
|---|---|---|---|
type
|
|
— | |
qualified_name
|
|
— | |
element_type
|
|
— | |
description
|
|
— | |
source_file
|
|
— | |
line_number
|
|
— | |
is_autodoc
|
|
— | |
autodoc_element
|
|
— | |
_autodoc_template
|
|
— | |
_autodoc_url_path
|
|
— | |
_autodoc_page_type
|
|
— | |
title
|
|
— | |
doc_content_hash
|
|
— |
Symbols on this page
Resolved target route for a/_fragrequest.
Build the block-fetch URL for a(route_path, block_name)pair.
route_pathis the underlying user-route path. Leading slashes are normalised; trailing slashes are preserved (they…
400 — the fragment URL is well-formed but can't be dispatched.
Build the underlying path from the catch-all segment.
The catch-all strips the leading/_frag/. We put back a single leading slash. Trailing-slash handling…
Return the encoded target path segment for a fragment-dispatch URL.
Whether request addresses the block-fetch endpoint.
Resolve/_frag{path}?_b=...before middleware policy runs.
Convert a handler's return value into aFragmentfor block_name.
Raises_BadFragmentRequestfor streaming / mutation / redirect results — those have no…
Match the underlying route, invoke its handler, re-pack as a Fragment.
Return aPendingRoute that dispatches /_frag{path}?_b=block.
The closure captures app so the handler can reach the compiled router and provider registry at request time.
FragmentDispatchTarget
class
Resolved target route for a/_fragrequest.
fragment_url
function
def fragment_url(route_path: str, block_name: str) -> str
Build the block-fetch URL for a(route_path, block_name)pair.
route_pathis the underlying user-route path. Leading slashes are
normalised; trailing slashes are preserved (they affect the handler's
view ofrequest.path). block_nameis URL-safe as-is — the kida
block-name grammar is a subset of what URLs accept.
Usage::
fragment_url("/docs/intro", "recent_updates")
# "/_frag/docs/intro?_b=recent_updates"
Also available as a template global of the same name when the app is compiled — use it in htmx attributes::
<div hx-get="{{ fragment_url('/docs/intro', 'recent_updates') }}"
hx-trigger="load">loading…</div>
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
route_path
|
str
|
— | |
block_name
|
str
|
— |
_BadFragmentRequest
class
400 — the fragment URL is well-formed but can't be dispatched.
_normalize_target_path
function
def _normalize_target_path(encoded: str) -> str
Build the underlying path from the catch-all segment.
The catch-all strips the leading/_frag/. We put back a single leading
slash. Trailing-slash handling is left to the caller (we try both).
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
encoded
|
str
|
— |
_encoded_path_from_fragment_request
function
def _encoded_path_from_fragment_request(path: str) -> str | None
Return the encoded target path segment for a fragment-dispatch URL.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
path
|
str
|
— |
is_fragment_dispatch_request
function
def is_fragment_dispatch_request(request: Request) -> bool
Whether request addresses the block-fetch endpoint.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
request
|
Request
|
— |
resolve_fragment_dispatch_target
function
def resolve_fragment_dispatch_target(router: Router, request: Request) -> FragmentDispatchTarget
Resolve/_frag{path}?_b=...before middleware policy runs.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
router
|
Router
|
— | |
request
|
Request
|
— |
_coerce_to_fragment
function
def _coerce_to_fragment(result: Any, block_name: str) -> Fragment
Convert a handler's return value into aFragmentfor block_name.
Raises_BadFragmentRequestfor streaming / mutation / redirect results
— those have no single block to extract.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
result
|
Any
|
— | |
block_name
|
str
|
— |
_dispatch_fragment
function
async
async def _dispatch_fragment(app: App, request: Request) -> Fragment
Match the underlying route, invoke its handler, re-pack as a Fragment.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
app
|
App
|
— | |
request
|
Request
|
— |
make_fragment_dispatch_pending_route
function
def make_fragment_dispatch_pending_route(app: App) -> PendingRoute
Return aPendingRoute that dispatches /_frag{path}?_b=block.
The closure captures app so the handler can reach the compiled router and provider registry at request time.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
app
|
App
|
— |
View source · /home/runner/work/chirp/chirp/site/../src/chirp/server/fragment_dispatch.py:1