Summary
`apps/api/openapi/openapi.yaml` is the hand-authored API source of truth. The admin app and `packages/ts/sdk` each define their own decoupled `Post` / `User` / `Media` types that drift from the wire format.
Confirmed impedance mismatches between server JSON and admin TypeScript Post type alone (8+ items):
- Envelope: server `{data, pagination.next_cursor}` vs admin `{posts, nextCursor, total}`
- Author: server `author_id` vs admin `author: {id, displayName}`
- Dates: server has three (`published_at` / `updated_at` / `created_at`) vs admin's single `date`
- `commentsCount`: admin expects, server doesn't emit
- Cursor name: `pagination.next_cursor` vs `nextCursor`
- Status enum drift between admin types and server's `validStatuses`
- Nullable mismatches (server emits null timestamps, admin types as string)
- Comments package solves this differently than posts — drift between sibling modules
Per-page adapters proliferating across:
- `posts/page.tsx:121-144` — full envelope + field flattener
- `comments/types.ts:91` — `WireComment` → `Comment` translator (the GOOD pattern)
- `redirects/page.tsx:29`, `webhooks/page.tsx:37`, `jobs/dlq/page.tsx:46` — `data || []` chains
- `marketplace/actions.ts:73,113` — `body.data ?? []`
Fix
- Add `packages/ts/api-types` workspace package.
- Wire `openapi-typescript` to generate `packages/ts/api-types/src/index.ts` from `apps/api/openapi/openapi.yaml` on build (or commit the generated file).
- Migrate `apps/admin` and `packages/ts/sdk` to import wire types from `@gonext/api-types`.
- Keep UI types (`Post` with `author.displayName`) as a transformed layer, but the wire side becomes single-source.
Why P1 not P0
The current per-page adapters work. This is technical debt, not a production-down issue. But every new admin page will accumulate a copy of the same pattern until this lands.
Summary
`apps/api/openapi/openapi.yaml` is the hand-authored API source of truth. The admin app and `packages/ts/sdk` each define their own decoupled `Post` / `User` / `Media` types that drift from the wire format.
Confirmed impedance mismatches between server JSON and admin TypeScript Post type alone (8+ items):
Per-page adapters proliferating across:
Fix
Why P1 not P0
The current per-page adapters work. This is technical debt, not a production-down issue. But every new admin page will accumulate a copy of the same pattern until this lands.