Skip to content

feat: typed REST communication layer between web and api (#11)#33

Merged
G0maa merged 19 commits into
mainfrom
feat/11-communication-between-api-and-web
May 27, 2026
Merged

feat: typed REST communication layer between web and api (#11)#33
G0maa merged 19 commits into
mainfrom
feat/11-communication-between-api-and-web

Conversation

@G0maa

@G0maa G0maa commented May 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Resolves #11 — decides and implements the communication method between apps/web and apps/api.

  • Decision: REST + OpenAPI. The API emits a committed apps/api/openapi.json from a dedicated @nestjs/swagger generation entrypoint (mirrors the real server's /api prefix + URI versioning).
  • Web consumes it Nuxt-natively. @hey-api/openapi-ts generates TypeScript types + Zod schemas (SDK plugin off); calls go through a $fetch.create $api plugin (base URL from runtime config) with Zod validation at the response boundary in a useAsyncData transform.
  • Contract stays honest. A CI step regenerates both artifacts and fails on drift.
  • Proven end-to-end against the existing /api/v1/status endpoint.

tRPC and GraphQL were considered and rejected (tRPC closes the public-API door / is non-idiomatic in NestJS; GraphQL is over-engineered for this surface). A full generated SDK + TanStack Query / neverthrow / transformers were explicitly deferred — all reversible since the OpenAPI doc remains the source of truth.

Design spec and implementation plan: docs/superpowers/specs/2026-05-26-web-api-communication-design.md, docs/superpowers/plans/2026-05-26-web-api-communication.md.

Test Plan

  • API suite green (pnpm --filter api test) — incl. OpenAPI document shape test
  • Web unit/component green (pnpm --filter web test) — incl. Zod boundary validation (accepts valid, rejects contract-violating payload)
  • format:check, lint, typecheck (api + web), build:web all pass
  • Generated contract in sync (drift check passes locally)
  • CI green on the PR

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Public GET /api/v1/status endpoint with typed response; frontend plugin and composable to fetch and Zod-validate status.
  • Tests

    • Added generation/contract e2e test and boundary validation tests ensuring generated schemas match runtime responses.
  • Chores

    • CI step to regenerate OpenAPI and fail on drift; codegen scripts added; runtime API base default configured.
  • Documentation

    • Added design, plan, and guidance for Web ↔ API typed contract workflow.

Review Change Stack

G0maa and others added 14 commits May 26, 2026 17:11
Decide on the web/api communication method (issue #11): REST over HTTP
with an OpenAPI document as the contract source of truth and
openapi-typescript-generated types consumed via Nuxt $fetch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Refine the design after evaluating a full generated client (SDK) against
a lighter types-only option, guided by the Nuxt 4 docs: keep REST +
OpenAPI, generate types + Zod via hey-api (SDK plugin off), and consume
Nuxt-natively through a $api $fetch instance with Zod validation in
transform. SDK / TanStack Query / transformers explicitly deferred.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 26, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2fdd1542-c485-4da9-9ff1-0bd2ced05b23

📥 Commits

Reviewing files that changed from the base of the PR and between 911d86e and fa3327c.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (10)
  • .claude/CLAUDE.md
  • .vscode/settings.json
  • apps/api/package.json
  • apps/api/src/entrypoints/generate-open-api.ts
  • apps/api/src/entrypoints/tests/generate-open-api.e2e.test.ts
  • apps/api/src/modules/status/use-cases/get-api-info/tests/get-api-info.e2e.test.ts
  • apps/api/src/modules/status/use-cases/get-api-info/tests/get-api-info.service.unit.test.ts
  • apps/api/src/modules/swagger/create-open-api-document.ts
  • apps/web/nuxt.config.ts
  • pnpm-workspace.yaml
✅ Files skipped from review due to trivial changes (2)
  • apps/api/src/modules/swagger/create-open-api-document.ts
  • .vscode/settings.json
🚧 Files skipped from review as they are similar to previous changes (5)
  • apps/api/src/entrypoints/tests/generate-open-api.e2e.test.ts
  • pnpm-workspace.yaml
  • apps/web/nuxt.config.ts
  • apps/api/package.json
  • apps/api/src/entrypoints/generate-open-api.ts

📝 Walkthrough

Walkthrough

Implements OpenAPI-driven typed REST: API generates committed apps/api/openapi.json from Swagger-decorated DTOs; web generates TypeScript and Zod artifacts, integrates a Nuxt $api plugin and useApiStatus composable with Zod validation; CI regenerates and fails on drift; docs and tests added.

Changes

Typed REST API Contract Implementation

Layer / File(s) Summary
Workspace & package dependency setup
pnpm-workspace.yaml, apps/api/package.json, apps/web/package.json
Workspace catalog adds @nestjs/swagger, @hey-api/openapi-ts, and zod. API adds generate:openapi script and Swagger dep. Web adds generate:api/e2e scripts and Zod/openapi-ts deps.
API OpenAPI documentation & generation
apps/api/src/modules/swagger/build-api-documentation.ts, apps/api/src/modules/status/use-cases/get-api-info/get-api-info.response.ts, apps/api/src/modules/status/use-cases/get-api-info/get-api-info.controller.ts, apps/api/src/entrypoints/generate-open-api.ts, apps/api/src/entrypoints/tests/generate-open-api.e2e.test.ts, apps/api/src/modules/swagger/create-open-api-document.ts
Adds buildApiDocumentation(version), converts status response to a Swagger-decorated DTO with @ApiProperty, annotates the controller (ApiTags, ApiOperation operationId, ApiOkResponse), and adds a generate-open-api entrypoint plus an e2e contract test and helper to create the Swagger document.
Generated OpenAPI contract artifact
apps/api/openapi.json
Committed OpenAPI 3.0 document defining GET /api/v1/status with operationId: getApiInfoV1 and GetApiInfoResponse schema (name, version, nodeEnv, uptimeSeconds, nullable commit).
Web API client codegen & consumption
apps/web/openapi-ts.config.ts, apps/web/app/api/types.gen.ts, apps/web/app/api/zod.gen.ts, apps/web/app/api/index.ts, apps/web/app/plugins/api.ts, apps/web/app/composables/useApiStatus.ts, apps/web/app/composables/__tests__/useApiStatus.spec.ts
Configures openapi-ts (types + Zod only) to generate types.gen.ts and zod.gen.ts. Adds a Nuxt $api plugin using runtimeConfig.public.apiBase, implements useApiStatus that fetches /v1/status and validates the response via zGetApiInfoResponse in useAsyncData transform, and includes tests for parsing success/failure.
Web & CI configuration for API communication
apps/web/nuxt.config.ts, apps/web/eslint.config.mjs, .github/workflows/ci.yml, .prettierignore
Adds runtimeConfig.public.apiBase default http://localhost:3000/api. ESLint ignores generated app/api/**. Prettier ignores apps/api/openapi.json. CI workflow includes a step to regenerate API/web artifacts and fail when git diff --exit-code reports drift.
Test assertion updates
apps/api/src/modules/status/use-cases/get-api-info/tests/*
Replaces Node assert/strict usage with expect and updates assertions in unit and e2e tests.
Architecture & implementation documentation
docs/superpowers/specs/2026-05-26-web-api-communication-design.md, docs/superpowers/plans/2026-05-26-web-api-communication.md, .claude/*, apps/api/.claude/*, apps/web/.claude/*
Design spec, implementation plan, and guidance files document REST + OpenAPI decision, generated types + Zod approach (no SDK), CI drift-check strategy, testing expectations, and a 12-task plan.

Sequence Diagrams

sequenceDiagram
  participant GenerateScript as generate:openapi script
  participant GenerateEntrypoint as generate-open-api.ts
  participant ApiModule as ApiModule
  participant SwaggerModule as SwaggerModule
  participant FileSystem as apps/api/openapi.json

  GenerateScript->>GenerateEntrypoint: pnpm build + node dist/src/entrypoints/generate-open-api.js
  GenerateEntrypoint->>ApiModule: NestFactory.create(ApiModule)
  GenerateEntrypoint->>SwaggerModule: createOpenApiDocument(app)
  SwaggerModule->>GenerateEntrypoint: OpenAPI document
  GenerateEntrypoint->>FileSystem: write formatted openapi.json
Loading
sequenceDiagram
  participant Component as Nuxt Component
  participant useApiStatus as useApiStatus Composable
  participant ApiPlugin as $api Plugin (useAsyncData)
  participant ApiServer as API Server
  participant ZodSchema as zGetApiInfoResponse Schema

  Component->>useApiStatus: call useApiStatus()
  useApiStatus->>ApiPlugin: useAsyncData fetch /v1/status via $api
  ApiPlugin->>ApiServer: GET /api/v1/status (baseURL from runtimeConfig)
  ApiServer->>ApiPlugin: raw JSON response
  ApiPlugin->>ZodSchema: zGetApiInfoResponse.parse(response) in transform
  ZodSchema->>ApiPlugin: validated GetApiInfoResponse
  ApiPlugin->>Component: typed data
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A rabbit hops with glee so bright,
OpenAPI sketches lines just right.
From Nest to Nuxt the types align,
Zod keeps responses clean and fine,
CI checks drift—commit and delight.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: typed REST communication layer between web and api (#11)' accurately describes the main change: implementing typed REST communication between the two applications.
Linked Issues check ✅ Passed All coding requirements from issue #11 are met: REST communication chosen, OpenAPI as single source of truth established, TypeScript/Zod types generated on web side, Zod response validation implemented, and CI drift detection added.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing the typed REST communication layer: OpenAPI generation, TypeScript/Zod codegen, Nuxt plugin setup, CI drift checks, and supporting documentation/configuration.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/11-communication-between-api-and-web

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

apps/api/src/entrypoints/generate-open-api.ts

ESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox.

apps/api/src/entrypoints/tests/generate-open-api.e2e.test.ts

ESLint skipped: the ESLint configuration for this file references a package that is not available in the sandbox.

apps/api/src/modules/status/use-cases/get-api-info/tests/get-api-info.e2e.test.ts

ESLint skipped: the ESLint configuration for this file references a package that is not available in the sandbox.

  • 3 others

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment thread apps/web/app/api/index.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
apps/api/src/entrypoints/tests/generate-open-api.e2e.test.ts (1)

36-43: ⚡ Quick win

Assert required fields, not only property names.

This currently passes even if one of the contract fields becomes optional in OpenAPI. Add an assertion on schema.required to lock the interface shape.

Proposed test hardening
     const schema = document.components?.schemas?.['GetApiInfoResponse'] as Record<string, any>
+    assert.deepEqual((schema.required ?? []).sort(), [
+      'commit',
+      'name',
+      'nodeEnv',
+      'uptimeSeconds',
+      'version',
+    ])
     assert.deepEqual(Object.keys(schema.properties).sort(), [
       'commit',
       'name',
       'nodeEnv',
       'uptimeSeconds',
       'version',
     ])
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/api/src/entrypoints/tests/generate-open-api.e2e.test.ts` around lines 36
- 43, The test currently only asserts property names on the OpenAPI schema for
'GetApiInfoResponse' (variable schema) but doesn't assert which fields are
required; update the test to also assert schema.required contains the exact
required field names (e.g.,
['commit','name','nodeEnv','uptimeSeconds','version']) so the contract fails if
any field becomes optional. Locate the assertion block around the schema
variable in generate-open-api.e2e.test.ts and add a check that schema.required
(sorted) strictly equals the expected required fields.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/superpowers/plans/2026-05-26-web-api-communication.md`:
- Around line 486-489: The markdown code fence containing the two-path snippet
("apps/web/app/api/" and "apps/api/openapi.json") is unlabeled and triggers
MD040; update that fence to specify a language label (use "text") so the block
becomes a fenced code block with ```text at the start and ``` at the end,
preserving the existing lines inside exactly as shown; locate the unlabeled
fence around the snippet and add the language token to fix the markdownlint
warning.

In `@docs/superpowers/specs/2026-05-26-web-api-communication-design.md`:
- Line 5: Update the design status line "Status: Approved (design);
implementation pending" to indicate implementation is complete by replacing it
with a clear implemented state (e.g., "Status: Implemented" or "Status:
Implemented — [YYYY-MM-DD]") and optionally add an explicit implementation date
or state transition note so the document reflects the delivered implementation;
look for the exact phrase "Status: Approved (design); implementation pending" in
the document and modify it accordingly.
- Around line 75-89: The fenced architecture block that begins with the line
"NestJS controllers + `@nestjs/swagger` decorators" is missing a language tag;
update the opening fence from ``` to ```text (and keep the closing fence as ```)
so the block is marked as plain text to satisfy markdownlint MD040.

---

Nitpick comments:
In `@apps/api/src/entrypoints/tests/generate-open-api.e2e.test.ts`:
- Around line 36-43: The test currently only asserts property names on the
OpenAPI schema for 'GetApiInfoResponse' (variable schema) but doesn't assert
which fields are required; update the test to also assert schema.required
contains the exact required field names (e.g.,
['commit','name','nodeEnv','uptimeSeconds','version']) so the contract fails if
any field becomes optional. Locate the assertion block around the schema
variable in generate-open-api.e2e.test.ts and add a check that schema.required
(sorted) strictly equals the expected required fields.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f78aad67-9064-4d43-9c90-e76193f50b3f

📥 Commits

Reviewing files that changed from the base of the PR and between f79cc94 and c2e4e60.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (22)
  • .github/workflows/ci.yml
  • .prettierignore
  • apps/api/openapi.json
  • apps/api/package.json
  • apps/api/src/entrypoints/generate-open-api.ts
  • apps/api/src/entrypoints/tests/generate-open-api.e2e.test.ts
  • apps/api/src/modules/status/use-cases/get-api-info/get-api-info.controller.ts
  • apps/api/src/modules/status/use-cases/get-api-info/get-api-info.response.ts
  • apps/api/src/modules/swagger/build-api-documentation.ts
  • apps/web/app/api/index.ts
  • apps/web/app/api/types.gen.ts
  • apps/web/app/api/zod.gen.ts
  • apps/web/app/composables/__tests__/useApiStatus.spec.ts
  • apps/web/app/composables/useApiStatus.ts
  • apps/web/app/plugins/api.ts
  • apps/web/eslint.config.mjs
  • apps/web/nuxt.config.ts
  • apps/web/openapi-ts.config.ts
  • apps/web/package.json
  • docs/superpowers/plans/2026-05-26-web-api-communication.md
  • docs/superpowers/specs/2026-05-26-web-api-communication-design.md
  • pnpm-workspace.yaml

Comment thread docs/superpowers/plans/2026-05-26-web-api-communication.md
Comment thread docs/superpowers/specs/2026-05-26-web-api-communication-design.md
Comment thread docs/superpowers/specs/2026-05-26-web-api-communication-design.md
Comment thread apps/api/src/modules/status/use-cases/get-api-info/get-api-info.controller.ts Outdated
Embed the API version in the operationId so hey-api's generated
operation-response type (GetApiInfoV1Response) no longer collides with
the schema type (GetApiInfoResponse), dropping the GetApiInfoResponse2
alias. Matches the version-suffixed operationId convention.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread apps/api/src/entrypoints/tests/generate-open-api.e2e.test.ts Outdated
Comment thread apps/api/src/entrypoints/tests/generate-open-api.e2e.test.ts
Comment thread apps/api/src/entrypoints/tests/generate-open-api.e2e.test.ts Outdated
Comment thread apps/api/src/entrypoints/tests/generate-open-api.e2e.test.ts Outdated
Comment thread apps/api/src/entrypoints/generate-open-api.ts Outdated
Comment thread apps/api/src/entrypoints/generate-open-api.ts
Comment thread apps/api/src/modules/swagger/build-api-documentation.ts
G0maa and others added 2 commits May 26, 2026 18:59
Root: cross-cutting REST+OpenAPI overview and the CI drift-check rule.
api: OpenAPI generation + version-suffixed operationId convention.
web: generated types/Zod client, $api+transform call pattern, and which
generated type the FE binds to (the schema body, not operation wrappers).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Reads → useAsyncData + $api wrapped in a per-endpoint composable;
mutations/handlers → imperative $api; useFetch/useAPI are read-only
setup-time variants and an anti-pattern in event handlers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread apps/web/.claude/CLAUDE.md

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
apps/web/.claude/CLAUDE.md (1)

63-69: ⚡ Quick win

Clarify the URL path mismatch between generated types and actual usage.

The guidance states call sites use version-relative paths like /v1/status (line 61), and the example at line 86 shows $api('/v1/status'). However, the generated types (context snippet 2) define url: '/api/v1/status' with the /api prefix included. This mismatch could confuse developers who inspect the generated types and expect to use the literal URL string from the schema.

Add a note explaining that while the OpenAPI document (and generated types) includes the full /api/v1/... path, actual $api calls should omit /api because apiBase already includes it.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/.claude/CLAUDE.md` around lines 63 - 69, The generated types/schemas
(e.g. GetApiInfoResponse, zGetApiInfoResponse from openapi.json) include the
full path prefix "/api/v1/...", but runtime calls use the $api fetch instance
which already applies apiBase (so call sites should use "/v1/..." not
"/api/v1/..."); update the documentation to explicitly state this mismatch and
instruct developers to omit the "/api" prefix when calling $api (and to continue
validating responses with the generated Zod schemas in transform), and mention
$api and apiBase by name so readers can find the fetch plugin and the generated
schemas.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/web/.claude/CLAUDE.md`:
- Line 100: The example in the useFetch invocation incorrectly references a
non-existent local identifier apiBase; update the example to call
useRuntimeConfig().public.apiBase instead so the baseURL is read from runtime
config. Locate the useFetch example (symbol: useFetch<T>('/v1/...', { baseURL:
apiBase, transform })) and replace the baseURL value with
useRuntimeConfig().public.apiBase, ensuring the example imports or assumes
useRuntimeConfig is available in component scope.
- Line 102: The documentation incorrectly states that useAPI is a createUseFetch
instance bound to $api; locate the section referencing useAPI/createUseFetch in
CLAUDE.md and update it to reflect the actual implementation: note that
apps/web/app/plugins/api.ts exposes $api via $fetch.create and that there is no
useAPI or createUseFetch in the repo today — either remove the createUseFetch
claim, mark useAPI as a future/optional idea (not implemented), or reword to
explain that $api exists but no useAPI helper is provided; reference the symbols
useAPI, createUseFetch, $api, and apps/web/app/plugins/api.ts when making the
edit.

---

Nitpick comments:
In `@apps/web/.claude/CLAUDE.md`:
- Around line 63-69: The generated types/schemas (e.g. GetApiInfoResponse,
zGetApiInfoResponse from openapi.json) include the full path prefix
"/api/v1/...", but runtime calls use the $api fetch instance which already
applies apiBase (so call sites should use "/v1/..." not "/api/v1/..."); update
the documentation to explicitly state this mismatch and instruct developers to
omit the "/api" prefix when calling $api (and to continue validating responses
with the generated Zod schemas in transform), and mention $api and apiBase by
name so readers can find the fetch plugin and the generated schemas.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e8f1cd97-f2f9-4e7b-8efb-4fed71fcb904

📥 Commits

Reviewing files that changed from the base of the PR and between c48c2a0 and 911d86e.

📒 Files selected for processing (1)
  • apps/web/.claude/CLAUDE.md

Comment thread apps/web/.claude/CLAUDE.md
Comment thread apps/web/.claude/CLAUDE.md
@G0maa G0maa merged commit cea941f into main May 27, 2026
2 checks passed
G0maa added a commit that referenced this pull request May 27, 2026
* docs: back-fill AgDR-0001 for web↔api communication decision

- Records the REST + OpenAPI + generated types/Zod decision in the
  canonical docs/agdr/ location (first AgDR for marsa)
- Condenses the design spec from PR #33 into the AgDR template:
  context, options considered (tRPC/GraphQL/types-only/SDK), decision,
  consequences, artifacts
- Makes the decision discoverable via the portfolio /agdr search

Refs #11

* fix: formatting
@G0maa G0maa deleted the feat/11-communication-between-api-and-web branch June 6, 2026 11:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Decide on a communication method between WEB/API

1 participant