Skip to main content

Documentation Index

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

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

The Beach Mystery is a single-page application built with React 18 and bundled by Vite, deployed as a fully static site to GitHub Pages. Because GitHub Pages serves pre-built files from a repository without any server-side routing layer, the app uses React Router’s HashRouter — every URL takes the form /#/play or /#/endings, so navigation events never reach the host server. All routing is resolved entirely in the browser. This page walks through every directory, file, and dependency you need to understand before making changes.

Directory Layout

The repository has a flat, intentional structure: compiled output lives in assets/, all React source is divided across components/, data/, and hooks/, and index.html is the single entry point the browser loads.
the-beach-mystery/
├── index.html              # SPA entry point — loads main.js and all CSS
├── assets/
│   ├── main.js             # compiled app entry (Vite output)
│   ├── main.css            # compiled global styles
│   ├── Nav.css             # nav component styles
│   ├── Footer.css          # footer component styles
│   ├── index.js            # React 18 runtime
│   ├── index2.js           # React Router runtime
│   ├── jsx-runtime.js      # React JSX transform runtime
│   └── story-art/          # PNG scene illustrations
│       ├── beach-shore.png
│       ├── beach-sunset.png
│       ├── buried-treasure-chest.png
│       ├── cave-entrance.png
│       ├── cave-fork.png
│       ├── dark-cave.png
│       ├── hidden-cave-treasure.png
│       ├── magical-creature-den.png
│       ├── treasure-island.png
│       └── treasure-map.png
├── components/
│   ├── Nav.js              # navigation bar with all route links
│   ├── Footer.js           # footer with brand and social links
│   └── SceneArt.js         # scene illustration renderer
├── data/
│   ├── story.js            # all story data (nodes, endings, storylines, etc.)
│   └── sceneImages.js      # maps scene keys to PNG asset URLs
└── hooks/
    └── useGameState.js     # game state management hook
The assets/ directory contains compiled Vite output, not hand-written source. The files main.js, main.css, Nav.css, Footer.css, index.js, index2.js, and jsx-runtime.js are generated artifacts. The authoritative source lives in components/, data/, and hooks/.

Directory Purposes

assets/

Vite’s compiled output directory. main.js is the bundled React app entry point, main.css contains compiled global styles, jsx-runtime.js is the React JSX transform runtime, and story-art/ holds all ten PNG scene illustrations used as chapter backdrops during story playback.

components/

Reusable React components shared across multiple routes. Nav.js renders the navigation bar and all route links, Footer.js renders the brand footer, and SceneArt.js resolves a scene key to its corresponding PNG and renders the illustration with alt text.

data/

Pure data modules with no React dependencies. story.js exports every STORY_NODE, ENDING, STORYLINE, PERSONALIZATION_QUESTION, GALLERY_SCENE, and the single RIDDLE object. sceneImages.js maps each scene key string (e.g. "cave-fork") to a { src, alt } object resolved via import.meta.url.

hooks/

Custom React hooks. useGameState.js is the sole file here and owns all game logic — story progression, inventory flags, achievements, settings, and localStorage persistence. See Game State for the full API.

Routing

The app uses HashRouter from React Router. Hash-based URLs (/#/play, /#/endings) are processed entirely by the browser’s JavaScript runtime; the # fragment is never sent to the server. This makes the app deployable to any static file host — including GitHub Pages — without a custom 404 redirect or server configuration.
1

Browser loads index.html

GitHub Pages serves the single index.html file for all requests. The HTML file preloads main.js and all module-preload hints for chunked assets.
2

React Router initialises HashRouter

HashRouter reads window.location.hash and matches it against the registered route table, rendering the correct page component.
3

Navigation updates the hash

Every <Link> in Nav.js updates only the # fragment, so no HTTP request is made and the app state survives navigation without a page reload.
All routes registered in Nav.js:
PathLabelIconPurpose
/StartHome / landing page
/playPlay🎮Interactive story player
/endingsEndings🏆Achievement tracker for all four endings
/galleryGallery🖼️Scene artwork viewer
/aboutAboutℹ️About the project
/case-studyCase Study📄Technical case study
/blogJournal📖Development journal

Tech Stack

React 18

Component rendering, hooks (useState, useCallback, useEffect), and the virtual DOM. The compiled React runtime is bundled into assets/index.js.

React Router (HashRouter)

Client-side routing via hash URLs. Bundled into assets/index2.js. HashRouter is used specifically for GitHub Pages compatibility — no server configuration required.

Vite

Build tool and development server. Bundles the source modules into the assets/ directory and resolves import.meta.url paths for story art PNGs in sceneImages.js.

localStorage

Browser persistence layer for save data, achievements, and settings. Three separate keys are used: beach-mystery-save, beach-mystery-achievements, and beach-mystery-settings. See Game State for details.

CSS Custom Properties

All theme values (colours, spacing, typography scale) are defined as CSS variables on :root. High-contrast mode is toggled by switching a data attribute that rebinds these variables.

Custom Inline SVG / PNG Artwork

Ten hand-crafted storybook-style PNG illustrations stored in assets/story-art/. Each is mapped to one or more scene keys in sceneImages.js and rendered by SceneArt.js.

Typography

The app loads three Google Fonts families directly in index.html:
FamilyWeightsRole
Cormorant Garamond400, 400i, 500, 500i, 600, 700Literary serif for all story narration text, dialogue, and riddle prompts
Outfit300, 400, 500, 600, 700Clean sans-serif for all UI elements — navigation, buttons, labels, and settings panels
JetBrains Mono400, 500Monospace for code blocks in the Case Study and Journal pages
Cormorant Garamond is loaded with both upright and italic variants so story text can use emphasis (<em>) for character voices or key items without a font-synthesis fallback.

Build docs developers (and LLMs) love