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.

Every icon on the Log Portfolio desktop — About Me, My Computer, Control Panel, Internet Explorer, MSN Messenger, and Outlook Express — is driven by a single array in components/Desktop.js. Adding a new window is as simple as appending one object to that array and writing the React component that will render inside it.

The Desktop App Registry

The registry array is assigned to the constant ee near the bottom of components/Desktop.js. Each entry fully describes both the desktop icon and the window it opens:
const ee = [
  {
    id: 'about',
    title: 'AboutMe.txt',
    icon: <FileText size={32} className="text-white drop-shadow-md" />,
    component: <AboutMeApp />,
    defaultSize: { width: 500, height: 400 }
  },
  // ... more entries
];

Registry Entry Fields

FieldTypeDescription
idstringUnique identifier for the window. Also used as the hash route when opening from a static page.
titlestringText shown in the window’s title bar and below the desktop icon.
iconReactNodeA Lucide icon at size={32} for the desktop grid. The same icon is cloned at size={16} for the taskbar button automatically.
componentReactNodeThe React element rendered as the window’s scrollable content area.
defaultSize{ width: number, height: number }Initial pixel dimensions of the window when it opens. The user can resize it after opening.

Adding a New Window

1

Write your content component

Create the React component that will live inside the window. You can define it inline in Desktop.js (as all the built-in apps do) or import it from a separate file. Keep the root element at h-full so it fills the window:
const ResumeApp = () => (
  <div className="h-full bg-white p-4 overflow-auto font-sans text-sm text-black">
    <h2 className="text-lg font-bold mb-4">Jane Doe — Résumé</h2>
    <p className="mb-2"><strong>Experience:</strong> 5 years building React applications</p>
    <a
      href="/resume.pdf"
      className="text-blue-600 underline"
      target="_blank"
      rel="noreferrer"
    >
      Download PDF
    </a>
  </div>
);
2

Import an icon

All icons are Lucide React icons, accessed through ../assets/createLucideIcon.js in the built bundle. In source, import directly from lucide-react:
import { FileText, Briefcase, Star } from 'lucide-react';
Choose an icon that visually represents your window’s content.
3

Add an entry to the registry array

Open components/Desktop.js and add a new object to the ee array. Pick a unique id that has not been used by any other entry:
{
  id: 'resume',
  title: 'Resume.pdf',
  icon: <FileText size={32} className="text-red-400 drop-shadow-md" />,
  component: <ResumeApp />,
  defaultSize: { width: 600, height: 500 }
}
That’s it — no additional routing, context registration, or boilerplate required.
4

Double-click to test

Save the file and reload the dev server (npm run dev). Your new icon will appear in the desktop grid. Double-clicking it opens the window immediately.

Opening Windows Programmatically

If you need to open a window from inside another component — for example, a button inside the blog that opens the contact form — use the useWindows() hook from contexts/WindowContext.js:
import { useWindows } from '../contexts/WindowContext';

const MyButton = () => {
  const { openWindow } = useWindows();

  return (
    <button
      onClick={() =>
        openWindow({
          id: 'contact',
          title: 'Outlook Express',
          icon: <Mail size={16} />,
          content: <ContactApp />,
          defaultSize: { width: 550, height: 450 }
        })
      }
    >
      Contact me
    </button>
  );
};

Duplicate Window Behaviour

openWindow checks whether a window with the same id already exists in the windows state. If a matching window is found, it is focused and un-minimized rather than opened a second time. This means you never end up with two copies of the same window — safe to call from anywhere, as many times as you like.

Linking from a Static URL

Log Portfolio includes pre-built static pages in the pages/ directory (e.g. pages/AboutPage.html) that deep-link directly into a specific window without requiring the user to double-click the icon. Each static page sets a global variable before the app boots:
<script>
  window.__STATIC_PAGE_ROUTE__ = "/about-page";
  if (!window.location.hash || window.location.hash === "#/" || window.location.hash === "#") {
    window.location.hash = "/about-page";
  }
</script>
To create a static deep-link page for your new window:
1

Copy an existing page

Duplicate pages/AboutPage.html as pages/ResumePage.html.
2

Set the route value

Update the __STATIC_PAGE_ROUTE__ value and the hash assignment to a unique path that matches your window’s id:
<script>
  window.__STATIC_PAGE_ROUTE__ = "/resume-page";
  if (!window.location.hash || window.location.hash === "#/" || window.location.hash === "#") {
    window.location.hash = "/resume-page";
  }
</script>
3

Update the page title

Change the <title> tag to reflect your new page:
<title>Resume | log-portfolio</title>
The icon field in each registry entry is stored at size={32} for the desktop grid. When the desktop component opens a window, it calls React.cloneElement(entry.icon, { size: 16 }) to create the smaller taskbar variant automatically — so you only need to specify the icon once.
Keep defaultSize within the range of 350–750px wide and 350–600px tall. Windows can be resized by the user at runtime, but the initial size should comfortably fit the content without requiring scrolling on a 1024px-wide viewport.

Build docs developers (and LLMs) love