How a single ApiSpec becomes a rendered endpoint reference page. The spec data
model and resolvers are covered in
single-source-of-truth.md; this doc is about the
components that consume them.
src/pages/docs/DocDetailPage.tsx handles /docs/:slug. It:
- reads
slugfrom the router, - resolves a
DocNodeviagetDocBySlug(slug)(returns NotFound for unknown slugs), - branches on
node.kind:"guide"→ renders<MdxGuide slug=… />with no right pane (see mdx-guides.md),"endpoint"→ renders<EndpointDetail spec=… />in the centre pane and<CodeSamples spec=… />in the right rail.
- emits SEO tags (title, description, canonical,
og:*) and analternatelink to the endpoint's.mdtwin.
src/components/docs/EndpointDetail.tsx. Renders everything about the endpoint,
split by parameter location. It reads via the resolvers, never raw spec fields:
| Section | Source |
|---|---|
Header — method tag + path, name, summary, UAT base URL |
spec.method, spec.path, spec.name, DEFAULT_BASE_URL |
| Description | spec.description |
| Path parameters | resolveRequestParams(spec) filtered by in === "path" |
| Query parameters | resolveRequestParams(spec) filtered by in === "query" |
| Body parameters | resolveRequestParams(spec) filtered by in === "body" |
| Headers | resolveHeaders() |
| Responses | <ResponseAccordion spec=… /> |
Because params come from resolveRequestParams, the common params appear
automatically for the methods they apply to (GET shows them as query params, other
methods as body params) — unless omitCommonParams drops one or an extraRequestParams
entry overrides it — and the auth headers appear on every endpoint without being
declared per-spec.
Params.tsx — responsive param renderer:
- wide (
xl+): dense 4-column table (Field, Type, Required, Description); - narrow: stacked field list (
FieldList); - shows a required/optional badge and any
example.
ResponseAccordion.tsx — collapsible response list:
- row 0 (open by default) = success, rendered as a field tree from
resolveResponseFields(spec); - one row per
spec.errorScenariosentry, each showing the error JSON example.
ResponseFieldTree.tsx — recursive renderer for ResponseField[]:
- indented list, left border on nested levels;
- field name + type + description;
- fields flagged
imp: trueget a "verifiable" badge and bold name (this is the "what can you verify?" affordance for verification products); - recurses into
childrenfor nested objects/arrays.
CodeSamples.tsx — the right rail. Request card (method/path header, copy
button, cURL/JS/Python tabs, line-numbered code, and a "Test Request" button that
opens the Scalar "Try it" modal via onTest) plus a response card showing
spec.sampleSuccessResponse. Fully covered in code-samples.md
and try-it-now.md.
Two contexts, same data:
- Runtime (client/SSR): the React components above render on navigation and during hydration.
- Build time: the Markdown-twin plugin reads the same specs to emit
.mdequivalents (see ../markdown-generation.md). The Markdown twin includes the request/response JSON examples, not the per-language code snippets.