Architektura a tech stack
Tech stack
- Backend: Rust (edition 2024), Axum 0.8, Tokio async runtime
- Databáze: PostgreSQL přes SeaORM 1.x; migrace běží automaticky při startu serveru
- Veřejné stránky: MiniJinja šablony renderované serverem (loader z
assets/<NAMESPACE>/templates/) - Admin UI: Vue 3 SPA (Pinia, Vue Router, Tailwind 4, Vite, TypeScript), buildovaná do
client/dist/a embedovaná do binárky přesrust-embed - Markdown: pulldown-cmark s vlastními direktivami (transclusion, obrázky, galerie, šachové pozice/partie)
- Auth: Argon2 hashování hesel, session cookies pro SPA, service tokeny (legacy) a OAuth2 (PKCE, RFC 7591) pro API/MCP klienty
- Logging:
tracing+tracing-subscribers env filtrem - AI: vlastní assistant podsystém v
src/ai/(více v about/blog/ai)
Struktura projektu
src/
bin/
site_server.rs # Hlavní HTTP server (port 3000)
site_migration.rs # Migration CLI (up/down/fresh/status)
site_cli.rs # Admin CLI (create-user, change-password)
routes/
public/ # Veřejné routes (catch-all, files, search, sitemap, tags)
api/ # JSON API (auth, pages, tags, files, galleries,
# menu, tokens, markdown, paths,
# assistant, llm, tool-permissions)
mcp.rs # MCP JSON-RPC endpoint pro Claude
oauth.rs # OAuth2 server (register, authorize, token, well-known)
revision.rs # Revize stránek
entity/ # SeaORM entity modely
user, token, page, page_revision, tag, menu,
file, file_blob, file_thumbnail, gallery,
oauth_{client,code,token},
llm_{provider,model},
assistant_{session,message},
user_mcp_server, tool_permission
migration/ # m_001 … m_022 (vč. fulltext indexu, OAuth, AI tabulek)
ai/ # Assistant: loop_driver, tool_registry, mcp_client,
# tool_permissions, local_tools, llm, handlers, config
auth.rs assets.rs config.rs files.rs
markdown.rs path_util.rs repo state.rs
client/ # Vue 3 SPA — Pinia, Vue Router, Tailwind 4, Vite
src/ # Komponenty, views, stores, router
dist/ # Build output (embedovaný do binárky)
assets/<NAMESPACE>/ # Multi-tenant statické bundly
css/ js/ img/ templates/ # MiniJinja šablony pro veřejné stránky
Jak server funguje
Při spuštění site_server proběhne:
- Inicializace
tracing(env filter zRUST_LOG). - Načtení
Configz prostředí (DATABASE_URL,PORT,NAMESPACE, …). - Vytvoření
AppState(DB pool + MiniJinja env naplněný zassets/<NAMESPACE>/templates/). - Spuštění SeaORM migrací (
Migrator::up) — automaticky. - Sestavení Axum routeru s podtřídami
mcp,oauth,public,api, admin SPA zrust-embed. - Listen na
0.0.0.0:$PORT.
Veřejné stránky — catch-all
Fallback handler GET /{*path} (viz src/routes/public/mod.rs):
- Hledá shodu v tabulce
menus→ renderuje její markdown. - Hledá shodu v tabulce
pages→ renderuje obsah stránky (skryté soukromé stránky pro nepřihlášené). - Jinak 404.
Markdown se renderuje custom direktivami (viz about/blog/mcp) a obalí se MiniJinja šablonou path_page.html.
Admin SPA
Routes GET /admin a GET /admin/{*path} čtou statické soubory z embedu client/dist/. Pokud cesta neexistuje (typický SPA hluboký link), server vrací index.html a Vue Router se postará o zbytek. Admin UI komunikuje výhradně přes JSON API /api/* — žádné serverové šablony.
Revize a diffy
Při každém uložení stránky se automaticky uloží řádek do page_revisions s diffem oproti předchozí verzi (knihovna diffy). Šetří místo, zachovává historii a dovoluje rollback přes POST /api/pages/:id/revisions/:rev_id/restore.