Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/apursley2012/y2k-webring/llms.txt

Use this file to discover all available pages before exploring further.

portfolioData.js is the only file you need to touch to update your portfolio content. Every page in Y2K Webring — your home profile, the projects grid, the skills matrix, writing posts, case studies, and the guestbook — reads its data directly from this one file. Edit a value, save, and the Vite dev server hot-reloads the change across every page instantly.

Complete Schema Reference

The file has six named exports. In the compiled output they are minified to single letters; the readable names are used below.

devInfo — Your Profile (S)

The top-level object that drives your Home page bio, status widget, stats panel, and social links.
const devInfo = {
  devName: string,        // Display name shown as the hero heading (e.g. "ALEX.EXE")
  tagline: string,        // Short one-liner shown beneath the name on Home
  bio: string,            // Multi-sentence biography for the About/profile section
  status: {
    building: string,     // What you're currently building
    reading: string,      // What you're currently reading
    debugging: string     // What you're currently debugging
  },
  guestbookCount: number, // Total guestbook entry count (manual — update when you add entries)
  stats: {
    location: string,     // Where you're based (e.g. "The Pacific Northwest (probably raining)")
    pronouns: string,     // Your pronouns (e.g. "they/them")
    obsessedWith: string, // Comma-separated interests for the stats panel
    previously: string,   // Prior careers or roles
    peeves: string        // Pet peeves — shown in the stats panel
  },
  socials: [
    {
      name: string,                                      // Display label (e.g. "GitHub")
      url: string,                                       // Full URL or "#" as placeholder
      icon: 'github' | 'linkedin' | 'mail' | 'rss'      // Lucide icon key
    }
  ]
}
Example (from the default data):
const devInfo = {
  devName: "ALEX.EXE",
  tagline: "No actual spells, just suspiciously organized files.",
  bio: "Full-stack developer weaving code into the digital ether. Previously a nursing student, now debugging reality.",
  status: {
    building: "A haunted React component",
    reading: "Documentation from 2014",
    debugging: "Reality (and CSS grids)"
  },
  guestbookCount: 1337,
  stats: {
    location: "The Pacific Northwest (probably raining)",
    pronouns: "they/them",
    obsessedWith: "mechanical keyboards, obscure CSS properties, cold brew",
    previously: "nursing student / healthcare / retail / merchandiser",
    peeves: "off-center buttons, fake enthusiasm, inconsistent branding"
  },
  socials: [
    { name: "GitHub",   url: "#", icon: "github"   },
    { name: "LinkedIn", url: "#", icon: "linkedin" },
    { name: "Email",    url: "#", icon: "mail"     },
    { name: "RSS",      url: "#", icon: "rss"      }
  ]
}

projects — Projects Grid (P)

An array of project cards rendered on the Projects page. Each entry maps to one card in the grid.
const projects = [
  {
    id: string,                                          // Unique slug (e.g. "proj-1")
    name: string,                                        // Project display name
    stack: string[],                                     // Technology tags (e.g. ["React", "TypeScript"])
    status: '✦ shipped' | '✦ in-progress' | '✦ haunted', // Project lifecycle status
    description: string,                                 // One or two sentence summary
    dataSource: 'live' | 'mocked' | 'sample',           // Indicates data fidelity of the demo
    demoUrl: string,                                     // Live demo link or "#"
    sourceUrl: string,                                   // Source code / repo link or "#"
    readmeUrl: string                                    // README / docs link or "#"
  }
]
Built-in status values and their meaning:
StatusMeaning
✦ shippedLive and complete
✦ in-progressActively being built
✦ hauntedLegacy project kept alive out of necessity
Example entries (from the default data):
const projects = [
  {
    id: "proj-1",
    name: "Grimoire.js",
    stack: ["React", "TypeScript", "WebGL"],
    status: "✦ shipped",
    description: "A digital spellbook for managing code snippets with a 3D particle interface.",
    dataSource: "live",
    demoUrl: "#",
    sourceUrl: "#",
    readmeUrl: "#"
  },
  {
    id: "proj-2",
    name: "Neon_Bazaar",
    stack: ["Next.js", "Stripe", "Tailwind"],
    status: "✦ in-progress",
    description: "An e-commerce platform for digital artifacts. Currently integrating the payment gateway.",
    dataSource: "mocked",
    demoUrl: "#",
    sourceUrl: "#",
    readmeUrl: "#"
  },
  {
    id: "proj-3",
    name: "Legacy_System_04",
    stack: ["PHP", "jQuery", "MySQL"],
    status: "✦ haunted",
    description: "An old client project that refuses to die. I maintain it out of fear.",
    dataSource: "sample",
    demoUrl: "#",
    sourceUrl: "#",
    readmeUrl: "#"
  }
]

