The Craft uses no CMS, no database, and no external content API. Every piece of portfolio content — your bio, projects, skills, work history, blog posts, and testimonials — is co-located directly as plain JavaScript objects and arrays inside the page files underDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/apursley2012/the-craft/llms.txt
Use this file to discover all available pages before exploring further.
assets/. To update any section, open the relevant file, edit the data, and save. Vite’s hot-module replacement will reflect your changes in the browser instantly during development.
Your Name and Bio
File:assets/About.js
The About page renders your name as a static heading and populates three bio paragraphs from JSX literals. Locate the following structure and replace the placeholder values with your own:
<p> tag content with your actual bio. Replace 'Accepting new pacts & contracts' with your current availability — for example, 'Open to full-time roles' or 'Currently unavailable'.
The
'Know Thy Witch' heading is the page’s section title, not your personal name. If you want your name displayed prominently on this page, add an <h2> or edit the existing <h2> that reads 'A Brief Familiar History' to show your name instead.Projects
File:assets/Projects.js
Projects are stored in the projects array near the top of the file. Each entry renders as a pinned parchment card with a slight rotation. The array shape is:
| Title | Stack |
|---|---|
| Necromancer UI | React, Tailwind, Framer Motion |
| Alchemist E-Commerce | Next.js, Stripe, PostgreSQL |
| Scrying Glass App | React Native, WebRTC, Socket.io |
| Grimoire CMS | Vue, Node.js, MongoDB |
title, ingredients, and incantation with your own project details.
Skills
File:assets/Skills.js
Skills are stored in the skills array and rendered as interactive nodes on a pentagram SVG. Hovering a node displays the skill’s full description in the panel to the left. Each entry shape is:
| ID | Name | Subtitle | x | y |
|---|---|---|---|---|
divination | Divination | Analytics & Data | 100 | 20 |
transmutation | Transmutation | State & Refactoring | 180 | 80 |
illusion | Illusion | UI & Animations | 150 | 170 |
conjuration | Conjuration | Backend & APIs | 50 | 170 |
abjuration | Abjuration | Security & Testing | 20 | 80 |
Work History
File:assets/Work.js
Past roles are stored in the work history array. Each entry maps to a candle in the interactive candle row — clicking a candle reveals that role’s details in an animated glass panel. The entry shape is:
id values 'coven-1', 'coven-2', and 'coven-3'. The first entry is selected by default when the page loads.
The
id field must be unique across all entries — it is used as a React key and as the state selector when a candle is clicked. If you add more entries, use a consistent naming pattern such as 'coven-4', 'coven-5', etc.Blog Posts
File:assets/Blog.js
Blog entries are stored in the posts array near the top of the file. They render as overlapping parchment cards that fan out and lift on hover. The entry shape is:
| Title | Date |
|---|---|
| Binding State with Zustand | Oct 31, 2023 |
| The Necromancy of Legacy Code | Sep 15, 2023 |
| Warding Your APIs | Aug 02, 2023 |
Blog cards currently display only a title, date, and excerpt — there is no detail page or external link built in. The “Read Entry →” label is decorative. If you want cards to link to real blog posts, add a
link field to each entry and wire it up to the anchor tag inside the card’s JSX in Blog.js.Testimonials
File:assets/Testimonials.js
Testimonials are stored in the testimonials array and displayed one at a time inside an animated crystal-ball mirror. Clicking the mirror or using the dot indicators cycles through entries. The entry shape is:
id values 1, 2, and 3. Replace the quote, author, and title fields with real client or colleague endorsements.
Contact Form
File:assets/Contact.js
The contact form collects three fields — True Name (name), Ethereal Address (email), and Your Intent (message) — and currently simulates a successful submission using a setTimeout:
setTimeout block with one of the following approaches:
Formspree (no backend required)
Sign up at formspree.io, create a form, and replace the
onSubmit handler with a fetch call to your form endpoint:EmailJS (client-side only)
Use the EmailJS SDK to send email directly from the browser without a server. Install the package and call
emailjs.send() inside the handler.Navigation Labels
File:components/MoonPhaseNav.js
The navigation data array controls the tooltip label shown on hover for each route, the route path, and the moon phase icon rendered in the navigation rail. The eight-entry array is defined near the top of components/MoonPhaseNav.js and has the following logical structure:
MoonPhaseNav.js is a pre-compiled, minified bundle file — the array’s variable name in the source is an internal identifier. To locate the array, search for the string path:"/" inside the file; it appears at the very start of the route data. Edit the name and phase values for any entry directly in-place.name field freely (e.g. change 'Spellwork' to 'Projects') without affecting routing — the path field is what React Router uses for navigation. The phase value determines which lunar icon is drawn next to each entry.
Do not change the
path values here without also updating the matching <Route path="..."> entry in assets/main.js. The two must stay in sync or navigation links will break.