// DocsSpecsIndex.jsx — v0.20.0. // // Landing route at `/docs/specs`. The operator-stated body shape for // the parallel `/docs/sessions/:nnnn` page is "no body list — pick a // transcript from the nav", and the same gesture applies here: the // `/docs/specs` route either redirects to the first configured spec // (the common case) or renders a "no specs configured" empty state // (only reachable if a deployment overrides `OHM_DOCS_SPECS` to an // empty list — the framework default has two entries). // // The redirect is client-side because the manifest is a single API // call away; server-side redirect would require either a backend // route for the bare `/docs/specs` path (out of scope for v0.20.0) // or a build-time bake of the first spec name (which couples the // frontend bundle to the deployment overlay, which we don't do). import { useEffect, useState } from 'react' import { Navigate, Link } from 'react-router-dom' import { getSpecsManifest } from '../api.js' import { EVENTS, track } from '../lib/analytics' export default function DocsSpecsIndex() { const [firstName, setFirstName] = useState(null) // Tri-state: 'loading' (waiting on manifest), 'redirect' (we have a // name to redirect to — render ), 'empty' (no specs // configured), or 'error' (couldn't load the manifest at all). const [status, setStatus] = useState('loading') useEffect(() => { track(EVENTS.DOC_VIEWED, { section: 'specs' }) }, []) useEffect(() => { let active = true getSpecsManifest() .then(payload => { if (!active) return const specs = (payload && payload.specs) || [] if (specs.length === 0) { setStatus('empty') } else { setFirstName(specs[0].name) setStatus('redirect') } }) .catch(() => { if (!active) return setStatus('error') }) return () => { active = false } }, []) if (status === 'redirect' && firstName) { return } return (

Specs

{status === 'loading' &&

Loading…

} {status === 'empty' && (

No specs are configured for this deployment.

← Back to the user guide

)} {status === 'error' && (

Couldn't load the spec list.

)}
) }