Colophon
The boring details about how this site is put together, for the people who care about that sort of thing.
Stack
- Application: Flask 3.1 on Python, WSGI via Gunicorn (2 workers, Unix socket), reverse-proxied through Nginx with HTTP/2 and keepalive connections.
- Database: SQLite 3 with WAL mode. Schema migrations via Flask-Migrate (Alembic). Full-text search via FTS5 with porter tokenizer.
- Templating: Jinja2 server-side rendering. Markdown processed through Python-Markdown (fenced_code, tables, toc, attr_list, admonition, def_list extensions), sanitized by nh3, a Rust-based HTML cleaner that replaces Bleach.
-
Frontend:
Bootstrap 5.3.3 (unused selectors
stripped by PurgeCSS at deploy time),
HTMX 2.0.4 for partial page updates without a build step
or client-side routing. Light/dark theme toggle with OS preference detection via
prefers-color-scheme, persisted to a cookie. All colors defined as CSS custom properties; theme switching overrides variables without reloading the page. Command palette (Ctrl+K) with live search, keyboard navigation between entries (arrow keys), and heading anchor links for shareable deep links. No React, no Vue, no webpack; just<script defer>and vanilla JS. -
Syntax Highlighting:
Prism.js 1.29 with line-numbers, line-highlight, and a
custom grammar definition for Asterisk dialplan syntax
(
language-asterisk). Token colors adapt to the active theme via CSS attribute selectors. - Content Editing: Editor.js block editor with a custom code tool that preserves language, title, and line highlight metadata through the markdown conversion round-trip. Custom Alert block tool with configurable admonition types (note, tip, info, warning, danger, important). marked.js and DOMPurify handle markdown preview.
- Content Operations (MCP): The site is managed in part through a Model Context Protocol server that exposes the production database as a set of Claude Code tools. Capabilities include reading and writing content entries, managing the changelog, moderating community submissions and user notes, resolving content flags, managing tags (rename, merge, search by usage), and querying site and search statistics. A separate log analysis interface imports the nginx access log incrementally into a SQLite database every five minutes, then exposes traffic stats, error queries, and path searches as additional MCP tools. The server runs in two modes: local (direct SQLite access during development) and remote (JSON commands piped over SSH to lightweight dispatcher scripts on the production host). No persistent process is required on the server side; each dispatcher reads stdin and exits.
- User Notes: Community-contributed notes on every content page, moderated before display. Four-layer anti-spam: honeypot fields, rate limiting, email confirmation (trusted contributors bypass), and admin approval. The consulting form uses the same honeypot + rate-limiting approach.
- Community Voting: Anonymous upvoting on all content pages. Server-side deduplication via SHA-256 hash of IP and user agent, with cookie-based UI state. Sortable by "Most upvoted" on category, tag, and updates pages.
- Tools: Interactive Dial Pattern Tester (client-side pattern matching engine with specificity ranking) and Audio Converter (server-side conversion via sox and ffmpeg with volume normalization, silence trimming, and G.722 wideband output). Shareable short URLs for pattern test results. Downloadable bundles via wget/curl with 24-hour retention.
-
SEO Pipeline:
Structured data (JSON-LD) on every page type. Dynamic sitemap with lastmod.
IndexNow integration for instant
search engine notification.
llms.txtfor AI discoverability. Social images auto-generated via ImageMagick. Version compatibility matrix across 880+ reference entries. - Mail: Postfix handles forward-only delivery for the domain (virtual aliases, no local mailboxes) and outbound relay for the consulting contact form. TLS where the other side supports it. Spam gets caught early by Spamhaus and SpamCop RBLs before the message body is even transferred.
Typography
- Headings, code, UI chrome: JetBrains Mono (weights 400 to 800), self-hosted WOFF2.
- Body text: Source Sans 3 (weights 400 to 700), self-hosted WOFF2.
Both use
font-display: swap.
The two primary weights (400) are preloaded via
<link rel="preload">
to avoid layout shift. The @font-face declarations are inlined directly into
<head> to eliminate one render-blocking request.
Performance
- CSS purged at deploy time: Bootstrap Icons stripped from ~2,000 icon rules to the ~80 actually used (96% reduction). Bootstrap CSS run through PurgeCSS against the template corpus.
-
All CSS files (Bootstrap, custom theme, tools, icons, syntax highlighting)
concatenated into a single
combined.cssat deploy time, reducing 7 HTTP requests to 1. URL paths rewritten during concatenation so font references resolve correctly from the new location. -
Static assets minified in-place
(rcssmin/rjsmin),
then pre-compressed to
.gzfiles for Nginx'sgzip_staticdirective, so Nginx never compresses on the fly. -
Nginx
response cache
(5-minute TTL, keyed on URI +
HX-Requestheader +view_modecookie) with stale-while-revalidate fallback. -
Static files served with
Cache-Control: public, immutableand 30-day expiry. No CDN; single-origin, same box. - Google Analytics is deferred until the first user interaction or a 4-second idle timeout, so it doesn't touch LCP.
Security
-
CSRF on all state-changing
endpoints (Flask-WTF).
Flask-Limiter rate-limits login
(10/min) and submissions (5/hr). Nginx
limit_req_zoneadds a second layer at the proxy. - All user-submitted content sanitized through nh3 with an explicit allowlist of tags and attributes.
-
HSTS
(2 years, includeSubDomains, preload),
X-Content-Type-Options: nosniff,X-Frame-Options: DENY, strictReferrer-PolicyandPermissions-Policy. -
Admin interface runs as a separate Gunicorn instance, accessible only via SSH tunnel.
Blocked at the Nginx level on the public vhost (
return 404). - Honeypot field on submission form for bot detection.
- Fail2ban jails on SSH, Nginx (bad bots, auth failures, script probes, rate limit violations, vulnerability scanners), and Postfix (connection abuse, SASL brute force).
Deployment
- Ansible playbooks (~1,900 lines across VM and Incus container targets). Code synced via rsync, virtualenv rebuilt on dependency changes, database backed up pre-migration with 7-day rotation.
- TLS via Let's Encrypt with certbot auto-renewal timer.
- Deploy pipeline: rsync code → regenerate llms.txt → purge CSS → minify → gzip-compress → migrate DB → restart Gunicorn → health check. Internal link checker validates all content cross-references post-deploy.
-
IPv4 and IPv6 firewalls via iptables. Systemd hardening with
ProtectSystem=strict,RuntimeDirectory-managed runtime paths, read-only application directories at runtime, andNoNewPrivileges. - Nginx access and error logs rotated weekly (13-week retention) via an explicit logrotate config. Gunicorn output captured by journald (500 MB cap, 3-month retention).
Open Source
| Project | License |
|---|---|
| Flask | BSD 3-Clause |
| SQLite | Public Domain |
| Bootstrap | MIT |
| Bootstrap Icons | MIT |
| HTMX | BSD 2-Clause |
| Prism.js | MIT |
| JetBrains Mono | SIL OFL 1.1 |
| Source Sans 3 | SIL OFL 1.1 |
| Python-Markdown | BSD 3-Clause |
| nh3 | MIT |
| Flask-Limiter | MIT |
| Flask-SQLAlchemy | BSD 3-Clause |
| marked.js | MIT |
| DOMPurify | Apache 2.0 / MPL 2.0 |
| Editor.js | Apache 2.0 |
| Gunicorn | MIT |
| Nginx | BSD 2-Clause |
| Let's Encrypt | MPL 2.0 |
| SoX | GPL 2+ |
| FFmpeg | LGPL 2.1+ |
By the Numbers
958
Published Entries
20
Categories
174
Tags
536
Automated Tests
| Python (application + shared + admin + tools) | ~8,400 lines |
| Jinja2 templates | 77 files |
| Custom CSS | ~68 KB |
| Vanilla JavaScript | ~64 KB |
| Database migrations | 22 |
| Ansible deploy playbooks | ~1,900 lines |
| Test suites | 2 (public + admin) |