Skip to main content

Documentation Index

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

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

The Projects page simulates a miniature Windows 98 desktop environment directly inside the browser. Three portfolio project windows are rendered on a teal canvas and can be freely repositioned by dragging their title bars. Clicking any window brings it to the front, replicating the window focus management of a real desktop OS. This page is one of the most interactive in the site — it turns a standard portfolio grid into a playful desktop metaphor.

Desktop Canvas

The entire page is enclosed in a single div that acts as the desktop surface:
<div className="h-[80vh] relative overflow-hidden bg-retro-teal/20 border-4 border-win-gray shadow-win-in p-4">
  <div className="absolute top-4 left-4 font-vt323 text-2xl text-black/50 pointer-events-none">
    Drag the windows around!
  </div>
  {/* Project windows */}
</div>
Visual appearance: The canvas is 80% of the viewport height, bounded by a thick Win98 inset border (border-4 border-win-gray shadow-win-in). The background is a very light teal wash (bg-retro-teal/20). A semi-transparent “Drag the windows around!” hint text is rendered in font-vt323 text-2xl text-black/50 at the top-left corner; it has pointer-events-none so it never interferes with window interaction. Overflow is clipped (overflow-hidden) so dragged windows cannot escape the canvas bounds.

Hardcoded Project Data

Three project objects are defined in a top-level constant array (be in the compiled source):
const projects = [
  {
    id: 1,
    title: "E-Commerce_2025.exe",
    name: "NextGen Storefront",
    desc: "A highly optimized, headless e-commerce platform built with Next.js, Stripe, and a lot of caffeine.",
    stack: ["React", "TypeScript", "Tailwind", "Stripe"],
    pos: { x: 20, y: 20 },
  },
  {
    id: 2,
    title: "AI_Chat_Bot.sys",
    name: "SassyBot AI",
    desc: "An AI assistant that intentionally gives you slightly passive-aggressive answers. Built with OpenAI API.",
    stack: ["Node.js", "OpenAI", "WebSockets"],
    pos: { x: 100, y: 150 },
  },
  {
    id: 3,
    title: "Legacy_System_Migrator.bat",
    name: "The Data Mover",
    desc: "A robust ETL pipeline that moves data from ancient mainframes into modern cloud databases without dropping a single bit.",
    stack: ["Python", "AWS", "PostgreSQL"],
    pos: { x: 300, y: 80 },
  },
];
Each project’s pos object sets its initial defaultPosition on the canvas, staggering the windows so they are visually separated on first render.

Window Focus Management

A single useState hook tracks which project window currently has focus:
const [focusedId, setFocusedId] = useState(null);
Each Window component receives:
  • zIndex={focusedId === project.id ? 50 : 10} — the focused window sits on top
  • onFocus={() => setFocusedId(project.id)} — clicking or interacting with a window calls this, updating focus
{projects.map((project) => (
  <Window
    key={project.id}
    title={project.title}
    icon={<FolderGit2 size={14} />}
    defaultPosition={project.pos}
    defaultSize={{ width: 350, height: "auto" }}
    zIndex={focusedId === project.id ? 50 : 10}
    onFocus={() => setFocusedId(project.id)}
    className="shadow-2xl"
  >
    {/* window content */}
  </Window>
))}
When no window has been clicked yet, focusedId is null and all windows render at zIndex: 10. The first window a user clicks jumps to zIndex: 50, pushing the others behind it. There is no close button on these project windows — they are permanently visible.

Project Window Content

Inside each window, the content area uses p-4 font-comic flex flex-col gap-4:

Project Name

<h3 className="font-bold text-xl text-retro-purple">{project.name}</h3>
Rendered in font-comic font-bold text-xl text-retro-purple.

Description

<p className="text-sm leading-relaxed">{project.desc}</p>
A short plain-text description of the project in text-sm leading-relaxed.

Tech Stack Badges

Each technology in the stack array is rendered as a small badge:
{project.stack.map((tech) => (
  <span
    key={tech}
    className="bg-retro-yellow px-2 py-1 text-xs border border-black shadow-[1px_1px_0px_#000] font-bold"
  >
    {tech}
  </span>
))}
Visual appearance: Compact yellow badges (bg-retro-yellow) with a 1px black border and a 1px offset solid drop shadow — a hand-stamped sticker aesthetic. Badges sit in a flex flex-wrap gap-2 row so they reflow on narrow windows.

Action Buttons

A dashed divider (border-t-2 border-dashed border-gray-300) separates the badge row from two action buttons rendered in a flex gap-2 row:
<BeveledButton className="flex-1 flex items-center justify-center gap-2 text-xs">
  <ExternalLink size={14} /> View Live
</BeveledButton>

<BeveledButton className="flex-1 flex items-center justify-center gap-2 text-xs">
  <Github size={14} /> Source
</BeveledButton>
Both buttons are equal-width (flex-1). The View Live button uses the Lucide ExternalLink icon; Source uses the Github icon. The buttons are currently decorative — no href values are wired up in the source.

Project Window Summary

Window TitleProject NameStackInitial Position
E-Commerce_2025.exeNextGen StorefrontReact, TypeScript, Tailwind, Stripe{ x: 20, y: 20 }
AI_Chat_Bot.sysSassyBot AINode.js, OpenAI, WebSockets{ x: 100, y: 150 }
Legacy_System_Migrator.batThe Data MoverPython, AWS, PostgreSQL{ x: 300, y: 80 }

Component Dependencies

ComponentSourceUsage
Window (p)components/Window.jsDraggable project frames
BeveledButton (d)components/BeveledButton.jsView Live and Source buttons
folder-git-2 (Lucide)lucide-reactWindow title bar icon
external-link (Lucide)lucide-reactView Live button icon
github (Lucide)lucide-reactSource button icon
useStateReact 18Window focus state

Build docs developers (and LLMs) love