← back

rad.typo

derry: -°C | kp: - | cpu: -°C

infrastructure

rad.typo runs on a single-board computer connected to a home internet connection in derry. no cloud, no data centers, no build pipeline. songs, poems, and releases are stored as flat JSON files and rendered client-side by a single template per content type. at times the site may go down or get slow...
Raspberry Pi 3B+ server running 24/7 in Derry
hardware specifications [ + ]
computer
Raspberry Pi 3 Model B Plus Rev 1.3
cpu
ARM Cortex-A53 1.4GHz quad-core
memory
1GB LPDDR2 SDRAM (921MB usable)
storage
64GB microSD (SanDisk Ultra)
network
10/100 Ethernet (eth0)
power consumption
~2.4W idle • ~3.0–3.8W under load
software stack [ + ]
operating system
Raspberry Pi OS Lite (Debian 12)
web server
Apache 2.4.62 with mod_rewrite
server-side
PHP (email subscriptions only)
frontend
vanilla HTML/CSS/JS — no frameworks, no build step
content layer
flat JSON files (songs.json, poems.json) rendered client-side by a single template per type
url routing
.htaccess rewrite rules map /songs/*.html and /poems/*.html to their respective templates
audio
MP3 served directly by Apache — HTML5 audio element, no proprietary codecs
radio
Fisher-Yates shuffle queue, MediaSession API for lock screen controls
payments
Stripe hosted checkout — no card data touches the server
ssl certificate
Let's Encrypt (auto-renewing)
dns
DuckDNS dynamic DNS
security
UFW firewall + fail2ban + SSH key auth
monitoring
bash scripts on a cron, writing to /api/stats.json every 60 seconds
status bar caching
sessionStorage IIFE restores weather, KP, and CPU values instantly on every page load
external APIs [ + ]
weather
Open-Meteo — temperature and weather code at Derry coordinates (55.0147°N, 7.3029°W) · polled every 5 minutes
solar activity
NOAA Space Weather Prediction Center — planetary K-index (NOAA-scale geomagnetic storm indicator) · polled every 5 minutes · color-coded 0–9 from quiet green to extreme storm purple
server telemetry
/api/stats.json — local endpoint generated by bash script · CPU temp, GPU temp, memory, disk, uptime, network I/O, Apache request count · refreshed every 30 seconds
payments
Stripe — hosted checkout links only, no client-side Stripe SDK
technical decisions [ + ]
Apache vs Nginx
Choice: Apache 2.4.62
Rationale: .htaccess support allows URL routing changes without root access. The template system depends on per-directory rewrite rules — Apache handles this cleanly with RewriteCond and RewriteRule. Performance difference vs Nginx is negligible at this scale. Memory overhead of 50–100MB is acceptable within our 921MB budget.
Flat JSON over a Database
Choice: songs.json + poems.json as the content layer
Rationale: Eliminating a database removes the largest attack surface entirely. JSON files are readable, diffable, and version-controlled alongside the rest of the site. No query overhead, no connection pooling, no migrations. A bash script generates /api/stats.json for server telemetry — the same philosophy applied to monitoring.
Single Template per Content Type
Choice: song-template.html and poems-template.html, routed via .htaccess
Rationale: Adding a new song or poem means editing one JSON file. No HTML file is created per piece of content. Apache rewrites /songs/bad-fortune.html to /song-template.html?id=bad-fortune — the template fetches the JSON, finds the entry by key, and renders the page client-side. 301 redirects handle legacy URL paths.
sessionStorage for Status Bar Caching
Choice: Synchronous IIFE restores cached weather, KP, and CPU values before the first render
Rationale: API calls to Open-Meteo and NOAA take 200–800ms. Without caching, the status bar flickers with dashes on every page load. The IIFE runs synchronously during HTML parse, restoring last-known values from sessionStorage instantly — then async fetches update them in the background. Result: the status bar appears populated even on cold navigation.
Monospace Typography
Choice: System monospace stack — no web fonts
Rationale: No font downloads means no render-blocking requests and no third-party tracking. The constraint also fits: monospace is the natural environment for code, terminals, and technical writing. The site reads like a document rather than a product.
Real-time Telemetry Polling
Choice: 30-second client polling of 60-second server updates (CPU) · 5-minute polling for weather and KP index
Rationale: CPU temperature changes meaningfully over 30–60 seconds under varying load. Weather and geomagnetic activity move slowly — 5-minute polling is honest. More frequent calls would waste Pi cycles and NOAA bandwidth without surfacing meaningful change. The telemetry page extends this with 24-hour rolling charts stored in localStorage.
Stripe for Payments
Choice: Hosted checkout links, no Stripe SDK loaded on-site
Rationale: A Pi on a home connection should not be processing card data. Stripe's hosted checkout handles PCI compliance entirely off-server. The implementation is three URL constants and a window.open() call — no client-side library, no webhook surface, no card data ever touches Derry.
design philosophy [ + ]
visible infrastructure:
The Pi's CPU temperature appears in the header of every page. Visitors see the physical reality of the server they're reading from — warm, constrained, real.
sustainable computing:
~3W continuous vs 50–200W for a typical cloud instance. ~0.2kg CO₂/month vs ~12kg for equivalent traditional hosting. A single LED bulb uses more power than the entire server.
no dependencies:
No npm. No build step. No framework. Editing a file makes it live. The entire frontend is readable source — view-source tells you everything.
local infrastructure:
Home internet connection, no CDN, no cloud abstraction. The latency you experience is the latency of Derry.
inspiration [ + ]