Caspian Utils (casp)
HTML-first utilities for Caspian applications.
caspian-utils is the shared Python runtime package behind Caspian templates, components, layouts, RPC handlers, and supporting utilities. This repository is not a full application starter, so this README documents the package surface that exists here.
- PyPI package:
caspian-utils - Python package:
casp - Python requirement:
>=3.14
Installation
pip install caspian-utils
Core Model
Caspian is HTML-first.
- write UI in
.html - use native Jinja syntax for server-rendered values and control flow
- define reusable components in Python
- import components with
@importcomments inside HTML - render components with
<x-component-name />tags - place child routes in layouts with a real HTML
<slot /> - render pages and layouts from Python with helpers in
casp.layout
There is no Caspian-only template syntax layer. Use standard Jinja {{ ... }} and {% ... %} directly.
HTML-First Components
Define a component in Python
from casp.component_decorator import component
@component
def AlertBox(title: str, children: str = "", class_name: str = "") -> str:
return f"""
<section class="alert {class_name}">
<h2>{title}</h2>
<div>{children}</div>
</section>
"""
Import and use it in HTML
<!-- @import { AlertBox } from "../components/ui" -->
<main class="space-y-4">
<x-alert-box title="Saved">
<p>Your settings were updated.</p>
</x-alert-box>
</main>
Alias imports when needed
<!-- @import { AlertBox as Notice } from "../components/ui" -->
<div>
<x-notice title="Heads up" />
</div>
Import and tag rules:
AlertBoxbecomes<x-alert-box>- aliases also convert to kebab-case, so
Noticebecomes<x-notice> - grouped imports use
<!-- @import { A, B as C } from "..." --> - single imports use
<!-- @import ComponentName from "..." --> - paths are resolved relative to the current template or component directory
Example: <!-- @import { AlertBox } from "../components/ui" --> resolves AlertBox from ../components/ui/AlertBox.py.
Rendering Pages
Use casp.layout to render HTML templates relative to a Python file.
from casp.layout import render_page
def get_dashboard() -> str:
return render_page(__file__, {
"pageTitle": "Dashboard",
"stats": ["Projects", "Tasks", "Alerts"],
})
<!-- app/dashboard/index.html -->
<!-- @import { AlertBox } from "../components/ui" -->
<main class="space-y-6">
<h1>{{ pageTitle }}</h1>
<x-alert-box title="Welcome back" class="rounded border p-4">
<p>Rendered through an imported Python component.</p>
</x-alert-box>
<ul>
{% for label in stats %}
<li>{{ label }}</li>
{% endfor %}
</ul>
</main>
casp.layout also exposes render_layout(), render(), load_template(), compile_template(), and layout discovery helpers for nested layout flows.
Nested Layouts
Layouts are authored as HTML and use a real <slot /> element as the child-route outlet.
<!-- app/layout.html -->
<html>
<head>
<title>{{ metadata.title }}</title>
</head>
<body>
<slot />
</body>
</html>
During nested layout rendering, Caspian parses the layout HTML and replaces real <slot> elements with the current child page or nested layout. Escaped documentation text such as <slot /> is not treated as a layout outlet.
If a layout needs shared props or metadata, add a sibling layout.py:
from casp.layout import Metadata
metadata = Metadata(title="Dashboard")
def layout():
return {
"shell_class": "dashboard-shell",
}
Those props are available in layout.html as {{ layout.shell_class }}. The installed layout runtime supports sync or async layout() results, but layout work should stay focused on shared subtree props or metadata.
Template Syntax
Caspian templates use native Jinja:
{{ value }}for interpolation{% if condition %}...{% endif %}for conditionals{% for item in items %}...{% endfor %}for loops- filters such as
{{ children | safe }}
There is no additional Caspian template language on top of Jinja.
Template Constraints
Some compiler rules are important when writing templates:
- every page, layout, and component must render exactly one top-level HTML element
- unknown
<x-...>tags raise an error unless the component has been imported - async components are supported by the component pipeline
- authored PulsePoint scripts should be plain
<script>tags inside the single root; the runtime can rewrite them for browser execution
These constraints exist because Caspian injects pp-component metadata into the rendered root element.
RPC Helpers
The package also includes the server-side RPC decorator and related request/serialization utilities.
from casp.rpc import rpc
@rpc(require_auth=True, limits="30/minute")
async def save_profile(name: str):
return {"ok": True, "name": name}
casp.rpc includes:
- RPC registration
- auth-aware decorators
- rate limiting
- serialization for common Python objects
- FastAPI-oriented request and response helpers
Auth Policy
casp.auth provides the framework runtime for sessions, route checks, decorators, CSRF helpers, and OAuth providers. Application auth policy should live in an app-owned src/lib/auth/auth_config.py file, where the app builds AuthSettings and applies them during startup with configure_auth(...).
Keep route privacy, redirects, and RBAC policy in that app config file instead of changing casp.auth.
Main Modules
| Module | Purpose |
|---|---|
casp.layout |
Load, compile, and render pages and nested layouts with native Jinja and parser-based <slot /> replacement |
casp.html_native |
BeautifulSoup-backed fragment parsing helpers used by layout and component transforms |
casp.component_decorator |
@component, component loading, and HTML rendering helpers |
casp.components_compiler |
Parse @import directives and transform <x-...> component tags |
casp.html_attrs |
Attribute rendering, prop alias normalization, and Tailwind class merge helpers |
casp.scripts_type |
Rewrite authored PulsePoint scripts for browser runtime execution |
casp.rpc |
RPC decorator, registration, serialization, and request handling helpers |
casp.streaming |
Server-Sent Events helpers including SSE |
casp.auth |
Auth settings, session helpers, decorators, OAuth providers, and route checks |
casp.runtime_security |
Safe public-file serving, security headers, and production secret checks |
casp.cache_handler |
Page cache helpers |
casp.state_manager |
Request-scoped and session-backed state helpers |
casp.validate |
Validation and sanitization helpers for strings, IDs, files, dates, and numbers |
casp.caspian_config |
Config loading and file index helpers |
Included Dependencies
This release currently installs utilities commonly used by Caspian apps, including:
fastapijinja2beautifulsoup4slowapipython-multiparthttpxcuid2python-ulid
See setup.py for the pinned versions in this release.
Repository
TheSteelNinjaCode/caspian_utils
License
MIT
Author
Jefferson Abraham
Release files for caspian-utils 0.3.8
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| caspian_utils-0.3.8.tar.gz | 53.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| caspian_utils-0.3.8-py3-none-any.whl | Python 3 | none | any | Details |
Total release size:108.1 kB
Release files / caspian_utils-0.3.8.tar.gz
| Download URL | caspian_utils-0.3.8.tar.gz |
|---|---|
| Size | 53.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f6996585398d961eb03669400d570dca906764d1da7af8f37f78900b0816269d
|
|
BLAKE2b-256 checksum How to use checksums |
ee1f9b106b4fcb26f6c4a3be69dc999b7dfa200ae53fe38627e1315bdc855cdc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Release files / caspian_utils-0.3.8-py3-none-any.whl
| Download URL | caspian_utils-0.3.8-py3-none-any.whl |
|---|---|
| Size | 55.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
02777c15a7eaacd5fdd93c6ce2ba2a8a5bcc0d0cad45239f462b37d5a82aa992
|
|
BLAKE2b-256 checksum How to use checksums |
6bf10cf808b2d641f21134efa913d157ba782d17e6e7e686372cad9e81f34af6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|