Skip to main content

Documentation Index

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

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

Log Portfolio is a single-page React application that simulates a Windows 98-era operating system shell entirely in the browser. Rather than navigating between pages, users interact with draggable, resizable windows that open on a persistent desktop — just like a real OS. The entire application is built with React and Vite, using Framer Motion for window animations and Tailwind CSS for the retro Win98 styling.

Three-Layer Architecture

The app is organized into three distinct layers that sit on top of each other, each with a clearly scoped responsibility.

Context Layer

WindowProvider in contexts/WindowContext.js holds all window state — which windows are open, their positions, z-indices, minimize/maximize flags, and which window is currently active. Every other component reads from and writes to this single source of truth.

Shell Layer

Desktop and Taskbar are always rendered and never unmount. The Desktop renders desktop icons from the app registry. The Taskbar reflects currently open windows as buttons and provides a Start-menu-style clock area.

Window Layer

Individual Window components are spawned on demand inside a React Portal targeting the DOM root. Each window is a Framer Motion motion.div with drag, resize, and animation behavior wired to WindowContext actions.

Component Relationships

The table below shows how each major piece fits into the hierarchy and what it depends on.
Component / ModuleLayerDepends OnResponsibility
WindowProviderContextReact useState, useCallbackOwns all window state; exposes openWindow, closeWindow, minimizeWindow, restoreWindow, maximizeWindow, focusWindow
useWindows()ContextWindowContextCustom hook; provides context values to any consumer; throws if used outside WindowProvider
DesktopShelluseWindows(), app registry arrayRenders the desktop icon grid; calls openWindow() on double-click
TaskbarShelluseWindows()Renders a button per open window; calls restoreWindow() / focusWindow()
WindowWindowuseWindows(), Framer Motion, React PortalRenders a single draggable/resizable window frame with title bar controls

Data Flow: Opening a Window

1

User double-clicks a desktop icon

The Desktop component’s onDoubleClick handler fires, calling openWindow() from useWindows() with the full window descriptor: { id, title, icon, content, defaultSize }.
2

WindowContext updates state

openWindow() checks whether a window with that id already exists in the windows array. If it does, it focuses the existing window instead of creating a duplicate. If not, it appends a new entry to windows with isOpen: true, isMinimized: false, isMaximized: false, and a fresh zIndex.
3

Window component mounts with animation

Because Window wraps its output in Framer Motion’s AnimatePresence, newly added windows animate in with a scale: 0.8 → 1 and opacity: 0 → 1 spring transition. Exit animations play the reverse — scaling down and sliding to y: 100vh — before the component unmounts.
4

Title bar interactions update context

Once open, every title bar button calls back into WindowContext: the button calls minimizeWindow(id), the button calls maximizeWindow(id), the button calls closeWindow(id), and clicking anywhere in the window body calls focusWindow(id) to bring it to the front.

The Desktop App Registry

The single source of truth for what applications exist in the portfolio lives in the apps array defined in Desktop.js. Each entry fully describes one desktop icon and the window it opens.
// components/Desktop.js (simplified)
const apps = [
  {
    id: "about",
    title: "AboutMe.txt",
    icon: <FileText size={32} className="text-white drop-shadow-md" />,
    component: <AboutApp />,
    defaultSize: { width: 500, height: 400 },
  },
  {
    id: "projects",
    title: "My Computer",
    icon: <Folder size={32} className="text-yellow-400 fill-yellow-400 drop-shadow-md" />,
    component: <ProjectsApp />,
    defaultSize: { width: 600, height: 450 },
  },
  // ... more apps
];
The full registry contains six apps: AboutMe.txt, My Computer (Projects), Control Panel (Skills), Internet Explorer (Blog), MSN Messenger (Testimonials), and Outlook Express (Contact). To add a new app, you add one entry to this array — no other wiring is needed. The Desktop component maps over the array to render icons, and passes the entry directly to openWindow() on double-click.

Static Pages

The pages/ directory contains one standalone HTML file per app route. Each file bootstraps the same Vite bundle but sets window.__STATIC_PAGE_ROUTE__ before the React app mounts, which tells the hash router to navigate directly to that app’s route. This means a shareable URL like pages/AboutPage.html opens the browser with the About Me window already in focus.
pages/
├── AboutPage.html        → /about-page
├── BlogPage.html         → /blog-page
├── ContactPage.html      → /contact-page
├── ProjectsPage.html     → /projects-page
├── SkillsPage.html       → /skills-page
└── TestimonialsPage.html → /testimonials-page
See Routing and Static Pages for a full breakdown of how these files work and how to add new ones.

Further Reading

Window Management System

Deep-dive into WindowContext — every exported function, the WindowData shape, and how the Window component handles drag, resize, and animation.

Routing and Static Pages

How hash-based routing works, what window.__STATIC_PAGE_ROUTE__ does, and step-by-step instructions for adding a new static page route.

Build docs developers (and LLMs) love