Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/apursley2012/neon-retro-web/llms.txt

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

The Projects page (/projects) mimics a Windows 98/XP file explorer window. A breadcrumb-style header reads C:\PORTFOLIO\PROJECTS with a subtitle 4 object(s) | 1.21 Gigawatts. Below it, four large icon tiles sit in a 2×4 grid — each a big emoji icon above a .exe-suffixed filename. Clicking a tile triggers an AnimatePresence-wrapped modal that slides in at scale 0.9 and expands to a two-column detail view: a CRT-framed screenshot on the left, and category, description, tech stack badges, and action buttons on the right. A semi-transparent backdrop with backdrop-blur-sm dims the rest of the page while the modal is open.

Page Structure

// Projects page component (minified identifier: rm)
const ProjectsPage = () => {
  const [selected, setSelected] = useState(null);

  return (
    <motion.div
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      exit={{ opacity: 0 }}
      className="h-full flex flex-col"
    >
      {/* Explorer header */}
      <div className="mb-6 flex items-center gap-4 border-b-2 border-y2k-teal pb-2">
        <FolderIcon className="w-8 h-8 text-y2k-turquoise fill-y2k-turquoise/20" />
        <div>
          <h2 className="font-display text-3xl text-white">C:\PORTFOLIO\PROJECTS</h2>
          <p className="font-code text-xs text-gray-400">4 object(s) | 1.21 Gigawatts</p>
        </div>
      </div>

      {/* Icon grid */}
      <div className="grid grid-cols-2 md:grid-cols-4 gap-8 p-4">
        {projects.map((project) => (
          <div
            key={project.id}
            onClick={() => setSelected(project.id)}
            className="flex flex-col items-center gap-2 cursor-pointer group"
          >
            <div className="w-16 h-16 flex items-center justify-center text-3xl bg-y2k-panel border-2 border-y2k-teal ...">
              {project.icon}
            </div>
            <span className="font-code text-xs text-center px-2 py-1 text-gray-300 ...">
              {project.title}.exe
            </span>
          </div>
        ))}
      </div>

      {/* AnimatePresence modal */}
      <AnimatePresence>
        {selected && (
          <motion.div
            initial={{ opacity: 0, scale: 0.9 }}
            animate={{ opacity: 1, scale: 1 }}
            exit={{ opacity: 0, scale: 0.9 }}
            className="absolute inset-4 md:inset-12 z-50 flex items-center justify-center"
          >
            <Window title={`${project.title} - Details`} onClose={() => setSelected(null)}>
              {/* Two-column detail view */}
            </Window>
          </motion.div>
        )}
      </AnimatePresence>

      {/* Backdrop */}
      {selected && (
        <div
          className="absolute inset-0 bg-black/60 backdrop-blur-sm z-40"
          onClick={() => setSelected(null)}
        />
      )}
    </motion.div>
  );
};

Project Data

