River Rooks | Technical Publication & Systems Architecture Blog

Developer-centric, high-signal, low-noise personal technical publication and systems architecture blog.

Inspired by native terminal environments, modal text editors (Zed, Ghostty), and tiling window managers, this site prioritizes raw performance, keyboard navigability, information density, and structured craftsmanship over generic marketing aesthetics.


1. Quickstart: Production Server Deployment

The production deployment uses a decoupled container architecture. The server does not need Node.js, git, or build dependencies—it only pulls the prebuilt engine from the registry and mounts a local folder containing your Markdown posts.

1.1 Server Directory Structure (~/docker/blog)

~/docker/blog/
├── .env                  # Environment variables (SITE_DOMAIN, etc.)
├── docker-compose.yml    # Production container definition
└── posts/                # Your live Markdown articles (.md)

1.2 Production docker-compose.yml

services:
  web:
    image: git.riverrooks.dev/venus/river-rooks-blog:latest
    container_name: river_rooks_web
    restart: unless-stopped
    volumes:
      - "./posts:/app/src/posts:ro"
    environment:
      - "SITE_DOMAIN=${SITE_DOMAIN:?Error: SITE_DOMAIN is not set. Please define SITE_DOMAIN in .env}"
      - "SITE_URL=${SITE_URL:-https://${SITE_DOMAIN}}"
      - "PORT=${PORT:-8080}"
      - "WATCH=${WATCH:-false}"
    ports:
      - "${HOST_PORT:-${PORT:-8080}}:${PORT:-8080}"
    networks:
      - backend
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.blog.rule=Host(`riverrooks.dev`) || Host(`www.riverrooks.dev`)"
      - "traefik.http.routers.blog.entrypoints=websecure"
      - "traefik.http.routers.blog.tls.certresolver=basic"
      - "traefik.http.services.blog.loadbalancer.server.port=8080"
      - "traefik.docker.network=backend"

networks:
  backend:
    external: true

1.3 Deployment Commands

# 1. Pull the prebuilt engine from Gitea registry
docker compose pull

# 2. Launch the container
docker compose up -d

# 3. Verify healthcheck status (transitions to healthy in 3-5 seconds)
docker compose ps

2. Local Development & Verification

All templates, styles, and engine code are developed in this repository (~/code/blog).

2.1 Native Node.js Workflow

# Install dependencies
npm install

# Run automated test suite (unit tests, filters, server, and docker assertions)
npm test

# Launch Eleventy dev server with hot-reload (binds to http://localhost:8080)
npm run dev

# Compile static assets to _site/
npm run build

# Start the native static server locally
npm start

2.2 Local Docker Compose Workflow

The local docker-compose.yml provides sensible defaults (localhost, port 8080, and mounts ./src/posts):

# Build and run the local container stack
docker compose up -d --build

# View container logs (Eleventy compilation + server output)
docker compose logs -f

# Stop and clean up
docker compose down

2.3 Development Standards: Strict TDD & Adversarial Verification

This project enforces a strict test-first development lifecycle and verification standard:

  1. Tests Written Before Functional Code: Automated test cases in test/ must always be written before writing or modifying any functional code, filters, templates, server endpoints, or scripts.
  2. Mandatory Adversarial Testing: Standard behavior for any functional change must always include adversarial test cases (boundary values, malformed/null inputs, unauthorized requests, path traversals, corrupt frontmatter, and design spec violations).
  3. Pre-Presentation Verification Gate: Every change must be verified by running npm test. All test cases must pass before presenting the final output or committing code.

3. Push & Update Cycles

Because the system separates the Engine (templates/code) from the Content (markdown notes), updates follow two distinct paths:

3.1 Publishing or Editing Articles (Content Workflow)

When you write a new note or edit an existing article:

  1. Add or update the Markdown file in posts/ (e.g. posts/my-new-post.md):
    ---
    title: "My Article Title"
    date: 2026-09-14
    tags: ["#systems", "#architecture"]
    excerpt: "A short synopsis of the article."
    ---
    
    # Article Content...
    
  2. Recompile the site:
    docker compose restart web
    
    Eleventy compiles the mounted markdown in ~150ms and starts serving immediately.

Tip

Zero-Restart Live Reload: Set WATCH=true in your server's docker-compose.yml environment. Eleventy will watch the posts/ directory in the background. Whenever a note is saved or synced (e.g., from Obsidian), the site automatically updates in memory without running any commands.

