Skip to main content

Documentation Index

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

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

Desktop is the root visual surface of DevOS. It combines two responsibilities: it renders the icon grid that users interact with to launch apps, and it acts as the mounting point for all open Window components. Every aspect of the desktop — background, icon layout, animated window entrances, and easter-egg decorations — lives in this single component.

Layout

The desktop fills the full viewport minus the 48 px taskbar at the bottom:
height: calc(100vh - 48px);  /* implicit — the taskbar is positioned fixed at the bottom */
The background is set via Tailwind utilities:
bg-os-cream bg-desktop-pattern
bg-os-cream provides the base cream colour; bg-desktop-pattern layers a radial-gradient dot pattern on top, evoking a classic OS linen texture. Clicking anywhere on the bare desktop deselects the currently selected icon.

Icon registry

The I array in Desktop.js is the single source of truth for which apps appear as desktop shortcuts. Each entry has the following shape:
interface DesktopIcon {
  id: string;                          // unique key; also used as the window id
  label: string;                       // filename-style label shown below the icon
  icon: React.ComponentType;           // Lucide React icon component
  component: React.ComponentType;      // app component rendered inside the Window
  defaultSize: { width: number; height: number };
}
The icons registered in the source are:
const I = [
  { id: 'home',        label: 'README.md',        icon: FileTextIcon,   component: HomeApp,         defaultSize: { width: 700,  height: 500 } },
  { id: 'about',       label: 'about_me.exe',      icon: UserIcon,       component: AboutApp,        defaultSize: { width: 600,  height: 450 } },
  { id: 'projects',    label: 'projects/',         icon: FolderIcon,     component: ProjectsApp,     defaultSize: { width: 800,  height: 550 } },
  { id: 'skills',      label: 'task_manager.exe',  icon: ActivityIcon,   component: SkillsApp,       defaultSize: { width: 650,  height: 500 } },
  { id: 'work',        label: 'career.log',        icon: TerminalIcon,   component: TerminalApp,     defaultSize: { width: 750,  height: 450 } },
  { id: 'case_studies',label: 'case_studies/',     icon: FileBoxIcon,    component: CaseStudiesApp,  defaultSize: { width: 900,  height: 600 } },
  { id: 'articles',    label: 'notes.txt',         icon: BookOpenIcon,   component: ArticlesApp,     defaultSize: { width: 600,  height: 700 } },
  { id: 'contact',     label: 'mail.exe',          icon: MailIcon,       component: ContactApp,      defaultSize: { width: 550,  height: 400 } },
  { id: 'testimonials',label: 'reviews.html',      icon: StarIcon,       component: TestimonialsApp, defaultSize: { width: 700,  height: 500 } },
];
The first real entry, used throughout these docs as the canonical example:
{ id: 'home', label: 'README.md', icon: FileTextIcon, component: HomeApp, defaultSize: { width: 700, height: 500 } }
To add a new app shortcut, append an entry to the I array in Desktop.js and import both the icon (from lucide-react) and the app component. No other configuration is needed — the icon will appear in the grid and openWindow will be wired automatically.

Icon interaction

Icons are rendered in a flex-col flex-wrap column starting at top-left of the desktop. Each icon is a 96 px wide div (w-24).
InteractionEffect
Single clickSets the selected icon ID in local state; highlights the icon with bg-os-teal/20 border border-os-teal/30
Double clickCalls openWindow(icon.id, { title, icon, component, defaultSize }) and clears the selection
Click on desktopClears the selection (handled by the root div’s onClick)
The onDoubleClick handler passes event.stopPropagation() to prevent the desktop click handler from immediately clearing the selection after the window opens.

Recycle Bin

A special Recycle Bin entry is hardcoded at the bottom of the icon column using mt-auto to push it to the end of the flex column. It uses the Trash2 Lucide icon and does not correspond to any real app entry in the I array. Double-clicking it fires an easter-egg alert:
onDoubleClick={(e) => {
  e.stopPropagation();
  alert(
    'Recycle Bin: Contains 42 unfinished side projects. ' +
    'Emptying is disabled to preserve your guilt.'
  );
}}

Window host

All open windows are rendered inside an AnimatePresence block so that exit animations play correctly when a window is closed:
import { AnimatePresence } from 'framer-motion';
import { Window } from './Window';

<AnimatePresence>
  {windows.map((win) => (
    <Window key={win.id} windowData={win} />
  ))}
</AnimatePresence>
AnimatePresence monitors the windows array from context. When a window is removed (closed), it waits for the exit animation (scale: 0.8, y: 100vh) to complete before removing the DOM node.

Sticky note

A decorative yellow sticky note is absolutely positioned in the top-right corner of the desktop at top-8 right-8. It has a rotate-2 transform for a hand-placed look and contains a hardcoded TODO list:
<div className="absolute top-8 right-8 w-48 bg-yellow-100 p-4 shadow-md transform rotate-2 font-serif text-sm text-gray-800">
  <p className="font-bold mb-2">TODO:</p>
  <ul className="list-disc pl-4 space-y-1">
    <li>Fix that one CSS bug</li>
    <li>Write tests (lol)</li>
    <li>Drink water</li>
  </ul>
</div>
This is a portfolio flourish — edit the list items or remove the element entirely from Desktop.js to customise or clean up the desktop for production.

Build docs developers (and LLMs) love