Dyed in the Wool is a single-page React portfolio bundled with Vite and deployed as a static site on GitHub Pages. Every visual layer — animated backgrounds, SVG displacement filters, cursor effects, and page transitions — is composed directly inside the React component tree, with no external state management and no backend.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/apursley2012/dyed-in-the-wool/llms.txt
Use this file to discover all available pages before exploring further.
Technology Stack
| Layer | Technology |
|---|---|
| UI framework | React 18 (createRoot, StrictMode) |
| Bundler | Vite (ESM output: assets/main.js, assets/proxy.js, assets/main.css) |
| Routing | React Router v6 — HashRouter for GitHub Pages compatibility |
| Animation | Framer Motion (motion.*, AnimatePresence, layoutId) |
| Styling | Tailwind CSS with custom dye-* color tokens |
| Icons | Lucide React v0.522.0 (ArrowRight, ExternalLink, Github, Send, X) |
| Fonts | Google Fonts — Caveat Brush (display) + DM Sans (body) |
Project Structure
Component Hierarchy
The entire app renders inside a singleHashRouter. The Layout component acts as the persistent shell — it renders on every route — while child route components mount and unmount inside <Outlet /> wrapped in AnimatePresence.
DyeDropCursor is also re-used as a standalone AnimatePresence host inside the Projects page to animate the project detail modal in and out.
Data Flow
Dyed in the Wool has no API calls and no state management library. All page data is defined as static JavaScript arrays co-located inassets/main.js:
- Projects — array of
{ id, title, type, color, description, tags }objects rendered as cards and expanded into a full-screen modal via Framer MotionlayoutIdshared-layout animation. - Skills — array of
{ name, color, level }objects that power the dye-bottle skill meter on the Skills page. - Work history — array of
{ year, company, role, color, description }objects rendered in an alternating timeline on the Work page. - About copy — a plain string array of paragraphs, rendered sequentially with
whileInViewscroll-triggered animations. - Nav links — a static array
[{ path, label }]defined inLayout.jsand iterated to renderNavLinkcomponents.
useState) handles UI interactions: modal open/close state on Projects, selected skill on Skills, and contact form field values and submission status on Contact.
Explore Further
Client-Side Routing
How HashRouter, route definitions, NavLink active indicators, static HTML page stubs, and Framer Motion page transitions all fit together.
Tailwind & the Dye Color System
Custom
dye-* color tokens, SVG displacement filters, mix-blend-mode layering, the grain overlay, and the animate-blob keyframe.