37 Commits

Author SHA1 Message Date
TehRiehlDeal d6b148239d Merge pull request 'Refactor/cohesion pass' (#1) from refactor/cohesion-pass into main
Reviewed-on: #1
2026-06-03 11:17:48 -07:00
TehRiehlDeal df78dc694f feat: make portfolio content crawlable + add SEO structured data
The entire portfolio rendered only on the PixiJS canvas, so crawlers saw a
near-empty body and the site ranked poorly for non-personalized searches. Fixes:

- NEW SeoContent.svelte: screen-reader/crawler-only (.sr-only) semantic HTML
  (h1 + bio + contact + Experience/Projects/Skills/Education), generated from
  data.ts (single source of truth, reuses aggregateSkills). Prerenders into
  build/index.html — verified it now contains the job/project/education text
  that was previously canvas-only. Also a big screen-reader accessibility win.
- JSON-LD schema.org Person in +layout (name, jobTitle, alumniOf, knowsAbout,
  sameAs LinkedIn/GitHub) — strong entity signal for name searches.
- Canonical URL; static/sitemap.xml + robots.txt Sitemap reference.
- Keyword-tuned <title>, description, og/twitter titles (name + role + stack).
- Demoted the transient welcome <h1> to a <div> so SeoContent's <h1> is the
  single canonical heading. Bumped SW cache to v2.

.sr-only utility added to app.css. check/lint/test/build clean; verified no
visual regression and no runtime exceptions (background + canvas unchanged).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 11:16:17 -07:00
TehRiehlDeal 6f17cba9c5 chore: add scripts/generate-og-image.sh to regenerate the OG card
Reproducible ImageMagick script that rebuilds static/og-preview.jpg from the
headshot + theme colours (with serif-font fallbacks so it runs on other
machines). Exposed as `npm run og:image`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 10:57:36 -07:00
TehRiehlDeal 6ff99e0d51 feat: add Open Graph / Twitter preview image for link unfurls
Link previews need an og:image — the tags existed but the image was
commented out. Generated a 1200x630 branded card (static/og-preview.jpg,
~100KB: dark space gradient, circular headshot with gold ring, gold serif
title + tagline) and wired up:
- og:image (+ secure_url, type, width, height, alt)
- twitter:image (+ alt); twitter:card already summary_large_image

Absolute URLs point at https://tehriehldeal.com/og-preview.jpg so crawlers
(Slack/Discord/iMessage/Twitter/Facebook) can fetch it. Tags verified present
in the prerendered build/index.html.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 10:44:07 -07:00
TehRiehlDeal 84112d8e42 refactor: extract PixiJS rendering into pixi/ modules
Phase 5 (behavior-preserving): decompose the ~1000-line onMount into focused
modules coordinated by a plain (non-reactive) controller object:
- pixi/types.ts        LineObject / NodeObject / BackgroundLayers
- pixi/controller.ts   shared mutable pan/zoom state + Pixi refs (NOT $state,
                       which would break PixiJS object identity)
- pixi/background.ts   gradient/nebula/stars/dust/vignette + ambient loops
- pixi/lines.ts        plasma-beam connections
- pixi/nodes.ts        origin + regular nodes; collapses the duplicated pointer
                       handlers into one attachNodeInteraction helper
- pixi/interaction.ts  pan/zoom/parallax + keyboard nav (return cleanups)
- pixi/animation.ts    sequenced entrance animation

onMount is now a thin orchestrator. SkillTree.svelte: 1177 -> 274 lines
(2453 at the start of the refactor). Listener passivity, the hasMoved click
guard, eventMode-until-animated ordering, and the R-reset parallax rebaseline
are all preserved.

svelte-check: 0 errors/0 warnings. lint/test/build clean. Verified onMount runs
with no runtime exceptions (background + stats panel render). NOTE: pan/zoom/
node-click/keyboard need a manual real-browser check (headless can't paint nodes).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 10:23:54 -07:00
TehRiehlDeal f08138718a refactor: extract leaf UI components from SkillTree.svelte
Phase 4 (behavior-preserving): split the monolithic component's DOM overlays
into focused children, each owning its markup + scoped CSS:
- LoadingIndicator.svelte, WelcomeTitle.svelte, Tooltip.svelte
- NodeModal.svelte (modal + ~280 lines CSS; onClose callback, category-narrowed)
- StatsPanel.svelte (toggle + backdrop + panel + ~340 lines CSS; onToggle/
  onToggleBranch callbacks). Kept the .stats-panel-toggle class name stable so
  the entrance-animation GSAP querySelector still resolves.

SkillTree.svelte drops from 2453 -> ~600 lines. Modernized the moved event
handlers (on:click -> onclick), clearing the 9 Svelte deprecation warnings.

svelte-check: 0 errors, 0 warnings. lint/test/build clean. Verified the stats
panel renders identically in-browser (LVL/mastery/branches all correct).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 10:10:17 -07:00
TehRiehlDeal bf235680a4 refactor: model TreeNode as a discriminated union
Phase 3 (behavior-preserving):
- Replace the 45-optional-field TreeNode interface with a tagged union over
  category: OriginNode | ExperienceNode | ProjectNode | SkillNode | EducationNode,
  sharing a BaseNode. Category-specific fields now live only on their member.
- Modal template narrows by category (category === 'experience' && ...) instead
  of bare field-presence checks; equivalent at runtime since each field is
  exclusive to its category (proven by the union compiling against the data).
- stats utils narrow correctly: aggregateSkills filters to SkillNode[] via a type
  predicate; countByProficiency and getPlayerClass guard on category.

svelte-check: 0 errors (every data node conforms). lint/test/build clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 09:59:25 -07:00
TehRiehlDeal 6091c62654 refactor: drive theme colors through CSS custom properties
Phase 2 (behavior-preserving):
- Add :root color tokens to app.css mirroring theme.ts cssVars
- Replace solid theme hex literals in SkillTree.svelte <style> with var(--..):
  #ffd700 -> --color-gold (x17), #a8a8b8 -> --text-muted (x8),
  #1a1a2e -> --panel-from, #0f0f1a -> --panel-to, #f9a825 -> --color-skills
- body background now var(--bg-space)

Values are identical to the literals; every referenced var has a :root
definition. rgba() shadows and one-off grays/badge colors left as-is.
check/lint/build all clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 09:54:29 -07:00
TehRiehlDeal 6c652e7138 refactor: centralize theme/config/utils + fix data and console bugs
Phase 1 of the cohesion refactor (behavior-preserving):

Single source of truth:
- New src/lib/theme.ts: category colors (moved from data.ts, re-exported
  for back-compat), derived hex strings, nebula palette, UI colors, CSS var map
- New src/lib/config.ts: breakpoint, zoom, parallax, node radii, particle
  counts, animation timings (previously scattered magic numbers)
- New src/lib/utils/tree.ts: getNodeById, getNodeRadius, getDistanceFromOrigin,
  getBeamIntensity (pure helpers lifted out of onMount)
- New src/lib/utils/stats.ts: branch ids/labels, proficiency order, and the
  stats-panel aggregation helpers (deduped from inline copies)
- SkillTree.svelte now imports all of the above; removed the duplicated
  getCategoryColorHex, stats helpers, branch id/label lists, and inline magic numbers
- Populated src/lib/index.ts barrel

Bug fixes:
- data.ts: tmdbAPI pypiUrl pointed at tvdbAPI -> corrected to tmdbAPI
- Removed/ gated stray console.log noise (skill-tree-loaded, SW logs)
- Removed dead vars (maxAlpha, glowMaxAlpha) and unused catch binding

Tooling: ESLint + Prettier now clean; added Vitest unit tests for the new
pure utils (14 tests). svelte-check: 0 errors. build: ok.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 09:40:27 -07:00
TehRiehlDeal aa58425f1a style: apply Prettier formatting across codebase
Isolated reformat commit so subsequent logic changes have clean diffs.
No behavior change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 09:29:52 -07:00
TehRiehlDeal a85bd16218 chore: add ESLint, Prettier, and Vitest tooling
Add code-quality tooling the project lacked:
- ESLint (flat config via @sveltejs/eslint-config)
- Prettier (tabs, single quotes, matching existing style)
- Vitest (node env, for pure-logic unit tests)
- npm scripts: lint, format, format:check, test, test:watch

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 09:29:28 -07:00
TehRiehlDeal 5e2cd60895 feat: add MovieLoop and TehRiehlBudget projects with new Games branch
Add a Games parent node branching off the top of the Projects node, with
MovieLoop (daily movie-chain web game built with React/NestJS) as its
first child. Add TehRiehlBudget (self-hosted personal finance app) as a
fourth child under Personal Tools, and stagger the Personal Tools
children coordinates so they no longer stack on a perfect vertical line.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 15:37:29 -07:00
TehRiehlDeal d68a9d3ca1 Added new node for new personal project 2026-01-21 00:22:41 -08:00
TehRiehlDeal 5ffd531f3c Added Keyboard navigation, added parallax effect to the background, changed zoom to center on Origin node, increased accessibility, optimized lighthouse score 2026-01-15 22:38:37 -08:00
TehRiehlDeal 540504f088 Added new personal project to the tree 2026-01-15 22:37:00 -08:00
TehRiehlDeal 8ba85d65e6 Updated gitignore 2026-01-15 22:36:47 -08:00
TehRiehlDeal 130e426cd2 Resized image for better performance 2026-01-15 22:36:40 -08:00
TehRiehlDeal 341972ba2e Added PWA support 2026-01-15 22:36:26 -08:00
TehRiehlDeal eb961b752c Added node connection beam animations 2026-01-12 23:35:14 -08:00
TehRiehlDeal 13a57b39a0 Added Character Sheet style stats panel 2026-01-12 22:51:49 -08:00
TehRiehlDeal 3b66249745 Fixed grammar error in aboutMe 2026-01-12 22:51:25 -08:00
TehRiehlDeal 62b6bc5e00 Updated gitignore 2026-01-12 22:51:11 -08:00
TehRiehlDeal aa0464e12b Added welcome animation 2026-01-11 23:39:53 -08:00
TehRiehlDeal fb2df94db1 Added handling of disaplaying pypi link and maintain status of my projects 2026-01-11 18:17:53 -08:00
TehRiehlDeal fff85687f6 Added title 2026-01-11 18:17:08 -08:00
TehRiehlDeal 15f9aaf03a Added all missing svgs 2026-01-11 14:31:29 -08:00
TehRiehlDeal 791de48bd6 Added my resume 2026-01-11 14:31:21 -08:00
TehRiehlDeal b82aa75ff1 Added link to download my resume 2026-01-11 14:31:12 -08:00
TehRiehlDeal feb1c4effc Updated Job layout to show it was all done within the same contract. Added entries for personal projects 2026-01-11 14:30:48 -08:00
TehRiehlDeal cbd5a1e42c Fixed custom favicon import 2026-01-11 12:18:03 -08:00
TehRiehlDeal 9f47ac5233 Added in missing svgs 2026-01-11 12:08:18 -08:00
TehRiehlDeal 92f00c75a4 Updated skill node layout, added more icons 2026-01-11 12:08:07 -08:00
TehRiehlDeal c279112778 Updated background to look a bit nicer, switched hero image, updated mobile responiveness 2026-01-11 12:07:44 -08:00
TehRiehlDeal 1275a1c5a9 Added custom favicon 2026-01-11 12:05:50 -08:00
TehRiehlDeal 7f0f86d14e feat(skill-tree): add touch support and improve modal handling 2026-01-10 11:04:35 -08:00
TehRiehlDeal f091bf6d55 refactor(tree): update node layout and iconography 2026-01-10 11:03:26 -08:00
TehRiehlDeal 3ad6b6edec Inital commit 2026-01-10 01:55:41 -08:00