3.2 Updating Blog Templates, CSS, or Features (Engine Workflow)

When you modify design tokens, Nunjucks templates, server routes, or dependencies:

  1. Develop and verify locally:
    npm test
    
  2. Build and push the new engine image to the Gitea container registry:
    # Build the engine image
    docker build -t git.riverrooks.dev/venus/river-rooks-blog:latest .
    
    # Push to Gitea
    docker push git.riverrooks.dev/venus/river-rooks-blog:latest
    
  3. Update the production server:
    docker compose pull
    docker compose up -d
    

4. System Architecture & Structure

4.1 High-Level Architecture

┌─────────────────────────────────────────────────────────────┐
│                    Dev Machine / Workstation                │
│  src/ (templates, CSS, config) + Dockerfile + entrypoint.sh │
└──────────────────────────────┬──────────────────────────────┘
                               │ docker push
                               ▼
┌─────────────────────────────────────────────────────────────┐
│       Gitea Container Registry (git.riverrooks.dev)         │
│          image: venus/river-rooks-blog:latest               │
└──────────────────────────────┬──────────────────────────────┘
                               │ docker pull
                               ▼
┌─────────────────────────────────────────────────────────────┐
│                     Production Server                       │
│                                                             │
│   ~/docker/blog/posts/ ──(volume)──> [ river_rooks_web ]    │
│   (Live Markdown Notes)               ├── entrypoint.sh     │
│                                       ├── 11ty compiles     │
│   Traefik (SSL / Proxy) <──────────── └── server.js (:8080) │
└─────────────────────────────────────────────────────────────┘

4.2 Key Engine Components

  • entrypoint.sh: Dynamic container entrypoint. Compiles mounted markdown notes with Eleventy on boot, starts optional background file watcher, and spawns server.js as PID 1 for clean signal handling.
  • Dockerfile: Minimal node:22-alpine container with pre-installed dependencies, baseline static pre-compilation, and baked-in HEALTHCHECK querying http://127.0.0.1:8080/healthz.
  • server.js: Zero-dependency native Node static web server supporting clean directory URLs, MIME caching, security headers, and the /healthz telemetry endpoint.
  • eleventy.config.js: Eleventy 3.x configuration, custom collections (posts, tagList), markdown-it anchor plugins, and custom date/reading-time filters.

4.3 Directory Map

.
├── .agents/                        # Antigravity agent configurations & rules
├── sample-designs/                 # Design specifications & HTML/CSS prototypes
├── src/                            # Blog engine source
│   ├── _data/                      # Site metadata & navigation
│   ├── _filters/                   # Modular Eleventy filters (date, readingTime, headings)
│   ├── _includes/
│   │   ├── layouts/                # Base & post Nunjucks templates
│   │   └── partials/               # Global bar, hero tile, post cards, code box
│   ├── assets/
│   │   └── css/                    # Modular CSS (tokens, reset, layout, components)
│   └── posts/                      # Default/fallback markdown posts
├── test/                           # Automated test suite (node:test)
├── docker-compose.yml              # Local development compose file
├── sample-docker-compose.yml       # Production-ready compose template
├── Dockerfile                      # Production container image definition
├── entrypoint.sh                   # Container startup & compilation entrypoint
├── server.js                       # Native Node static HTTP server
├── eleventy.config.js              # Eleventy configuration
├── package.json                    # Project scripts & dependencies
└── README.md                       # Documentation & runbook

5. Strict Design Specification

All UI components and stylesheets strictly follow sample-designs/design-specification.md:

Rule Constraint
Color Scheme Dark-mode native only. Canvas: #0d0f12, Surface: #121417, Elevated: #1c1f26, Borders: #2b303b.
Accents Terminal accents: Cyan (#00f0ff), Green (#00e676), Amber (#ffb700), Red (#ff5252).
Borders & Radius Crisp 1px solid borders. Zero to 4px maximum border-radius (sharp corners).
Strict Anti-Patterns NO glassmorphism (backdrop-filter), NO drop shadows or glows, NO gradients, NO spring animations.
Typography Monospace for UI & code (IBM Plex Mono, JetBrains Mono); clean sans-serif for body prose (Inter).
Interactivity Instant binary hover snaps (no slow fade transitions); high-contrast focus outlines for keyboard navigation.
S
Description
My super awesome blog
Readme
625 KiB
Languages
JavaScript 50.7%
HTML 28.8%
CSS 10.9%
Nunjucks 8.9%
Shell 0.4%
Other 0.3%