Theming

Token-driven dark/light theming with no reload.

Tokens

src/styles/tokens.ts: getThemeTokens(theme) / deriveSurfaceTokens(bg, text): a small, fixed set of base tokens (background, text, accent) plus surface/border tokens derived by mixing bg toward text, never introducing a new hue.

Applying without a reload

src/styles/apply-theme.ts: writes the resulting CSS custom properties and the data-theme attribute on <html>; switching themes only changes variable values, with no re-render of the component tree.

Zustand store

src/state/theme-store.ts: a Zustand store that persists the chosen theme in localStorage and applies it synchronously before the first paint (no wrong-theme flash).

Document Model

Before anything reaches a component, the raw OpenAPI document is normalized into an in-memory model (tagGroups → endpoints), implemented as plain TypeScript, tested independently, with no dependency on React. The four responsibilities:

  • normalize.ts: dereferences every $ref via @apidevtools/swagger-parser and groups endpoints by tag, preserving declared order.
  • cap-depth.ts: makes a dereferenced (and possibly cyclic) schema safe for JSON.stringify, for the "Copy OpenAPI" button.
  • example.ts / schema-tree.ts: build the example payload with type-tokens and the navigable schema tree from the same schema, without fabricating fake data.
  • filter.ts: the client-side search used by the sidebar.

Every function that walks the schema (flattenSchema, schemaToTreeNodes, extractValidationRules) tracks visited nodes by object identity, not by a numeric depth cap, so a genuinely recursive DTO renders a single (circular reference) / ↩ circular marker instead of unrolling N times or crashing.