Guidance for Claude Code (claude.ai/code) working with code in this repository.
VizzJson — JSON templating system for geospatial visualization using @@ prefix convention. Enables parameterized MapLibre/deck.gl map configs with live resolution. Built as internal Vizzuality showcase.
pnpm dev # Dev server on :3000
pnpm build # Production build
pnpm test # Run all tests once (vitest run)
pnpm test:watch # Tests in watch mode
pnpm test -- tests/lib/converter/functions.test.ts # Single test file
pnpm lint # ESLint check
pnpm format # Prettier check
pnpm check # Auto-fix lint + formatting
pnpm typecheck # TypeScript type checking (tsc --noEmit)Framework: TanStack Start (full-stack React) with file-based routing, TanStack Query, React 19, Tailwind CSS v4, shadcn/ui components.
Heart of project — two-stage JSON resolution pipeline:
- Params resolution (
params-resolver.ts) — Resolves@@#params.Xrefs against runtime param values. Returns immutable copies. - deck.gl conversion (
converter-config.ts) — Passes resolved JSON to deck.glJSONConverterhandling@@function:,@@type:,@@=[], and@@#GL.prefixes.
Entry point: resolveConfig(config, params) in index.ts.
Prefix convention:
@@#params.opacity— Runtime param ref (dot notation for nesting)@@function:setQueryParams— Call registered function@@type:ScatterplotLayer— Instantiate deck.gl layer or React component@@=[expression]— Evaluate JS expression@@#GL.POINTS— OpenGL constant
src/lib/converter/— Core resolution enginesrc/lib/param-inference.ts— Auto-detects UI control type (slider, color picker, switch, select, etc.) from param configsrc/lib/types.ts— Core types:LayerSchema,ParamConfig,LegendConfig,ExampleConfigsrc/hooks/use-converter.ts— React hook wrappingresolveConfig()with error handlingsrc/examples/— 10 progressive JSON configs (basic → advanced) demonstrating@@conventionsrc/components/playground/— Interactive editor: Monaco JSON editor, param controls, map renderer, legend panelsrc/components/landing/— Marketing landing page sectionssrc/components/legends/— Legend React components registered in converter
/— Landing page/playground— Main interactive editor (hides header/footer)/demo/*— Demo pages (table, tanstack-query, orpc-todo, i18n)
src/paraglide/— i18n runtime (generated by Paraglide)src/routeTree.gen.ts— Route tree (generated by TanStack Router)
- No semicolons, single quotes, trailing commas (
prettier.config.js) - Path aliases:
#/*and@/*both resolve to./src/* - TypeScript strict mode, ES2022 target
- shadcn/ui with
base-novastyle and lucide icons
Vitest with jsdom environment. Tests in tests/ mirror src/ structure. Core converter logic has full test coverage — params resolution, function calls, immutability verification, nested object/array handling.
Plans and specs from superpowers skills saved under .superpowers/ instead of default docs/superpowers/:
- Plans:
.superpowers/plans/YYYY-MM-DD-<feature-name>.md - Specs:
.superpowers/specs/YYYY-MM-DD-<topic>-design.md
User edits JSON → debounce 300ms → parse → extract params_config → render param controls → user adjusts params → resolveParams() (stage 1) → JSONConverter (stage 2) → map renders + legend resolves.
Project-scoped skills live in .claude/skills/ and auto-discover via session init — no need to invoke explicitly. Preferred stack skills for this repo: shadcn (base-nova), Tailwind v4, TanStack Start/Router/Query, Vitest, pnpm, accessibility.
Issues live as markdown files under .scratch/<feature>/. See docs/agents/issue-tracker.md.
Canonical defaults (needs-triage, needs-info, ready-for-agent, ready-for-human, wontfix) applied as Status: lines in issue files. See docs/agents/triage-labels.md.
Single-context: CONTEXT.md at root, docs/adr/ for ADRs. See docs/agents/domain.md.
Monorepo with three packages. Root is the main TanStack Start web app. Internal packages are @vizzuality/vizz-json (core JSON templating engine) and @vizzuality/vizz-map (MapLibre rendering primitives).
default (TanStack Start app)
- framework:
@tanstack/react-start,@tanstack/react-router,react@19,react-dom@19 - state:
@tanstack/react-query,@tanstack/ai,@tanstack/ai-openai,@tanstack/ai-react - forms-validation:
zod - ui:
shadcn@4,@base-ui/react,lucide-react - styling:
tailwindcss@4,@tailwindcss/vite,tailwind-merge,class-variance-authority - maps:
react-map-gl,maplibre-gl,@maplibre/maplibre-gl-style-spec,@mapbox/mapbox-gl-style-spec - editor:
@monaco-editor/react - theme:
next-themes - ui-extras:
sonner(toasts),react-resizable-panels(draggable layout),@dnd-kit/*(drag-drop) - database:
dexie,dexie-react-hooks - i18n:
@inlang/paraglide-js - compiler:
babel-plugin-react-compiler
packages/vizz-json
- core: Zod-free JSON templating engine; optional React export
- devOnly:
vitest
packages/vizz-map
- react-integration: React wrappers for vizz-json + react-map-gl
- devOnly:
vitest,@testing-library/react
packages/vizz-figma-map
- figma-plugin: Renders vizz-json maps, snapshots to Figma
- deps:
@vizzuality/vizz-json,@vizzuality/vizz-map,react@19,maplibre-gl,react-map-gl - devOnly:
@figma/plugin-typings,vite,vitest,concurrently