Skip to main content

Documentation Index

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

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

This page covers the repository layout of Player One and explains how the different pieces fit together at runtime. The project follows a Vite static-export pattern: a single React application is compiled into a shared set of JavaScript and CSS bundles, and then a lightweight HTML entry file is generated for each route. Understanding this layout makes it straightforward to add new pages, customise components, or deploy the site to any static host.

Directory Tree

player-one/
├── index.html              # Root HTML entry point
├── useScreenInit.js        # React + bundled runtime bootstrap
├── canvas.manifest.js      # Build manifest
├── assets/
│   ├── main.js             # Bundled application entry
│   ├── main.css            # Tailwind + custom arcade CSS
│   ├── jsx-runtime.js      # React JSX runtime
│   ├── createLucideIcon.js # Lucide icon factory
│   └── proxy.js            # Framer Motion + React Router bundle
├── components/
│   ├── Navigation.js       # Arcade navigation + inventory modal
│   ├── HUD.js              # Fixed HUD overlay with clock/score
│   ├── CRTOverlay.js       # CRT scanline + vignette effects
│   ├── GhostSprite.js      # Animated ghost SVG component
│   ├── PageTransition.js   # Framer Motion entrance animation
│   └── ArcadeCabinet.js    # Project card styled as arcade cabinet
└── pages/
    ├── Home.html
    ├── About.html
    ├── Projects.html
    ├── Skills.html
    ├── Writing.html
    ├── CaseStudies.html
    └── Contact.html

Static Export Approach

Player One uses Vite to produce a fully static build. Rather than relying on a single index.html with client-side routing fallbacks, the build generates one HTML file per route inside the pages/ directory. Each of these HTML files is structurally identical — they all load the same shared JS and CSS bundles from assets/ — but each one injects a small inline <script> block that tells the React application which route to render. The key mechanism is the global variable window.__STATIC_PAGE_ROUTE__. Before assets/main.js initialises the React tree, the per-page script sets this variable to the route string for that page (e.g. "/about", "/contact"). The React Router bootstrap inside main.js reads this value and uses it to pre-seed the hash location, so the correct page content renders immediately without any extra navigation.

Hash-Based Routing

Player One uses React Router’s HashRouter throughout the application. With HashRouter, every URL includes a # fragment before the path — for example, https://yoursite.com/#/projects. Because the hash is never sent to the web server, the browser always loads the HTML file it was directed to, and React Router handles all navigation client-side. This approach has an important practical benefit: no server-side redirect or rewrite rules are required. The site deploys identically to GitHub Pages, Netlify (with no _redirects file), Amazon S3, or any plain file host. Each pages/*.html file covers its own route, and refreshing any page or navigating directly to a #/ URL will work correctly.

Per-Page Route Bootstrap Script

Each HTML file in pages/ contains the following inline script pattern. Here is the example for the About page:
<script>
  window.__STATIC_PAGE_ROUTE__ = "/about";
  (function () {
    if (!window.location.hash || window.location.hash === "#") {
      window.location.replace(
        window.location.pathname +
        window.location.search +
        "#/about"
      );
    }
  })();
</script>
The script does two things:
  1. Sets window.__STATIC_PAGE_ROUTE__ to the canonical route string. The React bootstrap reads this value to know which route to activate.
  2. Redirects bare visits — if someone navigates directly to pages/About.html without a hash fragment (or with only a bare #), the IIFE immediately replaces the location with the correct #/about hash. This ensures the React Router HashRouter always sees a well-formed hash URL when it initialises.
The root index.html uses the same pattern with window.__STATIC_PAGE_ROUTE__ = "/" and appends #/ instead.

Asset Bundles

All shared JavaScript is compiled into the assets/ directory and loaded via <link rel="modulepreload"> in every HTML file:
FilePurpose
assets/main.jsApplication entry — mounts the React tree into #root
assets/main.cssCompiled Tailwind CSS plus all custom arcade utility classes and animations
assets/jsx-runtime.jsReact’s JSX transform runtime (react/jsx-runtime)
assets/createLucideIcon.jsLucide React’s icon factory function, shared by all icon references
assets/proxy.jsCombined bundle of Framer Motion (motion) and React Router (HashRouter, useNavigate, Routes, Link, etc.)

Component Descriptions

Each file under components/ is a pre-built ES module that exports a single React component:
ComponentExportDescription
Navigation.jsN (Navigation)Pixel-art navigation bar with links to all seven routes and an inventory/modal panel. Imports from proxy.js for routing hooks.
HUD.jsH (HUD)Fixed-position overlay rendering PLAYER_1, a static score of 999999, an “INSERT COIN” blinker, a credits counter, and a live clock that updates every second.
CRTOverlay.jsC (CRTOverlay)Renders two absolutely-positioned, pointer-events-none layers — crt-overlay (horizontal scanlines) and crt-vignette (radial darkening) — that sit above the entire viewport.
GhostSprite.jsG (GhostSprite)An SVG pixel-art ghost animated by Framer Motion to travel horizontally across the screen in a looping path, with configurable color, delay, duration, startX, startY, and scale props.
PageTransition.jsP (PageTransition)Wraps page content in a Framer Motion div that animates opacity, scale (0.95 → 1), and filter: blur on entrance and exit over 400 ms.
ArcadeCabinet.jsA (ArcadeCabinet)Renders a project card in the silhouette of a three-part arcade cabinet: a marquee header with the project title, a screen body showing the description, and a control panel footer with RUN DEMO, SOURCE, and README action buttons.

Build Output

Running npm run build produces a dist/ directory that mirrors the source layout:
  • One HTML file per route (root index.html plus one per page in pages/)
  • dist/assets/main.css — the complete Tailwind + arcade CSS bundle
  • dist/assets/main.js and associated JS chunks
  • All component and runtime modules
The result is a fully self-contained static site that can be uploaded to any CDN or file host as-is.
All component files under components/ and the bundles under assets/ are pre-built and minified. Editing them directly will have no effect once the site is rebuilt — Vite will overwrite them. To make lasting changes to a component, edit the original source file in your development workspace and then run npm run build again to regenerate the output.

Build docs developers (and LLMs) love