- CommitList: Hide SHA on mobile, smaller text, icon-only expand button
- Footer: Center cache status on mobile, hide rate limit
- Heatmap: Hidden on mobile (< 640px) - not useful on small screens
- SiteNav: Add hamburger menu for mobile, hide desktop links on small screens
- StatCard: Stack vertically on mobile (icon+label top, number bottom)
- Icon: Add line3Horizontal and xmark custom icons for hamburger menu
Adds isRefreshing state separate from loading. During auto-refresh,
existing data remains visible (no skeleton flash). Only the spinner
icon shows refresh activity. Removes manual refresh button.
Uses Framer Motion for enter/exit/reorder animations. New commits
slide in from the top, existing commits smoothly animate to their
new positions. Adds ~40KB to the bundle.
Prevents redundant GitHub API calls on page reload. Data is cached in
localStorage with a 5-minute TTL and auto-refreshed in the background.
Force-refresh button with 60s cooldown. Footer shows last-updated time
and countdown to next refresh.
Add fetchGitHubSocialAccounts() using /users/{login}/social_accounts API
as primary source. Validate Mastodon domains via NodeInfo instead of
blocklists. Add 5s timeouts to all fetch calls. Expand known instances
list. Skip cross-verification for authoritative sources (github, keybase).
Full refresh now clears cache to prevent stale false positives.
- Add IconBadge component with sm/md/lg variants
- Refactor FeatureCard to use IconBadge
- Update ArchHighlight and RepoInfo for consistency
- Add DASHBOARD_GITHUB_TOKEN to CI for rate limit
- HeroTerminal: all timers now flow through scheduleTimer/pendingTimersRef,
eliminating seekTimeoutRef/zoomTimerRef/powerOffTimerRef entirely;
poweringOnRef guards against rapid double-click race condition
- TerminalScreen: trim lineRefsRef to ROWS in pushLine to prevent
unbounded stale DOM ref accumulation
- Remove ~1.1MB unused audio duplicates (mp3 copies of m4a files,
unreferenced seek2 in both formats)
- Remove unused favicon-16.png
Performance & memory:
- HeroTerminal: fix setInterval one-time random (now recursive setTimeout),
reuse single Howl for seeks, track all timers via pendingTimersRef
- RainOverlay: cap at 30fps, skip on prefers-reduced-motion
- SpinnerLights: pre-compute boxShadow at spawn, nextId in useRef
- Remove eager audio preloads from <head> (Howler loads lazily)
- CloudBackground: remove unnecessary 'use client' (now Server Component)
Type safety & correctness:
- Import BootStep/SchoolStep/JoshuaStep/TerminalEntry from terminal-parser
instead of duplicating interfaces; typed terminal-data.ts export
- ThemeProvider: isTheme() type guard replaces unsafe 'as Theme' casts,
instanceof guard for event.target, try/catch on localStorage.setItem
- useCopyToClipboard: cancel previous timer on rapid clicks, try/catch
around clipboard API, cleanup on unmount
- TerminalScreen: use config.initialCursorDelay instead of magic 18000,
type predicate for filter(), track glitch reset timer for cleanup
Accessibility (WCAG):
- prefers-reduced-motion: global CSS rule + JS skip in Rain/Spinner/Glitch
- aria-hidden on decorative elements (Rain, Spinner, Clouds)
- focus-visible ring on ThemeSwitcher, CodePreview, PackageBadge buttons
- aria-pressed on active theme button, nav aria-label, main tabIndex
Code quality:
- Extract useCopyToClipboard hook (CodePreview + PackageBadge)
- bg-frosted-glass CSS utility replaces 3x inline color-mix
- hover:bg-white/* → hover:bg-foreground/* for theme consistency
- Remove dead zoomed prop, stale eslint-disable, move lineRefsRef up
- import type for ReactNode in FeatureCard
- Add SF Symbol icons to nav links (book for Docs, </> for GitHub)
- Fix theme button onClick broken by hydration mismatch: start with
null on both server and client, sync via useEffect after mount
- Active theme dot pulses with 3s ease-in-out glow animation
- Stronger glow on active theme indicator (triple-layer box-shadow)