Brand/content phase. The engineering was never the weak part of this site;
the copy was. Decisions on title, bio angle, download figures and node copy
were the owner's — this implements them.
Identity:
- jobTitle was 'Software Development - Lead Associate', an internal HR grade
that means nothing to a recruiter or a search engine. Now 'Lead Software
Engineer' — a faithful translation, not a promotion.
- aboutMe opened with "Intermediate Software Engineer", grading himself down
in his own headline, and named the most generic possible stack
(React/Node/SQL/ShadCN/Docker). It now leads with the work almost nobody
else has done: WebRTC telehealth, real-time gesture recognition that made
chat usable for speech-impaired patients, and air-gapped deployment
tooling. Those were previously buried 3-4 clicks deep in leaf nodes and
appeared nowhere on the surface.
- Title/description/OG/Twitter copy realigned to match. JSON-LD needed no
change — it already derives from the origin node.
Node copy:
- The five job nodes had placeholder descriptions ('Junior developer at the
start of my career.', 'Where I am now.') that are the first thing a tooltip
shows. Each is now a one-line hook naming the most substantial thing from
that role.
- Normalised highlight punctuation: only exp-job5's bullets ended in periods.
Proof of work:
- `downloads` existed on ProjectNode and was used by zero nodes despite two
published PyPI packages. Populated with verified lifetime figures from
pypistats.org (tvdbAPI 2,277, tmdbAPI 784, checked 2026-08-09) and dated in
a comment. Lifetime, deliberately, not the recent rate — 27 and 12 in the
last month is not a number worth advertising.
- Nothing rendered the field. NodeModal now shows it beside the status badge,
and SeoContent renders it too so it's crawlable.
Data integrity:
- edu-degree's description said "Computer Science" while its own structured
fields said Applied Science / IT-Software Development. Its label was the
generic "University"; now Green River College.
- calculatePlayerLevel() hardcoded '2020-10-01', duplicating
exp-job1.startDate — two sources for one fact, free to drift. It now
derives the earliest start from the experience nodes, via an explicit
"Month YYYY" parser rather than handing a bare "October 2020" to
`new Date` (not a format engines are required to accept).
- Added the first tests for calculatePlayerLevel, previously the only
untested export in stats.ts. 14 -> 16 tests.
- Fixed the 'tool-vscod' id typo.
Corrections to the audit this phase acted on: the self-hosted repos at
git.tehriehldeal.com ARE publicly reachable (all three return 200
anonymously) — the earlier claim that recruiters couldn't reach them was
asserted without checking. All three live project sites are up too.
Verified in the production build: modal shows the new title and bio, the
downloads badge renders as "↓ 2,277 downloads", figures are crawlable in the
prerendered HTML, and no filler copy survives.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
957 lines
27 KiB
TypeScript
957 lines
27 KiB
TypeScript
// Fields shared by every node, regardless of category.
|
|
interface BaseNode {
|
|
id: string;
|
|
label: string;
|
|
description: string;
|
|
x: number;
|
|
y: number;
|
|
parentId: string | null; // null means it's the root or connects to center
|
|
size: 'x-large' | 'large' | 'medium' | 'small';
|
|
icon?: string;
|
|
}
|
|
|
|
// Center node with profile/contact info.
|
|
export interface OriginNode extends BaseNode {
|
|
category: 'origin';
|
|
fullName?: string;
|
|
jobTitle?: string;
|
|
aboutMe?: string;
|
|
location?: string;
|
|
email?: string;
|
|
linkedIn?: string;
|
|
github?: string;
|
|
website?: string;
|
|
resumeUrl?: string;
|
|
}
|
|
|
|
// Jobs and contract roles.
|
|
export interface ExperienceNode extends BaseNode {
|
|
category: 'experience';
|
|
company?: string;
|
|
jobTitle?: string;
|
|
startDate?: string;
|
|
endDate?: string; // Use "Present" for current role
|
|
highlights?: string[]; // Key achievements or responsibilities
|
|
contractName?: string;
|
|
client?: string;
|
|
contractStart?: string;
|
|
contractEnd?: string;
|
|
}
|
|
|
|
// Personal projects / packages.
|
|
export interface ProjectNode extends BaseNode {
|
|
category: 'projects';
|
|
techStack?: string[];
|
|
projectUrl?: string;
|
|
repoUrl?: string;
|
|
npmUrl?: string; // For npm packages
|
|
pypiUrl?: string; // For PyPI packages
|
|
downloads?: string; // "1,000+ downloads"
|
|
stars?: number; // GitHub stars
|
|
status?: 'active' | 'maintained' | 'archived' | 'completed';
|
|
}
|
|
|
|
// Technical skills with proficiency.
|
|
export interface SkillNode extends BaseNode {
|
|
category: 'skills';
|
|
proficiency?: 'beginner' | 'intermediate' | 'advanced' | 'expert';
|
|
yearsOfExperience?: number;
|
|
}
|
|
|
|
// Academic background.
|
|
export interface EducationNode extends BaseNode {
|
|
category: 'education';
|
|
institution?: string;
|
|
degree?: string;
|
|
field?: string;
|
|
graduationYear?: string;
|
|
}
|
|
|
|
// Discriminated union over `category` — narrow on it to access category fields.
|
|
export type TreeNode = OriginNode | ExperienceNode | ProjectNode | SkillNode | EducationNode;
|
|
|
|
// The center of our tree is at (0, 0)
|
|
// Positive X = right, Negative X = left
|
|
// Positive Y = down, Negative Y = up
|
|
|
|
export const treeNodes: TreeNode[] = [
|
|
// ========== ORIGIN (Center) ==========
|
|
{
|
|
id: 'origin',
|
|
label: 'Kevin Riehl',
|
|
description:
|
|
'Welcome to my skill tree! Click on nodes to explore my experience, projects, and skills.',
|
|
x: 0,
|
|
y: 0,
|
|
parentId: null,
|
|
category: 'origin',
|
|
size: 'x-large',
|
|
icon: '',
|
|
fullName: 'Kevin Riehl',
|
|
jobTitle: 'Lead Software Engineer',
|
|
aboutMe:
|
|
"Software engineer with 5+ years building full-stack applications for Defense Health Agency programs. I've architected a WebRTC telehealth platform, shipped real-time gesture recognition that made chat usable for speech-impaired patients, and built the deployment tooling that unblocked a team after an air-gapped infrastructure migration. React, Node.js, NestJS, TypeScript, SQL.",
|
|
location: 'Kent, WA',
|
|
email: 'kevinriehl@gmail.com',
|
|
linkedIn: 'https://www.linkedin.com/in/kevinriehl',
|
|
github: 'https://github.com/TehRiehlDeal',
|
|
website: 'https://tehriehldeal.com',
|
|
resumeUrl: '/kevin-riehl-resume.pdf'
|
|
},
|
|
|
|
// ========== EXPERIENCE (Upper Right - Contract-Based) ==========
|
|
{
|
|
id: 'exp-branch',
|
|
label: 'Experience',
|
|
description: 'My professional journey.',
|
|
x: 200,
|
|
y: -150,
|
|
parentId: 'origin',
|
|
category: 'experience',
|
|
size: 'large',
|
|
icon: '/icons/experience.svg'
|
|
},
|
|
|
|
// Contract Parent Node
|
|
{
|
|
id: 'exp-contract',
|
|
label: 'DHA - Web and Mobile Technology',
|
|
description:
|
|
'Continuous work supporting the same government client through multiple contracting companies as the contract was re-competed and awarded.',
|
|
x: 320,
|
|
y: -220,
|
|
parentId: 'exp-branch',
|
|
category: 'experience',
|
|
size: 'medium',
|
|
icon: '/icons/contract.svg',
|
|
contractName: 'DHA WMT',
|
|
client: 'Defense Health Agency',
|
|
contractStart: 'October 2020',
|
|
contractEnd: 'Present'
|
|
},
|
|
|
|
// Job 1 - First company (starting point of the arc)
|
|
{
|
|
id: 'exp-job1',
|
|
label: 'Software Engineer',
|
|
description: 'Refactored legacy PHP endpoints onto Hapi.js and ran a MySQL to MSSQL migration.',
|
|
x: 420,
|
|
y: -280,
|
|
parentId: 'exp-contract',
|
|
category: 'experience',
|
|
size: 'small',
|
|
icon: '/icons/insightglobal.webp',
|
|
company: 'Insight Global',
|
|
jobTitle: 'Software Engineer',
|
|
startDate: 'October 2020',
|
|
endDate: 'April 2021',
|
|
highlights: [
|
|
'Refactored legacy PHP endpoints into a robust Hapi.js architecture, aligning the project with modern JavaScript standards and improving API response times',
|
|
'Executed a critical database migration from MySQL to MSSQL, ensuring data integrity during the transfer and optimizing schema definitions for the new environment'
|
|
]
|
|
},
|
|
|
|
// Job 2 - Arc continues upward
|
|
{
|
|
id: 'exp-job2',
|
|
label: 'Software Engineer',
|
|
description: 'Built a React + Hapi.js analytics search engine over complex event datasets.',
|
|
x: 500,
|
|
y: -350,
|
|
parentId: 'exp-job1',
|
|
category: 'experience',
|
|
size: 'small',
|
|
icon: '/icons/bluewater.png',
|
|
company: 'Bluewater Federal Solutions',
|
|
jobTitle: 'Software Engineer',
|
|
startDate: 'April 2021',
|
|
endDate: 'February 2024',
|
|
highlights: [
|
|
'Architected and built a comprehensive data analytics search engine using React and Hapi.js (TypeScript), enabling users to filter complex event datasets by location, type, and date for real-time analysis',
|
|
'Facilitated successful production releases by managing SQL database migration scripts and executing rigorous regression testing to ensure critical features remained stable during updates',
|
|
'Supported engineering team growth by conducting code reviews and leading the onboarding process for new developers, ensuring smooth knowledge transfer and adherence to coding standards'
|
|
]
|
|
},
|
|
|
|
// Job 3 - Peak of the arc
|
|
{
|
|
id: 'exp-job3',
|
|
label: 'Intermediate Software Engineer',
|
|
description: 'Web Bluetooth biometric monitoring, plus a team-wide move to ShadCN and Docker.',
|
|
x: 560,
|
|
y: -430,
|
|
parentId: 'exp-job2',
|
|
category: 'experience',
|
|
size: 'small',
|
|
icon: '/icons/sempervalens.png',
|
|
company: 'Semper Valens Solutions',
|
|
jobTitle: 'Intermediate Software Engineer',
|
|
startDate: 'February 2024',
|
|
endDate: 'June 2025',
|
|
highlights: [
|
|
"Championed the adoption of ShadCN by conducting a live technical demonstration on the team's starter template, proving the framework's ability to accelerate development velocity and ensure UI consistency across projects",
|
|
'Developed a Web Bluetooth interface for a biometric monitoring proof-of-concept, enabling real-time data ingestion and aggregation from multiple wearable sensors (accelerometers and smartwatches) for sleep analysis',
|
|
"Supported the engineering team's migration to containerized workflows by configuring, testing, and troubleshooting custom Docker environments, ensuring consistent application behavior across development and production"
|
|
]
|
|
},
|
|
|
|
// Job 4 - Continuing upward and right
|
|
{
|
|
id: 'exp-job4',
|
|
label: 'Intermediate Software Engineer',
|
|
description:
|
|
'WebRTC telehealth platform and real-time gesture recognition for speech-impaired users.',
|
|
x: 600,
|
|
y: -510,
|
|
parentId: 'exp-job3',
|
|
category: 'experience',
|
|
size: 'small',
|
|
icon: '/icons/chenega.jpg',
|
|
company: 'Chenega',
|
|
jobTitle: 'Intermediate Software Engineer',
|
|
startDate: 'June 2025',
|
|
endDate: 'January 2026',
|
|
highlights: [
|
|
'Architected a secure telehealth video conferencing application using React and WebRTC, designing the core signaling class to manage complex peer-to-peer connections (SDP offers/answers) and media stream constraints',
|
|
'Implemented Google MediaPipe to develop a real-time gesture recognition feature, enabling accessibility for speech-impaired users by translating hand signs (e.g., thumbs up) into animated in-chat reactions',
|
|
'Engineered adaptive network logic that monitors packet loss in real-time and dynamically adjusts video stream quality, ensuring connection stability and optimal user experience during bandwidth fluctuations'
|
|
]
|
|
},
|
|
|
|
// Job 5 - Current (highest point, prominent)
|
|
{
|
|
id: 'exp-job5',
|
|
label: 'Lead Associate',
|
|
description:
|
|
'Air-gapped deployment automation, a NestJS audit interceptor, and 90%+ test coverage.',
|
|
x: 620,
|
|
y: -590,
|
|
parentId: 'exp-job4',
|
|
category: 'experience',
|
|
size: 'medium',
|
|
icon: '/icons/peraton.png',
|
|
company: 'Peraton',
|
|
jobTitle: 'Lead Associate',
|
|
startDate: 'January 2026',
|
|
endDate: 'Present',
|
|
highlights: [
|
|
'Proactively engineered a suite of automation tools to streamline code deployment workflows to an air-gapped Git instance following a critical infrastructure migration, eliminating manual bottlenecks and restoring team development velocity',
|
|
'Designed and implemented a custom NestJS API interceptor to dynamically detect and audit specific user activities, providing robust, real-time daily activity tracking for compliance and analytics',
|
|
'Spearheaded a rigorous testing initiative to elevate code quality, systematically architecting and executing unit tests to scale platform test coverage from a legacy deficit to a resilient 90%+ baseline'
|
|
]
|
|
},
|
|
|
|
// ========== PROJECTS (Upper Left Quadrant) ==========
|
|
{
|
|
id: 'proj-branch',
|
|
label: 'Projects',
|
|
description: 'Personal projects and open-source contributions.',
|
|
x: -200,
|
|
y: -150,
|
|
parentId: 'origin',
|
|
category: 'projects',
|
|
size: 'large',
|
|
icon: '/icons/projects.svg'
|
|
},
|
|
|
|
// Open Source Libraries
|
|
{
|
|
id: 'proj-opensource',
|
|
label: 'Open Source',
|
|
description: 'Published packages and libraries available for the community.',
|
|
x: -350,
|
|
y: -220,
|
|
parentId: 'proj-branch',
|
|
category: 'projects',
|
|
size: 'medium',
|
|
icon: '/icons/opensource.svg'
|
|
},
|
|
|
|
// Personal Tools
|
|
{
|
|
id: 'proj-tools',
|
|
label: 'Personal Tools',
|
|
description: 'Applications built to solve real problems.',
|
|
x: -350,
|
|
y: -80,
|
|
parentId: 'proj-branch',
|
|
category: 'projects',
|
|
size: 'medium',
|
|
icon: '/icons/tools.svg'
|
|
},
|
|
|
|
// Games
|
|
{
|
|
id: 'proj-games',
|
|
label: 'Games',
|
|
description: 'Interactive games and playful experiments.',
|
|
x: -200,
|
|
y: -310,
|
|
parentId: 'proj-branch',
|
|
category: 'projects',
|
|
size: 'medium',
|
|
icon: '/icons/games.svg'
|
|
},
|
|
|
|
// ========== OPEN SOURCE CHILDREN ==========
|
|
{
|
|
id: 'proj-tvdbapi',
|
|
label: 'tvdbAPI',
|
|
description:
|
|
'Python library for accessing The TVDB API. Fetch show info, episodes, actors, and images with a simple interface. Published on PyPI.',
|
|
x: -420,
|
|
y: -310,
|
|
parentId: 'proj-opensource',
|
|
category: 'projects',
|
|
size: 'small',
|
|
icon: '/icons/python.svg',
|
|
techStack: ['Python', 'REST API', 'PyPI', 'GitHub Actions', 'Unit Testing'],
|
|
repoUrl: 'https://github.com/TehRiehlDeal/TVDB-API',
|
|
pypiUrl: 'https://pypi.org/project/tvdbAPI/',
|
|
// Lifetime PyPI downloads, checked 2026-08-09 (pypistats.org).
|
|
downloads: '2,277 downloads',
|
|
status: 'maintained'
|
|
},
|
|
{
|
|
id: 'proj-tmdbapi',
|
|
label: 'tmdbAPI',
|
|
description:
|
|
'Python library for The Movie Database API. Search for movies, TV shows, actors, and collections with comprehensive query options.',
|
|
x: -500,
|
|
y: -250,
|
|
parentId: 'proj-opensource',
|
|
category: 'projects',
|
|
size: 'small',
|
|
icon: '/icons/python.svg',
|
|
techStack: ['Python', 'REST API', 'PyPI', 'GitHub Actions', 'Unit Testing'],
|
|
repoUrl: 'https://github.com/TehRiehlDeal/tmdbAPI',
|
|
pypiUrl: 'https://pypi.org/project/tmdbAPI/',
|
|
// Lifetime PyPI downloads, checked 2026-08-09 (pypistats.org).
|
|
downloads: '784 downloads',
|
|
status: 'maintained'
|
|
},
|
|
{
|
|
id: 'proj-image-resize',
|
|
label: 'Image Resize Tool',
|
|
description:
|
|
'GUI-based batch image processor with intelligent whitespace trimming and automated resizing workflows. Features folder-based processing for brand-specific transformations and maintains aspect ratios.',
|
|
x: -460,
|
|
y: -180,
|
|
parentId: 'proj-opensource',
|
|
category: 'projects',
|
|
size: 'small',
|
|
icon: '/icons/python.svg',
|
|
techStack: ['Python', 'PIL/Pillow', 'Tkinter', 'Image Processing'],
|
|
repoUrl: 'https://github.com/TehRiehlDeal/python-image-resize',
|
|
status: 'completed'
|
|
},
|
|
|
|
// ========== PERSONAL TOOLS CHILDREN ==========
|
|
{
|
|
id: 'proj-renameshow',
|
|
label: 'Rename Show',
|
|
description:
|
|
'Desktop application for batch renaming TV show files using metadata from TVDB and TMDB. Features undo support, multi-episode detection, and automatic show searching.',
|
|
x: -475,
|
|
y: -135,
|
|
parentId: 'proj-tools',
|
|
category: 'projects',
|
|
size: 'small',
|
|
icon: '/icons/desktop.svg',
|
|
techStack: ['Python', 'Tkinter', 'tvdbAPI', 'tmdbAPI', 'PIL'],
|
|
repoUrl: 'https://github.com/TehRiehlDeal/python-file-rename'
|
|
},
|
|
{
|
|
id: 'proj-portfolio',
|
|
label: 'Skill Tree Portfolio',
|
|
description:
|
|
"This interactive portfolio you're exploring right now! A Path of Exile inspired skill tree built with modern web technologies.",
|
|
x: -480,
|
|
y: -60,
|
|
parentId: 'proj-tools',
|
|
category: 'projects',
|
|
size: 'small',
|
|
icon: '/icons/svelte.svg',
|
|
techStack: ['SvelteKit', 'TypeScript', 'PixiJS', 'GSAP', 'Vitest'],
|
|
projectUrl: 'https://tehriehldeal.com',
|
|
repoUrl: 'https://git.tehriehldeal.com/TehRiehlDeal/skill-tree-portfolio'
|
|
},
|
|
{
|
|
id: 'proj-character-builder',
|
|
label: 'Pathfinder 2E Character Builder',
|
|
description:
|
|
'Web-based character creation tool for Pathfinder 2E tabletop RPG. Features modern component-based architecture with comprehensive testing and code quality tooling.',
|
|
x: -490,
|
|
y: 15,
|
|
parentId: 'proj-tools',
|
|
category: 'projects',
|
|
size: 'small',
|
|
icon: '/icons/svelte.svg',
|
|
techStack: ['Svelte', 'TypeScript', 'Vite', 'Vitest', 'Playwright', 'ESLint'],
|
|
repoUrl: 'https://github.com/TehRiehlDeal/teh-riehl-character-builder',
|
|
status: 'active'
|
|
},
|
|
{
|
|
id: 'proj-budget',
|
|
label: 'TehRiehlBudget',
|
|
description:
|
|
'Self-hosted personal finance app tracking spending, balances, and net worth across checking, savings, credit, loans, and investments. Features field-level AES-256-GCM encryption, receipt uploads, audit logging, CSV export, and a local Ollama-powered AI advisor.',
|
|
x: -440,
|
|
y: 75,
|
|
parentId: 'proj-tools',
|
|
category: 'projects',
|
|
size: 'small',
|
|
icon: '/icons/react.svg',
|
|
techStack: [
|
|
'React',
|
|
'TypeScript',
|
|
'NestJS',
|
|
'Prisma',
|
|
'PostgreSQL',
|
|
'TailwindCSS',
|
|
'ShadCN',
|
|
'Zustand',
|
|
'Supabase',
|
|
'Ollama'
|
|
],
|
|
projectUrl: 'https://budget.tehriehldeal.com/',
|
|
repoUrl: 'https://git.tehriehldeal.com/TehRiehlDeal/TehRiehlBudget',
|
|
status: 'active'
|
|
},
|
|
{
|
|
id: 'proj-tcg',
|
|
label: 'TCG Management',
|
|
description:
|
|
'Self-hosted trading card game collection and inventory manager built to handle any TCG, with per-game catalogs and daily market prices sourced from TCGCSV. Features a camera scanner that auto-detects cards on-device using OpenCV and perceptual-hash matching, plus wishlists, trade binders, transaction history, and price-trend analytics. Runs entirely on a homelab in Docker with self-hosted CI/CD.',
|
|
x: -400,
|
|
y: 140,
|
|
parentId: 'proj-tools',
|
|
category: 'projects',
|
|
size: 'medium',
|
|
icon: '/icons/tcg.svg',
|
|
techStack: [
|
|
'React',
|
|
'TypeScript',
|
|
'NestJS',
|
|
'Prisma',
|
|
'PostgreSQL',
|
|
'Redis/BullMQ',
|
|
'OpenCV.js',
|
|
'Redux Toolkit',
|
|
'TailwindCSS',
|
|
'ShadCN',
|
|
'PWA',
|
|
'Docker'
|
|
],
|
|
projectUrl: 'https://tcg.tehriehldeal.com',
|
|
repoUrl: 'https://git.tehriehldeal.com/TehRiehlDeal/tehriehltcgmanagement',
|
|
status: 'active'
|
|
},
|
|
|
|
// ========== GAMES CHILDREN ==========
|
|
{
|
|
id: 'proj-movieloop',
|
|
label: 'MovieLoop',
|
|
description:
|
|
'Daily challenge game where players chain movies through shared actors — a "six degrees of Kevin Bacon" reimagined for the web. Features leaderboards, daily and freeplay modes, undo support, and PWA install with push notifications.',
|
|
x: -260,
|
|
y: -390,
|
|
parentId: 'proj-games',
|
|
category: 'projects',
|
|
size: 'small',
|
|
icon: '/icons/react.svg',
|
|
techStack: ['React', 'TypeScript', 'Vite', 'NestJS', 'Prisma', 'PWA', 'Web Push', 'Docker'],
|
|
projectUrl: 'https://movieloop.tehriehldeal.com/',
|
|
repoUrl: 'https://git.tehriehldeal.com/TehRiehlDeal/movieloop-frontend',
|
|
status: 'active'
|
|
},
|
|
|
|
// ========== SKILLS (Bottom Right Quadrant) ==========
|
|
{
|
|
id: 'skills-branch',
|
|
label: 'Skills',
|
|
description: 'Technologies and abilities I have acquired.',
|
|
x: 150,
|
|
y: 100,
|
|
parentId: 'origin',
|
|
category: 'skills',
|
|
size: 'large',
|
|
icon: '/icons/skills.svg'
|
|
},
|
|
|
|
// Concepts - upper right
|
|
{
|
|
id: 'concepts',
|
|
label: 'Concepts',
|
|
description: 'Core concepts I have learned throughout my career.',
|
|
x: 350,
|
|
y: -50,
|
|
parentId: 'skills-branch',
|
|
category: 'skills',
|
|
size: 'medium',
|
|
icon: '/icons/concepts.svg'
|
|
},
|
|
|
|
// Tools & DevOps - moved up slightly
|
|
{
|
|
id: 'tools-devops',
|
|
label: 'Tools & DevOps',
|
|
description: 'The tools I use to get work done!',
|
|
x: 450,
|
|
y: 100,
|
|
parentId: 'skills-branch',
|
|
category: 'skills',
|
|
size: 'medium',
|
|
icon: '/icons/devops.svg'
|
|
},
|
|
|
|
// Frontend - lower right
|
|
{
|
|
id: 'frontend',
|
|
label: 'Frontend',
|
|
description: 'The Frontend tools and frameworks I know!',
|
|
x: 350,
|
|
y: 350,
|
|
parentId: 'skills-branch',
|
|
category: 'skills',
|
|
size: 'medium',
|
|
icon: '/icons/frontend.svg'
|
|
},
|
|
|
|
// Backend & Real-Time - pulled closer to Skills
|
|
{
|
|
id: 'backend-real-time',
|
|
label: 'Backend & Real-Time',
|
|
description: 'The Backend frameworks and concepts I know!',
|
|
x: 150,
|
|
y: 280,
|
|
parentId: 'skills-branch',
|
|
category: 'skills',
|
|
size: 'medium',
|
|
icon: '/icons/backend.svg'
|
|
},
|
|
|
|
// Languages - left side
|
|
{
|
|
id: 'languages',
|
|
label: 'Languages',
|
|
description: 'The many languages I know!',
|
|
x: -100,
|
|
y: 280,
|
|
parentId: 'skills-branch',
|
|
category: 'skills',
|
|
size: 'medium',
|
|
icon: '/icons/languages.svg'
|
|
},
|
|
|
|
// ========== CONCEPTS CHILDREN (4) ==========
|
|
{
|
|
id: 'concept-oop',
|
|
label: 'Object Oriented Programming',
|
|
description:
|
|
'Object-Oriented Programming principles including encapsulation, inheritance, and polymorphism.',
|
|
x: 380,
|
|
y: -120,
|
|
parentId: 'concepts',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/oop.svg',
|
|
proficiency: 'expert'
|
|
},
|
|
{
|
|
id: 'concept-data-structure',
|
|
label: 'Data Structures & Algorithms',
|
|
description:
|
|
'Fundamental building blocks of efficient software—organizing data and solving problems with optimal time and space complexity.',
|
|
x: 430,
|
|
y: -75,
|
|
parentId: 'concepts',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/datastructure.svg',
|
|
proficiency: 'advanced'
|
|
},
|
|
{
|
|
id: 'concept-tdd',
|
|
label: 'Test Driven Development',
|
|
description: 'Unit testing, integration testing, and test-driven development practices.',
|
|
x: 435,
|
|
y: -20,
|
|
parentId: 'concepts',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/test.svg',
|
|
proficiency: 'intermediate'
|
|
},
|
|
{
|
|
id: 'concept-agile',
|
|
label: 'Agile',
|
|
description: 'Agile methodologies including Scrum and Kanban for iterative development.',
|
|
x: 395,
|
|
y: 30,
|
|
parentId: 'concepts',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/agile.svg',
|
|
proficiency: 'advanced'
|
|
},
|
|
|
|
// ========== TOOLS & DEVOPS CHILDREN (5) ==========
|
|
{
|
|
id: 'tool-git',
|
|
label: 'Git',
|
|
description: 'Version control with Git, branching strategies, and collaborative workflows.',
|
|
x: 530,
|
|
y: 40,
|
|
parentId: 'tools-devops',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/git.svg',
|
|
proficiency: 'expert'
|
|
},
|
|
{
|
|
id: 'tool-docker',
|
|
label: 'Docker',
|
|
description:
|
|
'Containerization with Docker for consistent development and deployment environments.',
|
|
x: 560,
|
|
y: 95,
|
|
parentId: 'tools-devops',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/docker.svg',
|
|
proficiency: 'advanced'
|
|
},
|
|
{
|
|
id: 'tool-cicd',
|
|
label: 'CI/CD',
|
|
description: 'Continuous integration and deployment pipelines with GitHub Actions and Jenkins.',
|
|
x: 555,
|
|
y: 150,
|
|
parentId: 'tools-devops',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/cicd.svg',
|
|
proficiency: 'intermediate'
|
|
},
|
|
{
|
|
id: 'tool-vscode',
|
|
label: 'VSCode',
|
|
description:
|
|
'Powerful, lightweight code editor by Microsoft with built-in Git support, debugging, and a vast extension ecosystem.',
|
|
x: 520,
|
|
y: 205,
|
|
parentId: 'tools-devops',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/vscode-plain.svg',
|
|
proficiency: 'advanced'
|
|
},
|
|
{
|
|
id: 'tool-linux',
|
|
label: 'Linux',
|
|
description: 'Linux system administration, shell scripting, and server management.',
|
|
x: 470,
|
|
y: 245,
|
|
parentId: 'tools-devops',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/linux.svg',
|
|
proficiency: 'advanced'
|
|
},
|
|
|
|
// ========== FRONTEND CHILDREN (6) ==========
|
|
{
|
|
id: 'fe-react',
|
|
label: 'React',
|
|
description: 'Building user interfaces with React, hooks, and state management.',
|
|
x: 420,
|
|
y: 295,
|
|
parentId: 'frontend',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/react.svg',
|
|
proficiency: 'advanced'
|
|
},
|
|
{
|
|
id: 'fe-redux',
|
|
label: 'Redux',
|
|
description:
|
|
'Predictable state management library for JavaScript applications, centralizing app state in a single store.',
|
|
x: 450,
|
|
y: 350,
|
|
parentId: 'frontend',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/redux.svg',
|
|
proficiency: 'intermediate'
|
|
},
|
|
{
|
|
id: 'fe-zustand',
|
|
label: 'Zustand',
|
|
description:
|
|
'Lightweight state management for React using a simple hooks-based API with minimal boilerplate.',
|
|
x: 440,
|
|
y: 405,
|
|
parentId: 'frontend',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/zustand-plain.svg',
|
|
proficiency: 'intermediate'
|
|
},
|
|
{
|
|
id: 'fe-tailwind',
|
|
label: 'Tailwind CSS',
|
|
description: 'Utility-first CSS framework for rapid UI development.',
|
|
x: 400,
|
|
y: 460,
|
|
parentId: 'frontend',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/tailwindcss.svg',
|
|
proficiency: 'advanced'
|
|
},
|
|
{
|
|
id: 'fe-shadcn',
|
|
label: 'ShadCN/UI',
|
|
description:
|
|
'Beautifully designed, accessible UI components that you copy and paste into your project. Built on Radix UI and Tailwind CSS.',
|
|
x: 340,
|
|
y: 500,
|
|
parentId: 'frontend',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/shadcnui.svg',
|
|
proficiency: 'advanced'
|
|
},
|
|
{
|
|
id: 'fe-pwa',
|
|
label: 'PWA',
|
|
description:
|
|
'Progressive Web Apps—web applications that deliver native app-like experiences with offline support, push notifications, and home screen installation.',
|
|
x: 270,
|
|
y: 520,
|
|
parentId: 'frontend',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/pwa.svg',
|
|
proficiency: 'intermediate'
|
|
},
|
|
|
|
// ========== BACKEND & REAL-TIME CHILDREN (6) ==========
|
|
{
|
|
id: 'be-nodejs',
|
|
label: 'Node.js',
|
|
description: 'Server-side JavaScript runtime for building scalable applications.',
|
|
x: 220,
|
|
y: 330,
|
|
parentId: 'backend-real-time',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/nodedotjs.svg',
|
|
proficiency: 'advanced'
|
|
},
|
|
{
|
|
id: 'be-hapi',
|
|
label: 'Hapi.js',
|
|
description:
|
|
'Enterprise-grade Node.js framework for building scalable APIs and services with built-in validation, authentication, and caching.',
|
|
x: 175,
|
|
y: 370,
|
|
parentId: 'backend-real-time',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/hapi.svg',
|
|
proficiency: 'advanced'
|
|
},
|
|
{
|
|
id: 'be-nestjs',
|
|
label: 'NestJS',
|
|
description:
|
|
'Progressive Node.js framework for building efficient, scalable server-side applications with TypeScript and Angular-inspired architecture.',
|
|
x: 115,
|
|
y: 390,
|
|
parentId: 'backend-real-time',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/nestjs.svg',
|
|
proficiency: 'intermediate'
|
|
},
|
|
{
|
|
id: 'be-webrtc',
|
|
label: 'WebRTC',
|
|
description:
|
|
'Real-time communication protocol enabling peer-to-peer audio, video, and data streaming directly in the browser without plugins.',
|
|
x: 50,
|
|
y: 385,
|
|
parentId: 'backend-real-time',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/webrtc.svg',
|
|
proficiency: 'intermediate'
|
|
},
|
|
{
|
|
id: 'be-socketio',
|
|
label: 'Socket.io',
|
|
description:
|
|
'Real-time bidirectional event-based communication library for Node.js and browsers with automatic fallback support.',
|
|
x: 0,
|
|
y: 355,
|
|
parentId: 'backend-real-time',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/socketdotio.svg',
|
|
proficiency: 'advanced'
|
|
},
|
|
{
|
|
id: 'be-restfulapi',
|
|
label: 'RESTful APIs',
|
|
description:
|
|
'Architectural style for designing networked applications using stateless HTTP methods to perform CRUD operations on resources.',
|
|
x: -25,
|
|
y: 310,
|
|
parentId: 'backend-real-time',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/openapi.svg',
|
|
proficiency: 'advanced'
|
|
},
|
|
|
|
// ========== LANGUAGES CHILDREN (7) ==========
|
|
{
|
|
id: 'lang-javascript',
|
|
label: 'JavaScript',
|
|
description: 'The language of the web. ES6+ features and beyond.',
|
|
x: -135,
|
|
y: 205,
|
|
parentId: 'languages',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/javascript.svg',
|
|
proficiency: 'expert',
|
|
yearsOfExperience: 5
|
|
},
|
|
{
|
|
id: 'lang-typescript',
|
|
label: 'TypeScript',
|
|
description: 'Type-safe JavaScript for scalable applications.',
|
|
x: -175,
|
|
y: 250,
|
|
parentId: 'languages',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/typescript.svg',
|
|
proficiency: 'expert',
|
|
yearsOfExperience: 5
|
|
},
|
|
{
|
|
id: 'lang-python',
|
|
label: 'Python',
|
|
description: 'Versatile language for scripting, data science, and backend.',
|
|
x: -195,
|
|
y: 300,
|
|
parentId: 'languages',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/python.svg',
|
|
proficiency: 'intermediate',
|
|
yearsOfExperience: 2
|
|
},
|
|
{
|
|
id: 'lang-rust',
|
|
label: 'Rust',
|
|
description:
|
|
'Systems programming language focused on safety, speed, and concurrency—guaranteeing memory safety without a garbage collector.',
|
|
x: -190,
|
|
y: 355,
|
|
parentId: 'languages',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/rust.svg',
|
|
proficiency: 'beginner',
|
|
yearsOfExperience: 1
|
|
},
|
|
{
|
|
id: 'lang-php',
|
|
label: 'PHP',
|
|
description:
|
|
'Server-side scripting language powering much of the web—from WordPress to Laravel, built for dynamic web content.',
|
|
x: -165,
|
|
y: 405,
|
|
parentId: 'languages',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/php.svg',
|
|
proficiency: 'intermediate',
|
|
yearsOfExperience: 2
|
|
},
|
|
{
|
|
id: 'lang-sql',
|
|
label: 'SQL',
|
|
description: 'Structured Query Language for database management.',
|
|
x: -125,
|
|
y: 450,
|
|
parentId: 'languages',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/mysql.svg',
|
|
proficiency: 'intermediate',
|
|
yearsOfExperience: 2
|
|
},
|
|
{
|
|
id: 'lang-bash',
|
|
label: 'Bash',
|
|
description: 'Shell scripting for automation and system tasks.',
|
|
x: -75,
|
|
y: 485,
|
|
parentId: 'languages',
|
|
category: 'skills',
|
|
size: 'small',
|
|
icon: '/icons/gnubash.svg',
|
|
proficiency: 'intermediate',
|
|
yearsOfExperience: 2
|
|
},
|
|
|
|
// ========== EDUCATION (Bottom Left Quadrant) ==========
|
|
{
|
|
id: 'edu-branch',
|
|
label: 'Education',
|
|
description: 'Where I learned the fundamentals.',
|
|
x: -150,
|
|
y: 100,
|
|
parentId: 'origin',
|
|
category: 'education',
|
|
size: 'large',
|
|
icon: '/icons/education.svg'
|
|
},
|
|
{
|
|
id: 'edu-degree',
|
|
label: 'Green River College',
|
|
description: "Bachelor's of Applied Science in IT and Software Development.",
|
|
x: -300,
|
|
y: 80,
|
|
parentId: 'edu-branch',
|
|
category: 'education',
|
|
size: 'small',
|
|
institution: 'Green River College',
|
|
degree: "Bachelor's Degree of Applied Science",
|
|
field: 'IT/Software Development',
|
|
graduationYear: '2017',
|
|
icon: '/icons/greenriver.png'
|
|
}
|
|
// {
|
|
// id: 'edu-cert',
|
|
// label: 'Certifications',
|
|
// description: 'Additional certifications and courses completed.',
|
|
// x: -280,
|
|
// y: 180,
|
|
// parentId: 'edu-branch',
|
|
// category: 'education',
|
|
// size: 'small',
|
|
// },
|
|
];
|
|
|
|
// Category colours now live in `$lib/theme` (single source of truth).
|
|
// Re-exported here for back-compat with existing `$lib/data` imports.
|
|
export { categoryColors } from './theme';
|