Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/apursley2012/choose-your-destiny/llms.txt

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

Choose Your Destiny solves one of the classic problems of single-page apps on static hosts: making every URL work on a direct browser visit without a server that can rewrite paths to index.html. The solution is a combination of React Router’s HashRouter — which puts all navigation in the URL fragment after # — and a set of pre-built static HTML shells in the /pages/ directory, each of which bootstraps the React app at the correct route automatically.

Why Hash Routing?

Standard BrowserRouter requires a web server configured to return index.html for every unknown path. On a static host (GitHub Pages, Netlify free tier with no redirect rules, S3), a request to /projects will return a 404 because there is no file at that path. HashRouter sidesteps this entirely. The full URL looks like:
https://username.github.io/choose-your-destiny/#/projects
The browser only sends /choose-your-destiny/ to the server. Everything after # is handled entirely in the browser by React Router. No server configuration is ever needed.
Do not swap HashRouter for BrowserRouter unless you add server-side rewrite rules. On GitHub Pages there is no way to do this — every non-root path will return a 404. Netlify and Vercel both support rewrite rules via a _redirects file or vercel.json, but those require additional configuration that is not included in this project.

How Each Static Page Shell Works

The /pages/ directory contains one HTML file per route. When a user navigates directly to, for example, https://username.github.io/choose-your-destiny/pages/About.html, the shell:
  1. Sets window.__STATIC_PAGE_ROUTE__ to the intended route path.
  2. Checks whether the URL already has a hash fragment.
  3. If there is no hash (or it is just #), it replaces the current URL to append the route’s hash — redirecting the browser to load the React app at the right place.
Here is the shell script from pages/About.html:
<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>
Every page shell is structurally identical — only the route string changes. The full list of shells and their corresponding routes:
File__STATIC_PAGE_ROUTE__Hash fragment
index.html/#/
pages/Home.html/#/
pages/About.html/about#/about
pages/Projects.html/projects#/projects
pages/Skills.html/skills#/skills
pages/Writing.html/writing#/writing
pages/CaseStudies.html/case-studies#/case-studies
pages/Contact.html/contact#/contact
canvas.manifest.js mirrors this same route table in a machine-readable format. It is consumed by useScreenInit to resolve the ?mp_screen= query parameter to a route path when the app is launched from a design-tool canvas. The manifest and the static shells must stay in sync — if you add a route, add a corresponding entry to both.

React Router Route Definitions

All seven routes are registered inside the Nm app root. The Sm redirect component runs first (reading the canvas manifest), followed by the sm layout shell which wraps the Routes tree:
// Simplified from assets/main.js (Nm component)
function Nm() {
  return (
    <HashRouter>            {/* th */}
      <Sm />                {/* redirect handler */}
      <sm>                  {/* layout: header, nav, background */}
        <Routes>            {/* Yp */}
          <Route path="/"            element={<cm />} />  {/* Home        */}
          <Route path="/about"       element={<fm />} />  {/* About       */}
          <Route path="/projects"    element={<hm />} />  {/* Projects    */}
          <Route path="/skills"      element={<gm />} />  {/* Skills      */}
          <Route path="/writing"     element={<xm />} />  {/* Writing     */}
          <Route path="/case-studies" element={<wm />} /> {/* Case Studies*/}
          <Route path="/contact"     element={<km />} />  {/* Contact     */}
        </Routes>
      </sm>
    </HashRouter>
  );
}
The component aliases above are minified names from the compiled bundle. In source they map to:
PathComponent aliasSection
/cmHome
/aboutfmAbout
/projectshmProjects
/skillsgmSkills
/writingxmWriting
/case-studieswmCase Studies
/contactkmContact

The Sm Redirect Component

Sm is a headless component that runs one side effect on mount. It calls useScreenInit to get an initial path from the canvas manifest (via the ?mp_screen= query param) and, if the path is not /, it calls React Router’s useNavigate to navigate there with replace: true so no extra history entry is created.
// Simplified from assets/main.js
function Sm() {
  const navigate = useNavigate();       // Jo()
  const screenState = useScreenInit();  // reads canvas.manifest.js via useScreenInit (exported as u)

  useEffect(() => {
    if (screenState?.path && screenState.path !== "/") {
      navigate(screenState.path, { replace: true });
    }
  }, []);

  return null;
}
This component renders nothing — it is purely a navigation side-effect. If no ?mp_screen= param is present, useScreenInit returns {} and Sm does nothing.

Adding a New Route

This project is a pre-built static site. There is no package.json, no source directory, and no build tooling in this repository. Adding a new route requires obtaining the original source, making changes there, rebuilding, and redeploying the output. The steps below describe what that process involves.
1

Create the page component in source

Add your new page component in the React source project. It should follow the same pattern as the existing pages — a div with min-h-screen, a PageHeader with a matching neon color prop, and your content wrapped in NeonCard components.
2

Register the route in the app root

Import your component and add a <Route> inside the Routes block in the Nm app root:
<Route path="/my-page" element={<MyPage />} />
3

Create the static HTML shell

Copy any existing file from /pages/ and update the two route strings:
<!-- pages/MyPage.html -->
<script>
  window.__STATIC_PAGE_ROUTE__ = "/my-page";

  (function () {
    if (!window.location.hash || window.location.hash === "#") {
      window.location.replace(
        window.location.pathname +
        window.location.search +
        "#/my-page"
      );
    }
  })();
</script>
4

Add the route to canvas.manifest.js

Add a new entry to the screens object. Pick a unique ID in the same format as the existing ones:
scr_newpage: {
  name: "My Page",
  route: "/",
  state: { path: "/my-page" },
  position: { x: 160, y: 10120 }
}
The position values only matter if you are using the manifest inside a canvas-based design tool. Set them to any unused coordinate.
5

Add the link to the navigation

Include the route in the nav-links array in the app source so it appears in the header navigation and mobile menu:
{ path: "/my-page", label: "MY PAGE", icon: SomeIcon, color: "cyan" }
6

Build and deploy

Rebuild the project from source to produce the updated static output, then upload or push the new build to your static host.

Build docs developers (and LLMs) love