Files
volumen/docs/architecture.md
T

2.7 KiB

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 CRuby. 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.
  • Single-admin — one password, one content directory, one user.
  • Self-contained — runs as a single Ruby process; no Node build step is required to operate the engine or its admin.
  • Dependency-light — a small, well-chosen set of gems (Sinatra, kramdown, toml-rb, puma) rather than a full framework.
  • Markdown-first — the visual editor round-trips through the same renderer that powers the public API, so stored content is always Markdown.

Components

lib/volumen/
  version.rb       # gem version
  config.rb        # loads /etc/volumen/config.toml, applies CLI overrides
  frontmatter.rb   # parse/serialise the `+++ … +++` TOML block
  post.rb          # Post model: metadata + raw body + rendered HTML
  store.rb         # reads the content directory into Post objects (mtime-cached)
  markdown.rb      # kramdown wrapper (render + <figure>/<figcaption> for titled images)
  feed_helpers.rb  # RSS / JSON Feed / sitemap generation
  users.rb         # users.toml + admin/author roles
  password.rb      # scrypt hashing/verification (OpenSSL::KDF)
  api_routes.rb    # /api/volumen/* (Sinatra routes)
  admin_routes.rb  # /admin/* (Sinatra routes)
  server.rb        # Sinatra app: composes the two route modules, shared helpers
  cli.rb           # command dispatcher
  web/
    views/         # ERB templates for the admin
    public/        # static assets (volumen-logo.svg, volumen-icon.svg)
exe/volumen        # CLI: serve, hash-password, version, help

Request flow

graph TD
  A[HTTP request] --> B{Route}
  B -->|/api/volumen/*| C[api_routes.rb]
  B -->|/admin/*| D[admin_routes.rb + CSRF + CSP]
  C --> E[Store]
  D --> E
  D --> U[Users]
  C --> F[FeedHelpers]
  C --> G[Markdown renderer]
  E --> H[(content_dir/*.md)]
  E --> I[(content_dir/media/*)]
  U --> J[(users.toml)]
  F --> E
  G --> K[<figure> for titled images]

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.