This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Browser-based OpenTibia map editor targeting Tibia 15.00+ client data (protobuf data format). Built with React 19, PixiJS 8, TypeScript, Vite, and Tailwind CSS 4. Renders and edits OTBM map files using sprite data from the Tibia client.
- Dev server:
npm run dev(Vite dev server, servesdata/andtibia/as public) - Build:
npm run build(runstsc -b && vite build) - Lint:
npm run lint(ESLint) - Protobuf codegen:
npm run proto(requires Docker — generatessrc/proto/appearances.ts) - Test:
npm test(Vitest, runs allsrc/**/*.test.tsfiles) - Test watch:
npm run test:watch(Vitest in watch mode) - Test single file:
npx vitest run src/lib/Camera.test.ts - Test coverage:
npm run test:coverage(uses@vitest/coverage-v8)
OTBM map file -> appearances.dat (protobuf) -> catalog-content.json -> sprite sheets (.bmp.lzma) -> items.xml
Key: Server ID = Client ID in v15.00+ (no items.otb mapping needed).
loadAssets() orchestrates startup: PixiJS app init -> sprite catalog -> appearances -> items.xml -> brush/material XML -> tilesets -> OTBM map parse. Returns InitResult consumed by setupEditor() which creates the MapRenderer and MapMutator. Initial camera position: first town's temple → map center (width/2, height/2) for loaded OTBM without towns → 1024/1024/7 for new empty maps.
- MapRenderer — PixiJS rendering engine. Manages Camera, ChunkManager, FloorManager, TileRenderer, SelectionOverlay, LightEngine. Handles multi-floor rendering with diagonal offset (RME-style).
- MapMutator — All map mutations (place/remove items, undo/redo, copy/paste, fill, border/randomize). Classifies items into draw layers: ground, bottom, common, top.
- Camera — Viewport position, zoom, floor navigation.
- ChunkManager — Spatial index for tiles grouped into chunks for efficient rendering.
- TileRenderer — Renders individual tiles using sprite data from TextureManager/SpriteResolver.
- FloorManager — Multi-floor visibility and transparency.
- otbm.ts — Binary OTBM parser/serializer.
- appearances.ts — Protobuf appearance data loader.
- items.ts — Item registry from items.xml.
XML-based brush definitions loaded from data/materials/. Types: ground brushes (with borders), wall brushes, carpet/table brushes, doodad brushes. BrushRegistry is the central lookup. Border/wall/carpet systems handle auto-tiling.
Editor tools: selectTool, drawTool, eraseTool, fillTool, doorTool. Each implements pointer event handlers. Managed by useEditorTools hook.
- App.tsx — Root component, manages all state and panel visibility.
- Toolbar.tsx — Top toolbar with tool buttons and hamburger menu.
- HamburgerMenu.tsx — Main menu with all operations and keyboard shortcuts.
- Inspector — Tile item inspector panel.
- BrushPalette / ItemPalette — Brush and raw item selection panels.
- FindItemDialog / ReplaceItemsDialog — Search and replace across map.
tibia/— Client assets (appearances.dat, catalog-content.json, sprite sheets). Served as Vite publicDir.data/materials/— Brush/tileset XML definitions (borders, brushes, tilesets).data/items.xml— Item names and properties.
vendor/otclient— C++ reference for protobuf/sprite/OTBM parsingvendor/remeres-map-editor— C++ reference for editor UX, brush systems, OTBM I/Ovendor/canary— Server-side item handling, map data
- Always write tests for new features and changes
- Write tests that test behaviors, not implementation details
- Use AAA (Arrange, Act, Assert) pattern for writing tests
src/proto/appearances.tsis generated from a proto file — do not write tests for itsrc/lib/appearances.tsis thin glue (fetch + decode + build maps) — does not need unit tests
Lower Z = higher elevation: Z=0 is sky, Z=7 is ground level, Z=8-15 is underground. "Upper floors" have lower Z numbers.
Uses RME convention: items render in forward array order (last item drawn on top). This differs from OTClient which reverses common items. OTBM export will need order translation.
A precision instrument shell. Dark steel frame, warm amber highlights. The map viewport is king — UI stays compact and out of the way.
- Content-first — maximize viewport, minimize chrome. No unnecessary panels or decorations.
- Information-dense — pack data tight with clear hierarchy. Use label/value pattern (uppercase condensed labels, monospace values).
- Warm on cold — amber/gold accents (
#d4a549) on cool dark surfaces. Evokes torchlight on stone — ties to Tibia's fantasy theme. - Crisp precision — small radii (3-7px), pixel-aligned edges. No bubbly soft rounding. This is a tool, not a toy.
- Layered depth — frosted glass panels (
backdrop-filter: blur), subtle shadows, elevation through opacity. Panels let the map bleed through.
- UI text: Barlow (400/500/600/700)
- Labels: Barlow Condensed, uppercase, wide tracking, tertiary color
- Data values: JetBrains Mono, primary color
- Accent values: JetBrains Mono,
--accent-textcolor - Base size: 12px. Keep UI text small and dense.
- Backgrounds:
--bg-void(#07070a) through--bg-active(#26262f) - Glass panels:
--glass-bg(rgba 82% opacity) with 12px blur - Text:
--text-primary(#e4e2de),--text-secondary(#908d85),--text-tertiary(#5c5a54) - Accent:
--accent(#d4a549) — warm amber/gold - Semantic:
--danger(#c44040),--success(#4a9e6a),--info(#5b9fd4)
- Use
.panelclass for overlay containers (frosted glass) - Use
.btn/.btn-iconfor buttons - Use
.label+.valuefor data display - Use
.separator/.separator-vfor visual dividers - Use
.kbdfor keyboard shortcut hints
All CSS variables and base classes: src/styles/theme.css
- All tools, views, and map operations must have entries in the hamburger menu (
src/components/Toolbar.tsx->menuSections) — not just keyboard shortcuts or context menu items.
- Don't copy code — if you need to write it twice, extract it into a shared utility, hook, or component.
- When writing diagrams in Markdown files, always use Mermaid syntax (```mermaid code blocks).