Skip to main content

Documentation Index

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

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

Y2K Webring is a single-page React 18 application built with Vite. Rather than relying on server-side rendering or a backend, it ships a set of pre-rendered static HTML files — one per route — each of which boots the same React bundle and immediately hydrates the correct page. Navigation is powered by hash-based routing (window.location.hash), which means the entire site can be deployed to any static file host (GitHub Pages, Netlify, S3) with zero server configuration.

Application Shell

Every page is wrapped by the AppLayout component (components/layout/AppLayout.js). It renders a responsive three-column flex container that holds all persistent UI:
┌──────────────────────────────────────────────────────┐
│               max-w-7xl  (p-4 md:p-8)                │
│  ┌──────────┐  ┌──────────────────┐  ┌────────────┐  │
│  │          │  │                  │  │            │  │
│  │ LeftNav  │  │   <main>         │  │  Right-    │  │
│  │ lg:w-64  │  │   flex-1         │  │  Webring   │  │
│  │ (always) │  │   (page content) │  │  lg:w-48   │  │
│  │          │  │                  │  │ (Home only)│  │
│  └──────────┘  └──────────────────┘  └────────────┘  │
└──────────────────────────────────────────────────────┘
The three columns behave as follows:
ColumnComponentWidthVisibility
LeftLeftNavlg:w-64Always rendered
Center<main> (flex-1)Fills remaining spaceAlways rendered
RightRightWebringlg:w-48Home route only
AppLayout checks useLocation().pathname === "/" to decide whether to render RightWebring and the SparkleTrail cursor effect. The center <main> always wraps children in PageTransitionBar, which handles the Framer Motion entry animation on every route change.
// components/layout/AppLayout.js (reconstructed from source)
const AppLayout = ({ children }) => {
  const isHome = useLocation().pathname === "/";
  return (
    <div className="min-h-screen p-4 md:p-8 max-w-7xl mx-auto flex flex-col lg:flex-row gap-6 relative">
      {isHome && <SparkleTrail />}
      <LeftNav />
      <main className="flex-1 flex flex-col min-w-0">
        <PageTransitionBar>{children}</PageTransitionBar>
      </main>
      {isHome && <RightWebring />}
    </div>
  );
};

Build Pipeline

Vite bundles the project into two primary output artefacts:
  • /assets/main.js — the complete JavaScript bundle (React, React Router, Framer Motion, all page components, and all data).
  • /assets/main.css — the compiled Tailwind stylesheet, including custom Y2K utility classes (border-chunky-magenta, bg-y2k-violet, etc.) and the @keyframes marching-ants animation.
Pre-rendered HTML files are emitted for every route:
index.html               →  /            (Home)
pages/About.html         →  /about
pages/Projects.html      →  /projects
pages/Skills.html        →  /skills
pages/Writing.html       →  /writing
pages/WritingPost.html   →  /writing-post
pages/CaseStudies.html   →  /case-studies
pages/Contact.html       →  /contact
Each HTML file pre-loads all required ES modules with <link rel="modulepreload"> so the browser can fetch them in parallel before executing the bundle:
<!-- index.html (excerpt) -->
<script type="module" crossorigin src="./assets/main.js"></script>
<link rel="modulepreload" crossorigin href="./useScreenInit.js">
<link rel="modulepreload" crossorigin href="./assets/jsx-runtime.js">
<link rel="modulepreload" crossorigin href="./assets/index.js">
<link rel="modulepreload" crossorigin href="./assets/createLucideIcon.js">
<link rel="modulepreload" crossorigin href="./assets/book-open.js">
<link rel="modulepreload" crossorigin href="./assets/proxy.js">
<link rel="modulepreload" crossorigin href="./components/layout/LeftNav.js">
<link rel="modulepreload" crossorigin href="./data/portfolioData.js">
<link rel="modulepreload" crossorigin href="./components/layout/RightWebring.js">
<link rel="modulepreload" crossorigin href="./assets/index2.js">
<link rel="modulepreload" crossorigin href="./components/layout/PageTransitionBar.js">
<link rel="modulepreload" crossorigin href="./components/y2k/SparkleTrail.js">
<link rel="modulepreload" crossorigin href="./components/layout/AppLayout.js">
<link rel="modulepreload" crossorigin href="./components/y2k/BorderedPanel.js">
<link rel="modulepreload" crossorigin href="./components/y2k/StatusWidget.js">
<link rel="modulepreload" crossorigin href="./components/y2k/ChunkyButton.js">
<link rel="modulepreload" crossorigin href="./components/y2k/PillTag.js">
<link rel="stylesheet" crossorigin href="./assets/main.css">

Static Hosting

Because the router uses window.location.hash, the server never needs to know which “page” the visitor is on — the hash fragment is purely client-side. A request for /pages/About.html always returns the same file regardless of what follows the #. Each HTML file includes an inline <script> that runs before the React bundle loads. It inspects the URL and, if no hash is present, rewrites it to the correct hash route. This ensures direct links (e.g. shared links without a #) still land on the right page. See Routing → Hash Redirect Script for the full script.
Because routing is entirely hash-based, there are no server-side rewrite rules needed. The site deploys as a folder of static files and works out of the box on GitHub Pages, Netlify, Cloudflare Pages, or any CDN.

Key Dependencies

PackageVersionRole
react18.3.1UI component model and rendering
react-dom18.3.1DOM renderer
react-router-dom6.30.4Hash-based client-side routing
framer-motionPage transition animations and sparkle effects
tailwindcssUtility-first CSS, extended with Y2K custom tokens
lucide-react0.522.0Icon set used in LeftNav and RightWebring
viteBuild tool, dev server, and module pre-loading

Further Reading

Routing

Hash-based URL strategy, the seven route definitions, and the page transition bar.

Data Layer

How all portfolio content lives in a single portfolioData.js source-of-truth file.

Build docs developers (and LLMs) love