The projects array (ma in the minified bundle) is defined as a module-level constant directly above the component. Each project object has the following shape:
// assets/main.js — projects array (identifier: ma)
const projects = [
  {
    id: "ecomm",
    title: "RetroCart E-Commerce",
    category: "Full Stack",
    icon: "🛍️",
    description: "A fully functional e-commerce platform with a nostalgic 90s aesthetic but modern React/Node.js architecture under the hood.",
    tech: ["React", "Node.js", "PostgreSQL", "Stripe"],
    demoUrl: "#",
    repoUrl: "#",
    image: "https://images.unsplash.com/photo-1555066931-4365d14bab8c?auto=format&fit=crop&w=800&q=80",
    note: "* Uses mocked payment data for demo",
  },
  {
    id: "dashboard",
    title: "MediMetrics Dashboard",
    category: "Frontend",
    icon: "📊",
    description: "Healthcare analytics dashboard inspired by my nursing days. Focuses on high-contrast readability and complex data visualization.",
    tech: ["TypeScript", "React", "D3.js", "Tailwind"],
    demoUrl: "#",
    repoUrl: "#",
    image: "https://images.unsplash.com/photo-1551288049-bebda4e38f71?auto=format&fit=crop&w=800&q=80",
    note: "* HIPAA compliant (mock data only)",
  },
  {
    id: "inventory",
    title: "MerchManager Pro",
    category: "Full Stack",
    icon: "📦",
    description: "Inventory management system built to solve the exact headaches I experienced in retail merchandising.",
    tech: ["Next.js", "Prisma", "PostgreSQL", "tRPC"],
    demoUrl: "#",
    repoUrl: "#",
    image: "https://images.unsplash.com/photo-1586864387967-d02ef85d93e8?auto=format&fit=crop&w=800&q=80",
    note: "",
  },
  {
    id: "cli",
    title: "Nostalgia CLI",
    category: "Tooling",
    icon: "⌨️",
    description: "A command-line tool that adds unnecessary but delightful 90s hacker movie effects to your terminal output.",
    tech: ["Rust", "CLI"],
    demoUrl: "#",
    repoUrl: "#",
    image: "https://images.unsplash.com/photo-1526374965328-7f61d4dc18c5?auto=format&fit=crop&w=800&q=80",
    note: "* Warning: May cause spontaneous hacking montages",
  },
];

Detail Modal Layout

When a tile is clicked, the modal opens as a two-column Window:

Left Column — Media

A CRT-effect frame (border-8 border-gray-800, crt-overlay CSS class) wraps an <img> with filter contrast-125 saturate-150 applied. A pulsing red LED dot (w-2 h-2 rounded-full bg-red-500 animate-pulse) sits in the top-right corner of the frame. Below the image are two action buttons: RUN DEMO (teal fill) and SOURCE (teal border, dark fill).

Right Column — Details

From top to bottom: a violet CATEGORY badge, a font-display project title, a description paragraph, a TECH_STACK section with monochrome bordered tech pill badges, a dashed-underline VIEW README.TXT link (magenta), and an optional orange italic note string.

Customising This Page

This is a pre-built static site. The repository contains only compiled output — there is no src/ directory or editable source files. The customisation steps below describe changes that must be made in the original source project before rebuilding.
1

Edit existing projects

In your source project, locate the projects data array (the ma identifier in the minified bundle corresponds to this array in the source). Update each object’s title, description, tech, demoUrl, repoUrl, image, and note fields. The icon field accepts any single emoji character.
2

Add a new project

In the source project, copy any existing project object and append it to the projects array with a unique id. The grid layout is grid-cols-2 md:grid-cols-4 — adding a fifth item wraps naturally to a new row. The modal handles any number of tech badges automatically via flex flex-wrap.
3

Replace the Unsplash images

Each project’s image is an Unsplash URL with auto=format&fit=crop&w=800&q=80. Replace the URL with any publicly accessible image. The <img> element applies filter contrast-125 saturate-150, so highly saturated photos look best with the CRT effect.
4

Wire up real demo and repo links

The demoUrl and repoUrl fields are currently both "#". Replace them with your actual live-demo URL and GitHub repository URL. The RUN DEMO button opens demoUrl and the SOURCE button opens repoUrl — both are plain <a> tags. Add target="_blank" rel="noopener noreferrer" if you want them to open in a new tab.
5

Update the Explorer header subtitle

The <p> reading 4 object(s) | 1.21 Gigawatts is hardcoded. In the source project, change 4 object(s) to match the actual number of projects in your array.
The modal uses AnimatePresence from Framer Motion with mode unset (defaults to "sync"). The Window component’s onClose prop is wired to () => setSelected(null) to close the modal. Clicking anywhere on the backdrop-blur-sm overlay div also closes it.
The crt-overlay class is defined in assets/main.css — it applies a scanline pseudo-element effect. If you replace the project screenshots with images that have important fine detail (e.g., text-heavy screenshots), the scanline overlay may reduce legibility. In the source project, add filter-none to the <img> or remove crt-overlay from the frame <div> for those entries.

Build docs developers (and LLMs) love