Skip to main content

Documentation Index

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

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

The virtual filesystem is the backbone of every navigation command in guest-portfolio.dev. When a visitor runs ls, cd, or cat, the terminal resolves paths against a plain JavaScript object tree exported from utils/fileSystem.js. No server, no database — just a nested object you can edit directly.

The fileSystem Object

The entire filesystem lives in a single constant (c in the minified build, exported and used throughout the app). Its root is the home directory "~", and every node in the tree follows a consistent schema.

Node Schema

Directory node:
{
  name:        "projects",       // display name used by ls
  type:        "dir",            // "dir" | "file" | "exec"
  permissions: "drwxr-xr-x",    // shown in ls -la output
  size:        "4096",           // shown in ls -la output (string)
  date:        "Oct 24 10:15",   // shown in ls -la output
  children: {                    // keyed by filename
    "terminal-portfolio.md": { /* file node */ },
    "mainframe-ai.md":       { /* file node */ }
  }
}
File node:
{
  name:        "about.md",
  type:        "file",           // "file" for plain files, "exec" for executables
  permissions: "-rw-r--r--",
  size:        "1024",
  date:        "Oct 24 10:05",
  content:     "about"           // string value — see special content keys below
}

Default Filesystem Tree

The default home directory (~) ships with the following structure:
~
├── about.md          (file)   content: "about"
├── skills.sh         (exec)   content: "skills"
├── projects/         (dir)
│   ├── terminal-portfolio.md  content: "project:terminal"
│   └── mainframe-ai.md        content: "project:ai"
├── blog/             (dir)
│   ├── why-i-love-vim.md      content: "blog:vim"
│   └── leaving-the-ui-behind.md  content: "blog:ui"
├── references.log    (file)   content: "references"
└── case-studies/     (dir)
    └── migration-to-k8s       content: "case:k8s"

Special Content Keys

The content field in a file node is usually a plain string that cat renders as-is. However, Terminal.js special-cases several filenames in its cat handler and renders custom React components instead of the raw content string:
FilenameWhat cat renders
about.md<AboutOutput /> — neofetch-style bio component
references.logInline JSX log entries (three hardcoded lines)
all othersnode.content rendered as plain text
The check is done by filename, not by the content value:
// Inside Terminal.js cat handler
if (node.name === "about.md") {
  output = <AboutOutput />;
} else if (node.name === "references.log") {
  output = <div>/* hardcoded log entries */</div>;
} else {
  output = <div>{node.content || "Empty file"}</div>;
}
The content key for about.md is only a placeholder — the filename "about.md" is what triggers the AboutOutput component. If you rename the file in fileSystem.js, you must also update the corresponding node.name === "about.md" check in Terminal.js, otherwise cat will fall through and display the raw "about" string instead of your bio.

Utility Functions

Two helper functions are exported from utils/fileSystem.js and used throughout the app.

readPath(cwd, path)

Resolves path relative to the current working directory cwd. Supports:
  • Relative paths (projects/terminal-portfolio.md, ../blog)
  • .. to traverse up one level (stops at ~)
  • ~-prefixed paths (~/projects) — always resolves from home
  • Absolute paths starting with / — treated as absolute from home root
Returns an object:
{ node, path, error }
// node  — the resolved filesystem node, or null on failure
// path  — the resolved absolute path string (e.g. "~/projects")
// error — an error string if resolution failed, otherwise undefined

getNode(path)

Resolves a path that is already absolute (starting from ~). Used internally by readPath. Returns the node object, or undefined if the path does not exist.

Adding a New Project File

1

Open utils/fileSystem.js

Locate the projects directory node inside the children of "~":
projects: {
  name: "projects",
  type: "dir",
  permissions: "drwxr-xr-x",
  size: "4096",
  date: "Oct 24 10:15",
  children: {
    "terminal-portfolio.md": { ... },
    "mainframe-ai.md": { ... }
  }
}
2

Add a new file node to children

Add your new project alongside the existing entries:
children: {
  "terminal-portfolio.md": { /* existing */ },
  "mainframe-ai.md":       { /* existing */ },

  "my-new-project.md": {
    name:        "my-new-project.md",
    type:        "file",
    permissions: "-rw-r--r--",
    size:        "512",
    date:        "Jan 15 09:00",
    content:     "# My New Project\n\nA short description of what this project does."
  }
}
3

Verify with ls and cat

In the live terminal, navigate to the projects directory and confirm the file appears:
cd projects
ls
cat my-new-project.md
The cat command will display the content string as plain preformatted text.
4

(Optional) Link to a man page

If the project warrants a full case study, add a corresponding entry in case-studies/ with content: "case:my-new-project" and create the matching JSX page in ManOutput.js. See the Content customization guide for details.

Adding a New Directory

Creating a subdirectory follows the same pattern as a file node, but with type: "dir" and a children object:
"open-source": {
  name:        "open-source",
  type:        "dir",
  permissions: "drwxr-xr-x",
  size:        "4096",
  date:        "Jan 15 09:00",
  children: {
    "plugin-x.md": {
      name:        "plugin-x.md",
      type:        "file",
      permissions: "-rw-r--r--",
      size:        "256",
      date:        "Jan 15 09:05",
      content:     "A Vim plugin for syntax highlighting Dockerfiles."
    }
  }
}
Add this object as a new key inside the children of whichever parent directory you want it to live in.

Build docs developers (and LLMs) love