Website
Personal website technical documentation. Actively maintained reference for ejfox.com architecture, features, and implementation details.
Last updated: 2025-11-16
Overview
Personal website and digital publishing system built with Nuxt 3. Primary purpose: publishing blog posts, predictions, and stats from multiple APIs. Content originates in Obsidian, gets processed to structured JSON, then served via Vue components.
Deployed via Docker containers with health checks. Production URL: https://ejfox.com
Architecture
Technology Stack
- Nuxt 3 (Vue 3, TypeScript)
- Docker containerized deployment
- Node.js server-side rendering
- Tailwind CSS with custom 8px baseline grid
- Georgia serif typography, 80-character line length enforcement
Content Pipeline
Content flows through a multi-stage processing system:
- Markdown files written in Obsidian vault
scripts/processMarkdown.mjsconverts MD to structured JSON- Individual JSON files stored in
content/processed/ manifest-lite.jsongenerated for listings- Vue components consume processed JSON, not raw Markdown
Processing includes: YAML frontmatter parsing, remark/rehype plugins, TOC extraction, tag counting, image optimization (Cloudinary srcset generation), code syntax highlighting.
Main Pages
Blog
Primary content type. Posts stored in content/blog/YYYY/ with drafts in content/blog/drafts/. Each post has YAML frontmatter with tags, date, dek, and optional metadata.
Sidenotes system implemented via 113-line client-side plugin that transforms standard Markdown footnotes into margin notes (Tufte CSS approach). Footnotes appear in right margin on desktop (>1280px), collapse to standard footnotes on mobile.
Projects
Showcases code and art experiments, data visualization work, digital tools. Two tiers: featured work and archive. Uses Swiss grid system (12-column on desktop). Project descriptions rendered from processed Markdown with full image support. TOC sidebar for navigation.
Technical detail: Images previously had forced 16:9 aspect ratio causing cropping. Fixed to respect natural aspect ratios while maintaining grid containment.
Predictions
Two subsystems:
Cryptographic Predictions - CLI tool (yarn predict) creates SHA-256 hashed predictions with optional PGP signing. Git commits provide timestamp proof. Storage: content/predictions/ as Markdown with verification data.
Kalshi Integration - Real-money prediction market positions tracked via live API. Features:
- Multi-layer smart caching (portfolio: 2min, events: 1hr, commentary: 10min)
- Commentary system in
content/kalshi/*.mdfor position analysis - Calibration tracking with Brier scores and calibration curves
- Portfolio P&L tracking (open/closed positions)
- Type-safe API consumer with full schema definitions in
server/types/kalshi.ts
Scripts: kalshi:test, kalshi:templates, kalshi:calibration
Gear
CSV-based gear inventory system with weight calculations. Features:
- Dynamic unit conversion (metric/imperial)
- Tuftian data visualizations (weight distributions, histograms)
- Ultra-dense data tables on 8px baseline grid
- Container-based organization with inline statistics
Data source: data/gear.csv with Weight_oz column. No TCWM scoring (removed in delete-driven cleanup).
Stats
Multi-source API aggregation dashboard. Integrates: GitHub, YouTube, LastFM, Chess.com, RescueTime, MonkeyType, photo counts. Caching layer prevents rate limit issues. Endpoint: server/api/stats.get.ts
Real-time personal metrics with sparkline visualizations.
Design System
Typography
- Primary: Georgia serif (system font, no custom loading)
- Monospace: System monospace stack
- 8px baseline grid enforced throughout
- 80-character line length limit (ESLint enforced)
- Journalist pyramid ordering for tags (special tags first, then by usage frequency)
Layout
- Editorial left-aligned content within max-w-screen-xl container (1280px)
- Swiss grid: 12-column system on desktop, single column mobile
- No horizontal centering via mx-auto for main content (left-aligned)
- Spacing: 2-4-8 rhythm (multiples of 8px)
Image Handling
Classes: .img-full, .img-large, .img-medium, .img-small
All images auto-optimized via Cloudinary: srcset generation, f_auto, q_auto, multiple width variants (400w, 800w, 1200w). Lazy loading and async decoding enabled. Aspect ratios preserved (no forced cropping).
Development Philosophy
Delete-Driven Development
Primary methodology: "When system hangs, delete code until it works. No clever fixes, no complex solutions. Find the bloat, delete it. Simple beats complex. Working beats perfect."
Examples of deletions:
- 15MB+ lighthouse reports and build logs from root
- Looping animations causing flicker
- Complex TCWM scoring from gear page
- 800+ line sidenotes system replaced with 113-line client plugin
- Custom fonts replaced with system Georgia
Code Quality
- TypeScript strict mode enabled
- ESLint with 80-char line enforcement
- Zero unused variable warnings (all prefixed with underscore or removed)
- Modern empty catch syntax for unused error parameters
Deployment
Docker-based with docker-compose. Health check endpoint: /api/healthcheck
Build artifacts stored in .nuxt and .output. Environment variables in .env (not committed).
Restart procedure: docker-compose restart for .env changes, full rebuild: docker-compose down && docker-compose up -d --build
Notable Technical Details
- Tags endpoint (
server/routes/tags.json.ts) serves dynamic JSON with usage-frequency ordering - Git-based content versioning (all posts committed to main branch)
- No mermaid diagrams (64MB bloat, deleted)
- Prose styles:
.proseclass with zinc color scheme, custom paragraph spacing - Image-in-paragraph fix:
.prose p imgexceptions for size classes - Client-side rendering for heavy components (sparklines, visualizations)
Maintenance Scripts
yarn blog:process- Process Markdown to JSONyarn predict- Create cryptographic predictionyarn kalshi:test- Fetch Kalshi portfolioyarn kalshi:templates- Generate commentary templatesyarn kalshi:calibration- Run accuracy analysisyarn build- Production buildyarn dev- Development server (port 3006)
Document History
This page serves as the authoritative technical reference for ejfox.com. Update when architecture changes, features are added/removed, or implementation details evolve. Maintain factual accuracy. Preserve historical context in deletions.