Routing
Caspian uses a high-performance file-system based router built on top of FastAPI. Your file structure defines your URL paths, making routing intuitive, type-safe, and async-native.
Core Concepts
All routes are defined inside the
src/app
directory. A route is simply a directory containing an
index.html
or
index.py
file.
| File Path | URL Path |
|---|---|
| src/app/index.html | / |
| src/app/about/index.py | /about |
| src/app/blog/posts/index.html | /blog/posts |
Async Page Logic (index.py)
For pages requiring metadata or server-side logic, use an
index.py file. Since we run on FastAPI,
the page() function should be
async to prevent blocking the event loop.
from casp.page import load_page title = "Caspian Documentation | The Native Python Web Framework" description = "Explore the comprehensive documentation for Caspian..." async def page(): # You can perform non-blocking DB calls here return load_page(__file__)
Dynamic Routes
Caspian supports dynamic segments using square brackets. These are
compiled into FastAPI path parameters (e.g.,
{id}) for
maximum performance.
Dynamic Segments
Wrap a folder name in brackets to create a variable segment.
Catch-all Segments
Use an ellipsis inside brackets to match multiple path segments.
Route Groups
You can organize your code without affecting the URL structure by wrapping a folder name in parentheses. This is useful for grouping related features (like auth) or opting specific routes out of a layout.
- src/app/(auth)/login/index.py /login
- src/app/(auth)/register/index.py /register
Layouts & Nesting
Layouts wrap your pages and preserve state during navigation. A layout is
defined by a
layout.html (and optional
layout.py) file. Layouts nest
automatically: a page inside
/dashboard/settings will be wrapped by the
Root layout, then the Dashboard layout.
<!DOCTYPE html> <html> <head> <title>{{ layout.title }}</title> <meta name="description" content="{{ layout.description }}" /> <!-- Global CSS / Scripts --> </head> <body> <NavBar /> <!-- Children are injected here --> {{ children | safe }} </body> </html>
Async Layout Logic (layout.py)
If you need to fetch data for a layout (like user info for a sidebar),
create a
layout.py file next to your HTML. It
must export an
async def layout() function.
from casp.auth import get_current_user async def layout(context_data): # context_data contains URL params (e.g. id=123) # Use await for non-blocking auth/db checks user = await get_current_user() return { "user": user, "theme": "dark" }