Personal website. danadzik.com
npm install
npm run devCopy .env.example and fill in credentials. All API keys are server-side only (Vercel serverless functions).
| Variable | Description |
|---|---|
LASTFM_API_KEY |
Last.fm API |
LASTFM_USERNAME |
Last.fm username |
STRAVA_CLIENT_ID |
Strava API |
STRAVA_CLIENT_SECRET |
Strava API secret |
STRAVA_REFRESH_TOKEN |
Initial OAuth token (stored in Redis after first use) |
UPSTASH_REDIS_REST_URL |
Upstash REST URL |
UPSTASH_REDIS_REST_TOKEN |
Upstash REST token |
| Command | Description |
|---|---|
npm run dev |
Start dev server |
npm run build |
Production build |
npm run lint |
ESLint + Stylelint |
npm run typecheck |
TypeScript check |
npm run test:unit |
Run tests |
/about, /projects, /resume, /links, /guestbook, /stats, /felixgpt
Vanilla TypeScript SPA styled as a retro desktop OS. DOM manipulation via class-based components. Vercel serverless functions for API integrations. Upstash Redis for persistence.
Draggable, resizable, focusable windows with z-index management, taskbar integration, and theme-aware chrome.
src/components/Window.ts— window lifecyclesrc/components/WindowManager.ts— focus, stacking, open/closesrc/components/Desktop.ts,src/components/DesktopIcon.ts— desktop surface and iconssrc/components/Taskbar.ts— start menu, clock, system traysrc/lib/windowContent/— HTML content generators for each windowsrc/config/routing.ts— route-to-window mapping
Shell emulator with a tree-based virtual filesystem using Windows-style paths (3:\Users\Dana\Desktop\...). Supports cd, ls, cat, tree, edit, open, whoami, etc. File ops with 4KB size limit. Executables can open windows or run handlers.
src/lib/terminal/commands.ts— command handlerssrc/lib/terminal/filesystem.ts— FS tree operationssrc/lib/terminal/filesystemBuilder.ts— initial FS structuresrc/lib/terminal/filesystemDiff.ts— diff/patch for save persistencesrc/lib/terminal/editor.ts— line-based text editor with dirty trackingsrc/components/Terminal.ts— terminal UI component
Custom esoteric programming language with Schopenhauerian influence. 8 memory slots (byte-wrapped, 0–255). Recursive descent parser, tree-walking interpreter. Compiles down to GRUND, a lower-level assembly with ring buffer and registers.
src/lib/welt/— lexer, parser, interpreter, compilersrc/lib/welt/grundInterpreter.ts— GRUND assembly interpretersrc/lib/welt/exercises.ts— programming challenges with test runner
Idle commodity trading simulator. Tick-based price simulation (trend/volatility/noise/mean reversion) with seeded RNG. 6 commodities, limit orders, corner market detection, random events, offline catchup. Phases unlock progressively: trading → factories → upgrades → market influence → org chart → structured products.
src/lib/marketGame/MarketEngine.ts— core simulation loopsrc/lib/marketGame/ChartRenderer.ts— canvas price chartssrc/lib/marketGame/commodities.ts,types.ts— data definitionssrc/lib/marketGame/factories.ts,upgrades.ts,employees.ts— progression systemssrc/components/businessPanel/— UI panels for each phase
2D pinball with custom physics engine. Circle-line/circle-circle collision detection, 4 substeps per frame. Canvas renderer. Flippers, bumpers, targets, launcher with charge mechanic. 3-ball lives, high score persistence.
src/lib/pinball/PinballGame.ts— game loopsrc/lib/pinball/physics.ts— vector math, collision resolutionsrc/lib/pinball/renderer.ts— canvas renderingsrc/lib/pinball/entities.ts— game objects
Turn-based auto-combat with shop/run loop and post-Enlightenment continental philosophy theme. 5 factions with scaling abilities. Units have triggers (combatStart, onDeath, roundStart, etc.). Buy/sell/reroll in shop phase, 30-round combat cap. Unit collection unlocked by winning against factions.
src/lib/autobattler/combat.ts— combat resolutionsrc/lib/autobattler/RunManager.ts— run loopsrc/lib/autobattler/units.ts— unit definitionssrc/lib/autobattler/CollectionManager.ts— unlocked units tracking
XP/level system with career skill tree (4 branches: Engineering, Trading, Growth, Executive). Career switching with dormancy penalty. Prestige resets for Hindsight currency. Ascension layer resets prestige for Foresight currency with permanent upgrades.
src/lib/progression/— XP, levels, career treesrc/lib/prestige/— prestige/ascension loops and upgrade definitionssrc/lib/achievements/— 150+ achievements across 13 categoriessrc/lib/cosmetics/— unlockable cursor trails, wallpapers, window chrome
Editing system files in the virtual filesystem (3:\DAS\*.welt) triggers themed crash effects: BSOD, display corruption, clock haywire, memory faults, forced restart. Glitch manager runs random visual artifacts (color splits, scanlines, screen tears) at configurable intervals. Calm mode disables all effects.
src/lib/systemCrash.ts— crash handler, file-to-effect mappingsrc/lib/systemCrash/effects/— individual crash effectssrc/lib/glitchEffects.ts— visual glitch managersrc/lib/calmMode.ts— global toggle
4 themes (Win95, Mac Classic, Apple II, C64) with light/dark/system color schemes. 8 locales (en, de, it, es, fr, pt, ja, zh) via i18next. Theme and locale glitches flash random alternatives as visual effects.
src/lib/themeManager.ts— theme/color scheme switchingsrc/lib/localeManager.ts— i18next setupsrc/locales/— translation files
- Last.fm — top 5 recent tracks with Deezer album art fallback (
src/lib/nowPlaying.ts,api/lastfm.ts) - Strava — most performant recent run by race equivalency (
src/lib/strava.ts,api/strava.ts) - Guestbook — reads from GitHub Issues API (
src/lib/guestbook.ts) - Analytics — Redis-backed event tracking, funnel analysis, A/B testing (
src/lib/siteStats.ts,api/analytics.ts) - Visitor count — Redis counter with bot detection (
src/lib/visitorCount.ts,api/visitor-count.ts)
- Session cost tracker — intercepts fetch, estimates per-session infrastructure cost (
src/lib/sessionCost.ts) - Save system — versioned JSON in localStorage, migrations, filesystem diff persistence, 256KB cap (
src/lib/saveManager.ts) - Audio — 7-track playlist, 17 SFX, autoplay attempts (
src/lib/audio.ts) - Photo slideshow — auto-rotating WebP slideshows with fade transitions (
src/lib/photoSlideshow.ts) - Popups — fake winner/error/ad popups on configurable timers (
src/lib/popupContent.ts) - Mobile — separate lock screen → home screen → app view flow (
src/components/mobile/) - Event system — typed custom events (50+ types) for cross-component communication (
src/lib/events.ts) - Router — hash/pathname routing, maps URLs to window IDs (
src/lib/router.ts)
Vercel functions in api/ with Upstash Redis (api/lib/redisGateway.ts). Response caching (1hr Last.fm, 6hr Strava, 5min analytics, 60s visitor count). Strava OAuth token refresh via Redis.
Vitest with v8 coverage. Node environment, thread pool. 600 unit tests across 25 suites covering market simulation, filesystem diff, terminal commands, Welt interpreter, pinball physics, progression balance, save migrations, etc.
vitest.config.ts— test configsrc/__tests__/— test files
17 basic functionality E2E tests via Playwright Chromium against a Vite preview server (localhost:4173).
e2e/navigation.spec.ts— desktop load, window open/close/drag, start menu, taskbar, widgetse2e/accessibility.spec.ts— lang attr, viewport meta, title, focus management, window titlese2e/analytics.spec.ts— perf event cappingplaywright.config.ts— Playwright config
Runs on PRs, pushes to main/staging, and merge queue. Single job: lint → typecheck → build → unit tests with coverage → Playwright E2E. Posts coverage summary as commit status. PR comments for both coverage (vitest-coverage-report-action) and Playwright results. Uploads both reports as artifacts (30 day retention).
Lighthouse (.github/workflows/lighthouse.yml)
Runs on PRs and pushes to main/staging. Builds and runs Lighthouse CI, posts scores (Performance, Accessibility, Best Practices, SEO) and Web Vitals (FCP, LCP, CLS, TBT, SI) as commit status, job summary, and PR comment. Updates existing PR comment on re-runs.
Nightly (.github/workflows/nightly.yml)
Cron at 2 AM UTC. Full pipeline: lint, typecheck, build, unit tests, E2E. Uploads test results with 7-day retention.
Release (.github/workflows/release.yml)
Runs on push to main. semantic-release with Conventional Commits preset. Generates changelog, bumps version in package.json, creates GitHub release. Breaking changes (!) → major, feat → minor, fix/perf/revert → patch, everything else skipped.
.releaserc.json— semantic-release config
Commit Validation (.github/workflows/validate-commit-message.yml)
Validates PR titles (squash merge message) and merge queue commits against commitlint with conventional commits. Allowed types: feat, fix, docs, style, refactor, perf, test, chore, revert, ci, build.
commitlint.config.js— commitlint config
- ESLint — typescript-eslint with strict rules: explicit return types, explicit member accessibility, consistent type imports/exports, sorted imports (simple-import-sort), no unused imports. Prettier integration. (
eslint.config.mjs) - Stylelint — stylelint-config-standard (
stylelint.config.mjs) - Prettier — via eslint-plugin-prettier
Vite with @ path alias to src/. Injects __BUILD_TIME__, __GIT_COMMIT__, __VERSION__ as compile-time constants. Deployed on Vercel.
vite.config.ts— Vite configvercel.json— Vercel config