skills — Skills Matrix (a)

A plain object whose keys are category names and whose values are arrays of skill entries. The Skills page iterates over this object to render each category section.
const skills = {
  'Category Name': [
    {
      name: string,              // Skill or tool name (e.g. "TypeScript")
      level: 1 | 2 | 3 | 4 | 5, // Proficiency — 1 = beginner, 5 = expert
      note: string               // Short annotation shown alongside the skill bar
    }
  ]
}
Built-in categories (preserve these keys or update the Skills page component if you rename them):
  • Languages
  • Frontend
  • Backend & Data
  • Tooling
  • Design Sensibilities
Example entries (from the default data):
const skills = {
  Languages: [
    { name: "TypeScript", level: 5, note: "5 years of strict typing" },
    { name: "JavaScript", level: 5, note: "The chaotic neutral core" },
    { name: "Python",     level: 4, note: "For scripting and data spells" },
    { name: "HTML/CSS",   level: 5, note: "The ancient texts" },
    { name: "SQL",        level: 3, note: "SELECT * FROM abyss" }
  ],
  Frontend: [
    { name: "React",         level: 5, note: "Component alchemy" },
    { name: "Tailwind",      level: 5, note: "Utility-first witchcraft" },
    { name: "Framer Motion", level: 4, note: "Making things move" },
    { name: "Vue",           level: 3, note: "A pleasant alternative" }
  ],
  "Backend & Data": [
    { name: "Node.js",    level: 4, note: "Server-side incantations" },
    { name: "PostgreSQL", level: 4, note: "Relational storage" },
    { name: "Redis",      level: 3, note: "Fast memory caching" },
    { name: "GraphQL",    level: 3, note: "Precise data fetching" }
  ],
  Tooling: [
    { name: "Git",     level: 5, note: "Time travel" },
    { name: "Docker",  level: 3, note: "Containerized chaos" },
    { name: "Webpack", level: 4, note: "Bundling the mess" },
    { name: "Vite",    level: 4, note: "Lightning fast builds" }
  ],
  "Design Sensibilities": [
    { name: "Y2K Aesthetic", level: 5, note: "Chunky borders & neon" },
    { name: "Accessibility", level: 4, note: "Web for everyone" },
    { name: "Typography",    level: 4, note: "Font pairings" }
  ]
}

writingPosts — Blog Posts (W)

An array of blog post objects rendered on the Writing page. The content field is the full post body as a plain string.
const writingPosts = [
  {
    id: string,      // Unique slug (e.g. "post-1")
    title: string,   // Post title
    date: string,    // Publication date in ISO 8601 format: 'YYYY-MM-DD'
    excerpt: string, // One or two sentence summary shown on the post listing
    tags: string[],  // Array of tag labels (e.g. ["Design", "Reflection"])
    content: string  // Full post body as a plain string (rendered with .drop-cap styling)
  }
]
Example entries (from the default data):
const writingPosts = [
  {
    id: "post-1",
    title: "Why I Still Use Chunky Borders in 2026",
    date: "2026-05-13",
    excerpt: "A defense of the 2px solid border and why flat design went too far.",
    tags: ["Design", "Reflection"],
    content: "The modern web is a sea of subtle shadows and 1px borders..."
  },
  {
    id: "post-2",
    title: "Debugging the Haunted State Hook",
    date: "2026-04-01",
    excerpt: "That time a React component retained state across page reloads for no logical reason.",
    tags: ["Bug Report", "Technical"],
    content: "It started on a Tuesday. The user profile component was showing..."
  },
  {
    id: "post-3",
    title: "From Nursing to Node.js",
    date: "2025-11-20",
    excerpt: "How triaging patients prepared me for triaging production bugs.",
    tags: ["Reflection", "For-General-Audience"],
    content: "People often ask how I made the jump from healthcare to software development..."
  }
]

caseStudies — Case Studies (C)

