🔑 1. Shared Library / Package (most common)
You create a third package (could be private NPM, Maven/Gradle module, or a Git submodule) that only contains:
Path builders (functions for creating URLs consistently).
Shared enums, constants, or type definitions.
Maybe request/response type schemas (if you’re using TypeScript, protobufs, or OpenAPI).
Frontend and backend both import this package, so paths stay in sync.
✅ Pros: Single source of truth, versioned, works well in monorepo or polyrepo.
❌ Cons: Extra setup (publishing or linking the package), version drift if not maintained.
🔑 2. Contract-First API (OpenAPI / GraphQL)
Define your API paths in OpenAPI (Swagger) or GraphQL schema.
Use codegen to generate:
Backend routes/stubs.
Frontend clients/types.
You don’t hand-write paths in either app; they’re generated.
✅ Pros: Strong guarantees, no drift, future-proof.
❌ Cons: Steeper learning curve, requires tooling.
🔑 3. Environment Variable Convention
Instead of a third app, keep env vars standardized across front/back:
API_BASE_URL
USER_PATH=/users
ORDER_PATH=/orders
Both apps construct final paths from these envs.
Works best if you use dotenv templates that are synced (e.g., .env.common checked into repo).
✅ Pros: Easy to implement, no extra repo.
❌ Cons: Can get messy if paths are more complex or logic-heavy.
🔑 4. Centralized Config Service (overkill for small apps)
A dedicated service (your “third app” idea) exposes config over HTTP.
Frontend and backend fetch paths/config at startup.
Rare outside very large orgs (where dozens of services need shared config).
✅ Pros: Centralized, dynamic, can update paths without redeploys.
❌ Cons: Adds another moving part, often unnecessary unless you’re at scale.
🔑 1. Shared Library / Package (most common)
You create a third package (could be private NPM, Maven/Gradle module, or a Git submodule) that only contains:
Path builders (functions for creating URLs consistently).
Shared enums, constants, or type definitions.
Maybe request/response type schemas (if you’re using TypeScript, protobufs, or OpenAPI).
Frontend and backend both import this package, so paths stay in sync.
✅ Pros: Single source of truth, versioned, works well in monorepo or polyrepo.
❌ Cons: Extra setup (publishing or linking the package), version drift if not maintained.
🔑 2. Contract-First API (OpenAPI / GraphQL)
Define your API paths in OpenAPI (Swagger) or GraphQL schema.
Use codegen to generate:
Backend routes/stubs.
Frontend clients/types.
You don’t hand-write paths in either app; they’re generated.
✅ Pros: Strong guarantees, no drift, future-proof.
❌ Cons: Steeper learning curve, requires tooling.
🔑 3. Environment Variable Convention
Instead of a third app, keep env vars standardized across front/back:
API_BASE_URL
USER_PATH=/users
ORDER_PATH=/orders
Both apps construct final paths from these envs.
Works best if you use dotenv templates that are synced (e.g., .env.common checked into repo).
✅ Pros: Easy to implement, no extra repo.
❌ Cons: Can get messy if paths are more complex or logic-heavy.
🔑 4. Centralized Config Service (overkill for small apps)
A dedicated service (your “third app” idea) exposes config over HTTP.
Frontend and backend fetch paths/config at startup.
Rare outside very large orgs (where dozens of services need shared config).
✅ Pros: Centralized, dynamic, can update paths without redeploys.
❌ Cons: Adds another moving part, often unnecessary unless you’re at scale.