- 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)
- COLS truncation now counts visible characters only (ignores HTML tags),
preventing broken markup when tags get cut off mid-pair
- typeSystem() types content between paired tags char-by-char while tags
appear instantly as complete open/close pairs
- Empty lines render with non-breaking space for correct row height,
fixing premature scrolling when blank lines consumed ROWS budget
- Stable line keys (monotonic counter) prevent React DOM thrashing
- terminal-parser bold regex uses negative lookahead to skip ***
Parser now supports basic Markdown syntax in all text fields:
- **bold** → <strong> with bold font weight
- __underline__ → <span> with underline decoration
- ~~strikethrough~~ → <span> with line-through
- *italic* → <em> with italic style
Implementation:
- Regex-based parser converts Markdown to HTML-like tags
- TerminalScreen component parses tags and renders as React nodes
- Styling via Tailwind classes (font-bold, underline, etc.)
- Works in all sequences: Boot, School, Joshua, UNIX commands
Examples added to terminal-script.md:
- **BIOS** in boot sequence
- __AUTHORIZED USE ONLY__ message
Build-time processing ensures no runtime overhead.
- Add preload links for all 5 audio files in layout head
- Browser downloads sounds during page load
- Eliminates delay when power button is clicked
- Improves user experience with immediate sound response
Files preloaded:
- power-on.mp3 (beep)
- hard-drive-boot.m4a
- hard-drive-spin.m4a
- hard-drive-seek1.m4a
- hard-drive-power-off.m4a
Lint Fixes:
- Fix setState in useEffect warnings by using lazy initialization and useLayoutEffect
- Remove unused parameters and variables (patterns, zoomed)
- Add eslint-disable comments for legitimate patterns (hydration, cleanup)
- Fix ref mutation warnings in cleanup functions
Code Optimizations:
- Remove dead Patterns interface and regex objects from CodePreview
- Simplify tokenizeLine to use combined regex directly
- Use lazy state initialization in ThemeProvider to avoid SSR mismatch
- Split audio preload and mount state into separate effects
- Use useLayoutEffect for synchronous DOM updates (terminalOpacity reset)
- Improve cleanup by copying ref values before use
- Add proper cancelAnimationFrame cleanup for fade animation
Result: ✓ All lint errors fixed, production build successful
- Remove 'as const' from generated terminal-data.ts
- Add type assertion for INTERACTIONS array to fix TypeScript error
- Fixes production build failure with readonly type mismatch
- Create terminal-parser.ts to parse terminal-script.md
- Add build script (generate-terminal-data.ts) to convert markdown to TypeScript
- Refactor TerminalScreen.tsx to use generated data instead of hardcoded arrays
- Add prebuild script to package.json for automatic data generation
- Install tsx and @types/howler dev dependencies
- Fix parser to preserve spacing in COUNTER prefix (Memory Test: )
- Update terminal-script.md documentation with [INLINE] tag explanation
Now terminal content can be edited in markdown without touching TypeScript:
1. Edit terminal-script.md
2. Run: npx tsx scripts/generate-terminal-data.ts
3. Reload browser - changes are live
Adds realistic CRT monitor scanline sweep effect to terminal:
**Visual Effect:**
- Sharp bottom edge (cathode ray current position)
- Trailing phosphor glow upward (150px trail)
- Gradient: transparent → 0.02 → 0.04 → 0.08 → 0.1
- Sharp edge: 0.08 opacity, no blur
- Trail: blur(3px) for smooth phosphor decay
**Animation:**
- 15s linear infinite
- Moves from top to bottom within terminal area only
- Minimal pause between cycles
- Only active when terminal is powered on
**Implementation:**
- Container (150px) with gradient + sharp 2px bottom edge
- Uses transform: translateY() for smooth animation
- CSS @keyframes crt-scanline-move
- Positioned within CRT glow layer (z-index 3)
Inspired by real CRT electron beam behavior where the
cathode ray sweeps the screen with phosphor persistence
trailing behind.
- Increased scanline height from 3px to 8px
- Set animation directly in style instead of via Tailwind class
to ensure 30s duration is applied correctly
The old 'background-position' animation was still present and
overriding the new slower 'translateY' version. Now only the
30s animation remains active.
- Removed AudioContext setup and management
- Removed playCrtPowerOnSound() function (95 lines)
- Removed audio unlock listeners
- Cleaned up handlePowerOn comment
Audio caused issues with browser autoplay policies and added
unnecessary complexity. Terminal animation works fine without it.
- Make playCrtPowerOnSound() async with proper AudioContext.resume()
- Add AudioContext unlock on first user interaction (click/touchstart)
- Add error handling for audio failures
- Ensures sound works in all browsers with autoplay restrictions
- Remove SN Pro Google Font import from globals.css
- Add Nunito font import with weights 400, 500, 600, 700
- Update CSS variables to use --font-nunito
- Apply Nunito as primary font family for body text
- Keep Geist Mono for monospace elements
- Add robots.txt and sitemap.xml (static files for export mode)
- Add OG image (1200x630) with terminal icon + branding
- Add Twitter Card meta tags (summary_large_image)
- Add canonical URL via metadataBase
- Add JSON-LD structured data (SoftwareSourceCode schema)
- Add <main> landmark and skip-navigation link for accessibility
- Add preconnect hints for Google Fonts, Google Static, and Umami
- Add web app manifest (site.webmanifest)
- Add meta keywords for secondary search engines
- Add aria-hidden on decorative SF Symbol icons
- Powered-off terminal shows no text (realistic CRT behavior)
- Add permanent glass sheen with diagonal specular highlight in theme color
- Glass overlay covers full screen area with vignette effect
- Add BluePalette (VFD-style, #00AAFF base) and VioletPalette (HSL-generated from hue 270°)
- Remove GeneratedPalette entirely (replaced by dedicated VioletPalette)
- Reorder palette cycling: Green → Amber → Red → Violet → Blue → White → NCurses
- Sync all landing page CSS theme colors with exact Swift palette values
- Add blue theme to landing page with matching VFD colors
- Fix theme switcher FOUC: useEffect syncs React state after hydrate
- Update default theme to Green (was Amber)
- Update landing page logo to latest DocC version
- Next.js static site in docs/ with SN Pro font and WarText headline
- 4 phosphor themes (Green, Amber, White, Red) with localStorage persistence
- Animated cloud background tinted to active theme
- SF Symbols icons via sf-symbols-lib/hierarchical
- PackageBadge with copy-to-clipboard, version from CI tag
- CI workflow builds landing page + DocC, deploys to GitHub Pages
- Version auto-resolved from git tags on deploy