An array of in-depth project case studies. Each field maps to a distinct section of the case study layout, including an RPG-style “bugs encountered” list.
const caseStudies = [
  {
    id: string,            // Unique slug (e.g. "cs-1")
    title: string,         // Case study title
    setup: string,         // Client or project context — the "before" state
    problem: string,       // The core problem that needed solving
    investigation: string, // Research or discovery process
    designChoices: string, // Design decisions made and why
    buildChoices: string,  // Technical/implementation decisions made and why
    bugs: [
      {
        name: string,      // Bug name (displayed as an enemy in the RPG panel)
        hp: number         // Bug "hit points" — a playful difficulty indicator
      }
    ],
    result: string,        // Outcome and measurable impact
    nextTime: string       // Retrospective: what you'd do differently
  }
]
Example entry (from the default data):
const caseStudies = [
  {
    id: "cs-1",
    title: "Neon_Bazaar: Reimagining E-commerce",
    setup: "A boutique digital art collective needed a storefront that didn't look like Shopify.",
    problem: "Standard e-commerce platforms enforce a grid-and-white-background aesthetic that clashed with the collective's cyberpunk/Y2K brand.",
    investigation: "I analyzed 15 different 'alternative' storefronts and found they all suffered from poor accessibility and confusing UX, despite looking cool.",
    designChoices: "We opted for a 'directory' style layout inspired by old BBS systems, but implemented with modern ARIA standards and responsive CSS grid.",
    buildChoices: "Next.js for SSR SEO benefits, Stripe for payments, and Framer Motion for the glitch-hover effects.",
    bugs: [
      { name: "Stripe Webhook Duplication",          hp: 45 },
      { name: "Framer Motion Memory Leak on Mobile", hp: 80 }
    ],
    result: "A 40% increase in conversion rate compared to their old platform, and a site that actually feels like their brand.",
    nextTime: "I would use a lighter animation library for the micro-interactions to save bundle size."
  }
]

guestbook — Guestbook Entries (G)

An array of guestbook messages displayed on the Guestbook page. Each entry has a Tailwind color class to tint the visitor’s name.
const guestbook = [
  {
    id: number,      // Numeric entry ID (increment for each new entry)
    name: string,    // Visitor's display name
    date: string,    // Entry date in ISO 8601 format: 'YYYY-MM-DD'
    text: string,    // The guestbook message body
    color: string    // Tailwind text color class applied to the name (e.g. 'text-y2k-lime')
  }
]
Available color values: 'text-y2k-lime', 'text-y2k-cyan', 'text-y2k-magenta' Example entries (from the default data):
const guestbook = [
  {
    id: 1,
    name: "Recruiter_Sarah",
    date: "2026-05-20",
    text: "Love the aesthetic! Your React skills are exactly what we need at [REDACTED] Corp. Let's connect?",
    color: "text-y2k-lime"
  },
  {
    id: 2,
    name: "Dev_Dave",
    date: "2026-05-18",
    text: "The chunky borders give me life. Also, stole your custom scrollbar CSS. Thanks!",
    color: "text-y2k-cyan"
  },
  {
    id: 3,
    name: "Design_Witch",
    date: "2026-05-10",
    text: "Finally, someone who understands that readability and personality aren't mutually exclusive.",
    color: "text-y2k-magenta"
  }
]
Remember to increment devInfo.guestbookCount when you add new entries so the counter on the Home page stays accurate.

Quick Edit Guide

1

Open portfolioData.js

Navigate to data/portfolioData.js in your project root and open it in your editor.
2

Find the section you want to update

The file is organized in the same order as the schema above: devInfo first, then projects, skills, writingPosts, caseStudies, and guestbook. Use your editor’s search (Ctrl+F / Cmd+F) or scroll to the relevant block.
3

Edit the values

Update the string, number, or array values directly. Keep the key names and structural shape intact — the components read specific property names.
4

Save the file

Save the file. The Vite dev server detects the change via HMR (Hot Module Replacement) and reloads the affected pages automatically — no manual browser refresh needed.
Keep demoUrl, sourceUrl, and readmeUrl set to either a valid absolute URL (e.g. "https://github.com/you/project") or the placeholder "#". An empty string ("") will resolve to the current page URL and cause unexpected navigation behavior when a user clicks the link.

Build docs developers (and LLMs) love