# Architecture > Status: the core library, the public JSON API, and the server-rendered admin > (login, CSRF, post CRUD, Markdown editor + live preview) are implemented. **volumen** is a small, file-based Markdown blog engine written in Python. It has no database: every post is a `.md` file on disk with a TOML frontmatter block. The engine reads those files, exposes them as a JSON API, and ships a server-rendered admin for editing them. ## Design goals - **File-based** — posts are plain `.md` files, safe to commit to Git and edit by hand or through the admin. - **Self-contained** — runs as a single Python process (Uvicorn) under FastAPI; no Node build step is required to operate the engine or its admin. - **Dependency-light** — a small, well-chosen set of PyPI packages (FastAPI, python-markdown, Jinja2, itsdangerous, python-multipart) rather than a full-stack framework. The standard library covers cryptography. - **Markdown-first** — the visual editor round-trips through the same renderer that powers the public API, so stored content is always Markdown. ## Components ``` src/volumen/ __init__.py # VERSION + in-memory login-attempt rate limiter cli.py # argparse entry point: serve, hash-password, version config.py # loads config.toml via stdlib tomllib, deep-merges defaults frontmatter.py # parse/serialise the `+++ … +++` TOML block post.py # Post model: metadata + raw body + rendered HTML store.py # reads the content directory into Post objects (mtime-cached) markdown.py # python-markdown + pymdown-extensions wrapper,
/
feed_helpers.py # RSS / JSON Feed / sitemap generation users.py # users.toml + admin/author roles password.py # scrypt hashing/verification (hashlib + secrets.compare_digest) api_routes.py # /api/volumen/* (FastAPI APIRouter) admin_routes.py # /admin/* + /media/* (FastAPI APIRouter) server.py # create_app factory, middleware, dependency helpers web/ templates/ # Jinja2 templates for the admin static/ # static assets (volumen-logo.svg, volumen-icon.svg) exe/volumen # thin shim that calls volumen.cli:main ``` ## Request flow ```mermaid graph TD A[HTTP request] --> B{Route} B -->|/api/volumen/*| C[api_routes.py] B -->|/admin/*| D[admin_routes.py + CSRF + CSP] B -->|/media/*| E[admin_routes.py media_router] C --> F[Store] D --> F D --> U[Users] C --> H[FeedHelpers] C --> G[Markdown renderer] F --> I[(content_dir/*.md)] F --> J[(content_dir/media/*)] U --> K[(users.toml)] H --> F G --> L[
for titled images] D --> M[SessionMiddleware + CSPMiddleware] C --> M E --> M ``` ## Middleware stack - `SessionMiddleware` (Starlette) — signed cookie session, signed with `itsdangerous` using the secret derived from `[admin].session_key`. Set to `HttpOnly` and `SameSite=Strict`; `Secure` is added by `SecureCookieMiddleware` when the request was forwarded over HTTPS. - `SecureCookieMiddleware` (custom) — inspects `X-Forwarded-Proto` (when `[server].trust_proxy = true`) and exposes `request.state.session_secure` for downstream code that needs to know whether the request is HTTPS. - `CSPMiddleware` (custom) — injects the `Content-Security-Policy` header on every `/admin/*` response. ## Public site integration The public website (e.g. `petrbalvin.org`, a Vue 3 + Vite + Tailwind SPA) consumes volumen's JSON API. volumen does not render the public site itself; it is headless for the front-end and only renders its own admin.