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):
x-tagGroups.name— resource / domain (e.g. Cocktails, Ingredients)- Tag
x-displayName— sub-area (e.g. Core, Lifecycle, Step actions) - 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
| Location | Purpose |
|---|---|
app/lib/openapi/tags.ts | Tag name constants, root tags metadata, x-tagGroups |
app/lib/schemas/*.ts | Per-operation tags: [ApiTags.…] on each route in ResourceApiDoc |
app/lib/openapi/buildDocument.ts | Injects tags + x-tagGroups into the generated document |
docs/docusaurus.config.ts | sidebarOptions.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}:
| Suffix | Typical operations |
|---|---|
Core | list, create, get, update, delete, check |
Step actions | cocktail step actions (/actions) |
Lifecycle | clone, archive, unarchive |
Import & export | import/json, export/json, export/pdf |
Media | …/image |
References | reverse 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:
- Add
{Resource} / {Area}tags toApiTags,OPENAPI_TAGSandOPENAPI_TAG_GROUPS. - Update the schema file(s) to use
tags: [ApiTags.…]on each operation. - 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-methodclasses are already emitted by the generator). - API version tabs —
docs/sidebars.ts+docs/api/versions.json. - Introduction deduplication —
dedupeApiIntro()indocs/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.