You are working as an SDK contributor on the TomTom Maps SDK for JavaScript monorepo.
AGENTS.md files are the cross-tool source of truth for contributor guidance in this repo (architecture, commands, conventions, workflows). This skill orients you to them — do not restate or duplicate their content here.
Orientation steps
Always read the root
AGENTS.mdfirst for architecture, build order, dev commands, conventions, and key files.Read the package-specific
AGENTS.mdfor the area you're touching:If the task touches… Read core/core/AGENTS.mdmap/map/AGENTS.mdservices/services/AGENTS.mdexamples/examples/AGENTS.md(andexamples/E2E_TESTING.mdfor test work)map-integration-tests/map-integration-tests/AGENTS.mdplugins/(any)plugins/AGENTS.mdplugins/agent-toolkit/plugins/agent-toolkit/AGENTS.md+plugins/agent-toolkit/ENGINEERING-GUIDELINES.mdplugins/viewport-places/plugins/AGENTS.md(no dedicated AGENTS.md; seesrc/viewportPlaces.ts)plugins/landmarks-3d/plugins/AGENTS.md(no dedicated AGENTS.md; seesrc/Landmarks3D.ts)shared-configs/shared-configs/AGENTS.mddocumentation/documentation/AGENTS.mddocumentation/docs-portal/documentation/docs-portal/AGENTS.md(guide writing withSDKGuideLiveCodingExample)If the area is unclear, read all package-level
AGENTS.mdfiles before acting.Before you write code, silently confirm you're in contributor mode with these easy-to-violate rules top-of-mind:
- Biome for formatting/linting (not ESLint or Prettier). Run
pnpm lintfrom root. - pnpm for package management; shared version pins live in
pnpm-workspace.yamlundercatalog:. - Vitest for unit tests; place tests in
tests/subdirectories next to source. - Strict TypeScript — no
any, no unnecessary casts. - Coordinates: always
[longitude, latitude](GeoJSON order) — easy to get wrong. - Full variable names —
responsenotres,parametersnotparams,errornoterr,configurationnotconfig, etc. (full list in rootAGENTS.md). - Arrow functions over
functiondeclarations; omit braces/returnfor single-expression one-liners. - No re-exports — import directly from canonical source, never barrel-forward.
- Blank line after single-line
if— Biome does not enforce; apply manually. - Map modules: get instances via
await SomeModule.get(map), nevernew SomeModule(). - Tool
executein plugins must catch and return{ error: string }, never throw. - Build order is strict:
core→services+map. Never importmapfromservicesor vice versa. - Example E2E tests need
dist/: everypnpm test:e2e[:update-snapshots](per-example or viapnpm e2e-test:examples:update-snapshot <name>/pnpm generate-thumbnails:examples <name>from root) requirespnpm -F map build+pnpm -F @examples/<name> buildfirst — the Playwright server servesdist/, not the dev server. Skipping the build silently uses stale assets. - New examples must ship both
e2e-tests/snapshots/upon-load.png(frompnpm test:e2e:update-snapshots) andcontent/thumbnail.png(derived viapnpm generate-thumbnails:examples <name>). Commit both.
- Biome for formatting/linting (not ESLint or Prettier). Run
After every change
Always run both of these from the repo root after editing any source file, before reporting the task as complete:
pnpm lint:fix
pnpm format:fix
lint:fix runs Biome's check+lint with --write; format:fix runs Biome's formatter with --write. If lint:fix exits non-zero, fix the reported errors (warnings about pre-existing complexity/non-null-assertions in unrelated files are not blocking — only address what your change introduced or what Biome flags as an error).
Cross-file consistency check (before pushing)
Most automated review nags come from references that drift between code, exports, tests, and docs. Before pushing, do a quick sweep matched to the kind of change you just made.
Renamed or removed a public symbol — start with git grep -l '<oldName>' from the repo root, then walk the hits across:
- the package's own
src/**(registries, barrels, schemas, tests, mocks, fixtures) examples/**(entry points, hooks, eval cases, tests, snapshots)documentation/docs-portal/guides/**— bothnavigation.ymland every.mdxunder the affected guide.claude/skills/**— skill descriptions list trigger keywords by symbol name and go stale silently
Replace every hit. If the rename also changed semantics (not just the name), re-read the touched code so descriptions, JSDoc, and guides still match the actual runtime behavior — they go stale silently.
Changed a public type shape (default generic, exported interface, output schema) — also:
- update the JSDoc
@typeParam/ property docs to match the actual default and shape (a common review nag is "JSDoc says X but signature says Y") - decide whether downstream consumers need a deprecated alias or a major-version bump (see
.release-please-manifest.json)
Added external-resource fetching — confirm bounded handling: explicit protocol allowlist, AbortController timeout, streamed size cap. Don't trust new URL alone.
Package-specific extras — when a package's own AGENTS.md lists "after adding X, also touch Y" rules (e.g. plugins/agent-toolkit/AGENTS.md for new state slices or registered tools), follow those as well. The root-level checks above don't replace them.
When to branch off this skill
- Building an SDK consumer app (not editing SDK source) → use the
tomtom-maps-sdk-jsskill instead. - Writing or editing customer-facing guides → follow
documentation/docs-portal/AGENTS.md. - Working on the agent-toolkit plugin →
ENGINEERING-GUIDELINES.mdis required reading before touching tools, state, or system prompts.