// Every route this site serves, in one place. // // `scripts/prerender.js` used to build its own list while `src/routes.jsx` built // the router's, and nothing compared them. A route added to one and not the // other is not a small bug: the page is never prerendered, so `server/index.js` // answers a direct request for it with `dist/404.html`, and every visitor // following a link and every crawler reading the sitemap gets a 404 on a page // the site's own navigation points at. // // Plain JavaScript with no side effects, because prerender imports it in Node // before Vite exists, and so does the validator runner. import { services } from '../../src/data/services.js' import { industries } from '../../src/data/industries.js' export const STATIC_ROUTES = [ '/', '/about', '/services', '/industries', '/contact', '/support', '/privacy-policy', ] export const ROUTES = [ ...STATIC_ROUTES, ...services.map((service) => `/services/${service.id}`), ...industries.map((industry) => `/industries/${industry.id}`), ] const join = (base, path) => `${base}/${path}`.replace(/\/{2,}/g, '/') /** Flattens the router's nested table into the paths it declares. */ export const routerPaths = (table, base = '') => table.flatMap((route) => { const self = route.index ? base || '/' : route.path === '/' ? '/' : join(base, route.path ?? '') const children = route.children ? routerPaths(route.children, self === '/' ? '' : self) : [] return [self, ...children] }) /** * Routes the router declares that nothing prerenders. A path with a parameter * (`/services/:slug`) or the catch-all is covered by the data lists above * rather than by a literal, so neither counts as drift. */ export const routeDrift = (table) => [ ...new Set( routerPaths(table) .filter((path) => !path.includes(':') && !path.includes('*')) .filter((path) => !ROUTES.includes(path)), ), ]