Skip to main content

OpenAPI navigation tags

The API Reference sidebar is generated from the OpenAPI spec. Grouping, labels and order are controlled in the app (not in the docs repo). After changing tags, regenerate the spec and sync the docs (see Workflow below).

Why tags (not paths)?

URL paths in this API are mostly flat (/api/v1/workspaces/{id}/cocktails/...). Product concepts do not always match path prefixes — for example step actions live under /actions, not /cocktails/actions. Tags let you group by domain while keeping REST paths unchanged.

The docs theme supports two sidebar levels from the spec (plus operations):

  1. x-tagGroups.name — resource / domain (e.g. Cocktails, Ingredients)
  2. Tag x-displayName — sub-area (e.g. Core, Lifecycle, Step actions)
  3. Operations — individual endpoints (with HTTP method badges)

There is no third nesting level (e.g. grouping by HTTP method). Method badges show GET/POST/PUT/DELETE next to each operation instead.

Where to edit

LocationPurpose
app/lib/openapi/tags.tsTag name constants, root tags metadata, x-tagGroups
app/lib/schemas/*.tsPer-operation tags: [ApiTags.…] on each route in ResourceApiDoc
app/lib/openapi/buildDocument.tsInjects tags + x-tagGroups into the generated document
docs/docusaurus.config.tssidebarOptions.groupPathsBy: 'tagGroup'

Each schema file exports one or more *ApiDoc objects. Every HTTP method block includes a tags array — that is what drives the sidebar entry.

Example: split a resource into sub-groups

Before (one flat tag):

// app/lib/schemas/cocktails.ts
GET: {
tags: ['Cocktails'],
summary: 'List cocktails',
// ...
},
POST: {
tags: ['Cocktails'],
summary: 'Clone cocktail',
// ...
},

After (domain sub-tags):

import { ApiTags } from '@lib/openapi/tags';

GET: {
tags: [ApiTags.cocktailsCore],
summary: 'List cocktails',
// ...
},
POST: {
tags: [ApiTags.cocktailsLifecycle],
summary: 'Clone cocktail',
// ...
},

Add the new tag names to ApiTags, OPENAPI_TAGS and the correct x-tagGroups entry in app/lib/openapi/tags.ts.

Tag naming convention

For resources with many endpoints, use {Resource} / {Area}:

SuffixTypical operations
Corelist, create, get, update, delete, check
Step actionscocktail step actions (/actions)
Lifecycleclone, archive, unarchive
Import & exportimport/json, export/json, export/pdf
Media…/image
Referencesreverse lookups (e.g. cocktails using an ingredient)

Use x-displayName for the sub-area label inside a resource group (e.g. Core under the Cocktails group — not Cocktails · Core).

Top-level groups (x-tagGroups)

x-tagGroups defines sections in the sidebar. Every tag used by an operation must appear in exactly one group, or it will not show up when using groupPathsBy: 'tagGroup'.

Current groups (see OPENAPI_TAG_GROUPS in the app) — one group per resource:

  • Workspace — Core, Settings, API keys, Join codes, Membership
  • Workspace Users, Audit Logs
  • Cocktails, Ingredients, Garnishes, Glasses, Ice, Tags, Units, Cards, Calculations
  • Monitor — Configuration, Slides
  • Queue, Statistics (Logging / Advanced), Ratings

Each resource uses sub-tags such as Core, Lifecycle, Import & export, Media, etc. where applicable.

Introduction page (sidebar)

The OpenAPI plugin injects the info/intro doc (cocktail-manager-api) into every x-tagGroup. In docs/sidebars.ts, dedupeApiIntro() strips those duplicates and keeps one Introduction entry at the top of the API sidebar.

Workflow

From the app repository:

pnpm openapi:generate

This writes app/openapi/v1.json (and runs the drift guard in CI). Then in the docs repository:

pnpm sync:openapi

That copies the specs, cleans old generated pages and runs gen-api-docs. Restart pnpm start if the sidebar does not refresh.

Extending to new resources

When adding a new API resource:

  1. Add {Resource} / {Area} tags to ApiTags, OPENAPI_TAGS and OPENAPI_TAG_GROUPS.
  2. Update the schema file(s) to use tags: [ApiTags.…] on each operation.
  3. Run the workflow above.

Keep one tag per operation (the first tag controls grouping). Do not group by HTTP method — summaries plus method badges are easier to scan.

Docs-only options

These do not require OpenAPI changes:

  • HTTP method badges — CSS in docs/src/css/custom.css (.api-method classes are already emitted by the generator).
  • API version tabsdocs/sidebars.ts + docs/api/versions.json.
  • Introduction deduplicationdedupeApiIntro() in docs/sidebars.ts.

For custom sidebar labels or a third nesting level you would need sidebarGenerators in docusaurus.config.ts and a swizzled sidebar component — only consider that if tag sub-groups are not enough.