FastAPI engine, Caspian workflow
Run native async Python with FastAPI dependencies and middleware, then expose route-local work through typed RPC, streaming responses, uploads, and redirects.
A full-stack framework that combines FastAPI, Python-only routing, focused components, and PulsePoint reactivity in one application model.
from casp.component_decorator import html from src.components.TodoList import TodoList async def page(): todos = await load_todos() return html(r""" <main class="space-y-6"> <x-todo-list items="{{ todos | json }}" /> </main> """, todos=todos)
One application model
Python owns routing, data, actions, and reusable UI. PulsePoint adds reactive browser behavior without introducing a separate frontend application.
Run native async Python with FastAPI dependencies and middleware, then expose route-local work through typed RPC, streaming responses, uploads, and redirects.
State, effects, refs, context, portals, transitions, optimistic updates, error boundaries, and SPA navigation.
Create src/app/users/index.py. Nested layout.py modules compose the surrounding shell.
Enable Prisma to generate an async Python ORM for route loaders, RPC actions, uploads, auth flows, and shared services.
async def page(): users = await prisma.user.find_many() return html(markup, users=users)
RPC for request/response work, generator streams for progressive output, multipart RPC for uploads, and named sockets for persistent bidirectional channels.
PPIcons
Bring Lucide-based icons into the project as native Python components. They participate in real imports, prop forwarding, class merging, and the same x-* composition system as your UI.
Add accessible Python components to your own source tree, import them explicitly, and adapt every detail. The result stays readable, local, and native to Caspian.
✔ Button → src/lib/maddex/Button.py
✔ Accordion → src/lib/maddex/Accordion.py
from casp.component_decorator import component, html from casp.html_attrs import get_attributes @component def Button(variant="default", **props): attributes = get_attributes( {"type": "button", "class": styles[variant]}, props, ) return html(r""" <button {{ attributes }}>{{ children | safe }}</button> """, attributes=attributes)
Live preview
Component-first authoring
Pages remain short assemblies. Each substantial header, toolbar, form, table, panel, or repeated card becomes a focused Python component — one native root when it takes props, or a fragment when it does not.
from casp.component_decorator import component, html from casp.html_attrs import get_attributes @component def StatusCard(label="", value="", **props): attributes = get_attributes( {"label": label, "value": value}, props, ) return html(r""" <article {{ attributes }}> <p>{label}</p> <strong>{value}</strong> </article> """, attributes=attributes)
Keep Python parameters, server interpolation, readable HTML, and the owning PulsePoint script together. Use real imports for every child x-* tag.
Forward browser-facing props with get_attributes(...) so the native root exposes them to pp.props.
Live usage
<x-status-card label="Users" value="42" />Call declared Python actions from component events. Caspian filters payload keys, applies auth and rate policy, serializes results, and supports normal, multipart, and streamed responses.
from casp.rpc import rpc @rpc(require_auth=True, limits="30/minute") async def like_post(post_id: str): post = await prisma.post.update( where={"id": post_id}, data={"likes": {"increment": 1}}, ) return {"likes": post.likes}
<button onclick="likePost()"> Likes: {likes} </button> <script> const [likes, setLikes] = pp.state(0); async function likePost() { const result = await pp.rpc( "like_post", { post_id: "123" }, { abortPrevious: true } ); setLikes(result.likes); } </script>
Start with the core, then enable the capabilities your application needs in caspian.config.json. They join the same runtime, project structure, and verification workflow.
"mcp": trueMount an app-owned FastMCP server at /mcp, share the FastAPI lifespan, and protect production access with MCP_AUTH_TOKEN.
➜ fastmcp run src/lib/mcp/fastmcp.json
✔ tools mounted → /mcp
"websocket": trueDefine authenticated Python @socket() handlers and connect through pp.socket(). Pools support rooms, broadcasts, presence, chat, and collaboration.
npm run check runs Pyright, Ruff, authored-template validation, and Pytest in one deterministic application gate.
pyright — pass
ruff — pass
templates — pass
pytest — pass
✓ all checks passed
npm run format formats component markup with djLint, then Python with Ruff. Every markup rewrite is checked against the original and written only when it is guaranteed to render identically — unproven blocks are skipped and reported.
markup — 418 blocks formatted
python — 37 files reformatted
⚠ 12 skipped — would change rendering
a skip is a result, not a failure
PulsePoint errors, uncaught exceptions, interaction failures, and clean page loads feed a route-aware browser log. npm run logs reports what is clean, unresolved, or still needs an interaction recheck.
LIVE dev session active
✕ /dashboard — total is not defined
/ — clean
routes not listed were never opened
Pre-render eligible routes and public assets into deployable static HTML, including declared paths for dynamic routes.
✔ /docs → static/docs/index.html
Centralized sessions, OAuth providers, redirects, RBAC, route privacy, RPC authorization, secure headers, CSRF, rate limits, and safe public-file delivery.
✔ fail-closed production defaults
A deliberate workflow
Caspian keeps project generation, local development, framework updates, production builds, static export, and application checks discoverable through one project surface.
Create
npx create-caspian-app@latest
Develop
npm run dev
Verify
npm run check
Start with installation, then follow the feature guides for your project.