HashRouter.jsxjavascript
import { HashRouter, Routes, Route } from "react-router";
import Pages from "./Routes";
import { ContentProvider } from "./services/content";
import { ScreensaverProvider } from "./services/screensaver";
import { Screensaver } from "./components/Screensaver/Screensaver";
import { ErrorBoundary } from "./components/ErrorBoundary";
import { Stage } from "./components/Stage/Stage";
import { PrintMapPage } from "./pages/PrintMap/PrintMap";

/**
 * Hash-based router variant - works regardless of the deploy path, so it's
 * the default (see App.jsx). Stage (the whole-app scale wrapper, see
 * Stage.jsx) sits inside <HashRouter> rather than around it in App.jsx,
 * because it reads its config via useConfig() -> useSearchParams(), which
 * requires router context. Content + screensaver providers around the
 * routes, pages guarded by the ErrorBoundary; the Screensaver stays mounted
 * as a sibling so its fade works in both directions.
 *
 * `/print-map` is a dev-only export tool (see PrintMap.jsx), not part of the
 * visitor-facing kiosk - it's branched out here, before Stage/ContentProvider/
 * ScreensaverProvider, so it gets none of the kiosk chrome (fixed-resolution
 * scaling, idle screensaver) and fetches its own content directly instead of
 * going through ContentProvider's route-based file resolution
 * (presentationModes.js has no entry for it).
 */
const Router = () => {
  return (
    <HashRouter>
      <Routes>
        <Route path="/print-map" element={<PrintMapPage />} />
        <Route
          path="/*"
          element={
            <Stage>
              <ContentProvider>
                <ScreensaverProvider>
                  <ErrorBoundary>
                    <Pages />
                  </ErrorBoundary>
                  <Screensaver />
                </ScreensaverProvider>
              </ContentProvider>
            </Stage>
          }
        />
      </Routes>
    </HashRouter>
  );
};

export default Router;