Skip to content
| Marketplace
Sign in
Visual Studio Code>Other>TS-REST NavNew to Visual Studio Code? Get it now.
TS-REST Nav

TS-REST Nav

Stephen Paul

|
1 install
| (0) | Free
Navigate between ts-rest contracts, handlers, services, schemas, and frontend call sites — without JSDoc links.
Installation
Launch VS Code Quick Open (Ctrl+P), paste the following command, and press enter.
Copied to clipboard
More Info

TS-REST Nav

Navigate between ts-rest contracts, handlers, services, schemas, and client call sites using predictable folder naming under roots you configure.


Minimum requirements

This extension helps when your project already has something like:

  • Separate trees for contracts, HTTP handlers, and service logic (or at least distinct filename patterns in shared folders)
  • Names that line up across layers — same operation name on the contract, handler export, service function, and client call when possible
  • ts-rest with shared contract files that declare your HTTP routes (the extension links each route to its handler, service, and callers)

Optional, but needed for the fuller hop set:

  • A stable client API prefix (e.g. getRestApi().employees.listEmployees())
  • A server services namespace in handlers (e.g. ServerServices.employees.listEmployees)
  • Colocated schema files next to contracts (for the Schema lens)

If you don’t use ts-rest or your routes aren’t declared in shared contract files, this won’t add much.


⚠️ GETTING STARTED

Point the extension at your contracts, handlers, and services folders — once those roots are set, CodeLens and navigation light up. We don’t assume a default directory structure, because every repo puts these in different places.

1. Install

Install TS-REST Nav from the VS Code / Cursor marketplace, then reload the window if prompted.

2. Add workspace settings (required)

Add this to your workspace settings (.vscode/settings.json, or the "settings" block in a *.code-workspace file), then reload:

{
  "tsrest.nav.contractsRoots": ["shared/api"],
  "tsrest.nav.handlersRoot": "server/api",
  "tsrest.nav.servicesRoot": "server/services",
  "tsrest.nav.contractsGlob": "**/shared/api/**/*.contracts.ts",
  "tsrest.nav.handlersGlob": "**/server/api/**/*.{ts,js}",
  "tsrest.nav.clientGlobs": [
    "**/web/**/*.{ts,tsx}",
    "**/mobile/**/*.{ts,tsx}"
  ],
  "tsrest.nav.clientApiExpressions": ["getRestApi()"],
  "tsrest.nav.serverServicesExpression": "ServerServices"
}
  • *Root paths are relative to the repo root (the directory that contains those folders). Include a packages/ prefix only if your folders actually live under packages/.
  • Globs are normal VS Code workspace globs.
  • Adjust paths/expressions to match your repo.
  • Optional: override filename templates with contractFilePattern, handlerFilePattern, and serviceFilePattern (see below).

3. Confirm it works

Open a *.contracts.ts route key (e.g. listEmployees:). You should see CodeLens: API · Service · Schema · Call sites.

If nothing appears, see Troubleshooting.


What it does

Location CodeLens
Contract route key listEmployees: API · Service · Schema · Call sites
API listEmployeesApi Contract · Service · Call sites
Service export async function listEmployees Contract · API · Call sites
Client getRestApi().employees.listEmployees() Service · API · Contract

Cmd/Ctrl-click and TS-REST Nav: Go to Related work from the same places.

Prefer matching names across layers (listEmployees everywhere). If a handler calls a differently named service method, the extension warns (Service ⚠ + Problems panel).

Directory structure (under your configured roots)

More detail: docs/directory-structure.md. Naming across layers: docs/naming.md.

Default filename templates (configurable):

Layer Setting Default
Contract tsrest.nav.contractFilePattern {area}.contracts.ts
Handler tsrest.nav.handlerFilePattern {op}.api.ts
Service tsrest.nav.serviceFilePattern {area}.service.ts

Placeholders: {area} (kebab area id), {op} (kebab operation id). A .js twin is also tried when the pattern ends in .ts.

Flat area (folder name = router area):

{contractsRoot}/[audience]/<area>/<area>.contracts.ts
{handlersRoot}/[audience]/<area>/<op-kebab>.api.ts
{servicesRoot}/<area>/<area>.service.ts

Nested domain group (router key from the contracts file stem):

{contractsRoot}/…/<domain>/get-<area>/<area>.contracts.ts
{handlersRoot}/…/<domain>/<op-kebab>.api.ts
{servicesRoot}/<domain>/<area>.service.ts

[audience] is optional — see tsrest.nav.audiences below. Router key = camelCase of the area (employees → employees). Handlers and services may share one directory if filenames differ.

Settings reference

Setting Default Description
tsrest.nav.contractsRoots [] Required. Contract tree roots
tsrest.nav.handlersRoot "" Required. Handler tree root
tsrest.nav.servicesRoot "" Required. Service tree root
tsrest.nav.contractsGlob **/*.contracts.ts Contract search fallback
tsrest.nav.handlersGlob **/*.api.ts Handler search fallback
tsrest.nav.clientGlobs [] Client call-site globs
tsrest.nav.clientApiExpressions getRestApi(), … Client call prefixes
tsrest.nav.serverServicesExpression ServerServices Handler→service call namespace
tsrest.nav.audiences private/public/internal Optional top-level API-surface folders (not feature areas). Set [] if you don’t use them.
tsrest.nav.contractFilePattern {area}.contracts.ts Contract filename template
tsrest.nav.handlerFilePattern {op}.api.ts Handler filename template
tsrest.nav.serviceFilePattern {area}.service.ts Service filename template
tsrest.nav.warnNameMismatch true Warn on service/route name mismatch
tsrest.nav.enabled true Master switch
tsrest.nav.showCodeLens true CodeLens on route keys

Troubleshooting

CodeLens never appears / status bar says configure roots

  • Confirm tsrest.nav.contractsRoots, handlersRoot, and servicesRoot are set and non-empty.
  • Reload the window after changing settings.

Multi-root workspace

  • Put tsrest.nav.* in the *.code-workspace "settings" block.
  • A folder’s .vscode/settings.json only applies to that folder — not sibling roots.
  • A workspace file does not inherit root .vscode/settings.json.

Gitignored *.local.code-workspace

  • If you copy a shared workspace file into a personal *.local.code-workspace, copy the tsrest.nav settings block too. Otherwise lenses disappear with no error.

Develop (extension authors)

npm install
npm test
npm run install-extension   # symlinks into ~/.cursor/extensions

Then Developer: Reload Window.

License

MIT

  • Contact us
  • Jobs
  • Privacy
  • Manage cookies
  • Terms of use
  • Trademarks
© 2026 Microsoft