Skip to content

Build an app (capstone)

The capstone. You’ve built tools, documents, typed programs, and an agent. Now kaos-ui assembles them into a complete application: a FastAPI backend on kaos-agents (SSE streaming, bearer auth, a virtual filesystem per session) and a Vite + React frontend — with Makefile, Docker, Caddy, and pre-commit included.

The scaffold step runs offline here via dry-run, so you can see exactly what you’d get without writing anything.

Terminal window
uv run examples/scaffold-app.py
Template 'web:spa' would create 77 files, including:
.env.example
.gitignore
AGENTS.md
...
Available templates: dashboard:streamlit, module, tui:textual, web:api, web:spa, workflow
examples/scaffold-app.py
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.13"
# dependencies = ["kaos-ui>=0.1.0a15,<0.2"]
# ///
"""The capstone: scaffold a full KAOS application.
`kaos-ui` generates production-shaped projects wired to the rest of KAOS. The
`web:spa` template is a complete app: a FastAPI backend on `kaos-agents` with
SSE streaming and bearer auth, plus a Vite + React frontend — Makefile, Docker,
Caddy, and pre-commit included.
This example uses **dry-run** mode, which reports exactly what *would* be written
without touching the filesystem — deterministic and offline. To actually create
the project, drop `dry_run=True` (or run `kaos-ui new web:spa my-app`).
Run it:
uv run examples/scaffold-app.py
"""
from __future__ import annotations
import kaos_ui
def main() -> "kaos_ui.ScaffoldResult":
result = kaos_ui.scaffold("web:spa", "my-legal-app", dry_run=True)
files = sorted(str(f) for f in result.files)
print(f"Template '{result.template}' would create {len(files)} files, including:\n")
for f in files[:8]:
print(f" {f}")
print(" ...")
print(f"\nAvailable templates: {', '.join(kaos_ui.kinds())}")
return result
if __name__ == "__main__":
result = main()
names = {str(f) for f in result.files}
# A real, non-trivial project: backend + tooling are all present.
assert len(result.files) >= 20, f"only {len(result.files)} files"
assert "Makefile" in names and ".env.example" in names
assert result.dry_run is True # we wrote nothing to disk

A complete, deployable monorepo — backend, frontend, and ops, wired together:

  • Directorymy-legal-app/
    • Directorybackend/ FastAPI on kaos-agents
      • Directoryapp/
        • main.py the app + SSE streaming endpoint
        • auth.py bearer-token auth
        • runtime.py KaosRuntime + agent wiring
        • settings.py typed settings
      • Directorytests/ auth · health · settings · uploads
      • Dockerfile
      • pyproject.toml
    • Directoryapps/spa/ Vite + React frontend
      • vite.config.ts
      • package.json
    • Directorypackages/ui/ shared UI components
    • Caddyfile TLS + reverse proxy
    • docker-compose.yml
    • Makefile make install · make dev
    • .env.example provider key + auth token
    • README.md

Drop dry_run=True, or use the CLI:

Terminal window
kaos-ui new web:spa my-legal-app
cd my-legal-app
make install # uv (backend) + pnpm (frontend), with supply-chain hardening
make dev # FastAPI + Vite dev servers

kaos-ui scaffolds more than web apps — see them all in the package reference and the how-to on adding your own template kind:

KindWhat you get
web:spaFastAPI + Vite/React full-stack app (this capstone)
web:apiFastAPI backend only
dashboard:streamlitA Streamlit data dashboard
tui:textualA terminal UI app
moduleA new KAOS module package
workflowA single-file script

You’ve walked the spine end to end. From here: