{"id":29276880,"url":"https://github.com/tracktor/map","last_synced_at":"2026-01-16T16:07:08.052Z","repository":{"id":287009865,"uuid":"963185871","full_name":"Tracktor/map","owner":"Tracktor","description":null,"archived":false,"fork":false,"pushed_at":"2025-07-02T16:09:38.000Z","size":1208,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-02T17:26:01.957Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Tracktor.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-04-09T09:39:22.000Z","updated_at":"2025-07-02T16:09:41.000Z","dependencies_parsed_at":"2025-05-27T22:22:24.402Z","dependency_job_id":"cc1ca08b-3b98-42ba-9c0c-a6b7e22cb3ab","html_url":"https://github.com/Tracktor/map","commit_stats":null,"previous_names":["tracktor/map"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Tracktor/map","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tracktor%2Fmap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tracktor%2Fmap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tracktor%2Fmap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tracktor%2Fmap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Tracktor","download_url":"https://codeload.github.com/Tracktor/map/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Tracktor%2Fmap/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263715508,"owners_count":23500251,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-07-05T09:11:16.105Z","updated_at":"2026-01-16T16:07:08.042Z","avatar_url":"https://github.com/Tracktor.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 🗺️ @tracktor/map\n\nA modern, lightweight React map library built on top of Mapbox GL JS and react-map-gl. Designed for simplicity, flexibility, and visual elegance.\n\nEasily combine markers, routes, GeoJSON features, isochrones, and nearest-point calculations — all with a declarative, type-safe API.\n\n[![npm version](https://img.shields.io/npm/v/@tracktor/map.svg)](https://www.npmjs.com/package/@tracktor/map)\n[![License](https://img.shields.io/badge/license-UNLICENSED-red.svg)](LICENSE)\n\n---\n\n## 🚀 Installation\n```bash\nnpm install @tracktor/map\n```\n\nor\n```bash\nyarn add @tracktor/map\n```\n\nor\n```bash\nbun add @tracktor/map\n```\n\n---\n\n## ⚙️ Requirements\n\n| Dependency | Version | Purpose |\n|------------|---------|---------|\n| `react` | 17+ / 18+ / 19+ | Core React runtime |\n| `react-dom` | 17+ / 18+ / 19+ | React DOM rendering |\n| `mapbox-gl` | ≥3.0.0 | Map rendering engine |\n| `@tracktor/design-system` | ≥4.0.0 | UI theming and components |\n| `@mui/icons-material` | * | Material UI icons |\n| `@mui/x-license` | * | MUI X license integration |\n\n🪶 **You'll also need a Mapbox access token** to render maps. Get one at [mapbox.com](https://account.mapbox.com/access-tokens/).\n\n---\n\n## ✨ Features\n\n✅ **Declarative API** — manage complex map interactions with simple props  \n✅ **Markers \u0026 Popups** — customizable React components or image-based icons  \n✅ **Routing \u0026 Isochrones** — visualize travel-time areas or compute optimal routes  \n✅ **GeoJSON Layers** — render vector data dynamically  \n✅ **Nearest Marker Search** — find and highlight closest points instantly  \n✅ **Type-safe API** — full TypeScript support with smart IntelliSense  \n✅ **Responsive Design** — automatically adapts to any container or screen size  \n✅ **Built for performance** — minimal re-renders, efficient map updates  \n✅ **Multiple Routing Engines** — supports both OSRM (free) and Mapbox Directions API  \n✅ **Flexible Map Styles** — works with Mapbox styles, OpenStreetMap, or custom raster tiles\n\n---\n\n## 🧩 Quick Start\n```tsx\nimport { MapProvider, MarkerMap } from \"@tracktor/map\";\n\nconst markers = [\n    {\n        id: 1,\n        lng: 2.3522,\n        lat: 48.8566,\n        Tooltip: \u003cdiv\u003eParis\u003c/div\u003e,\n        color: \"primary\",\n        variant: \"default\",\n    },\n    {\n        id: 2,\n        lng: -0.1276,\n        lat: 51.5074,\n        Tooltip: \u003cdiv\u003eLondon\u003c/div\u003e,\n        color: \"secondary\",\n        variant: \"default\",\n    },\n];\n\nfunction App() {\n    return (\n        \u003cMapProvider\n            licenseMuiX=\"your-muix-license\"\n            licenceMapbox=\"your-mapbox-token\"\n        \u003e\n            \u003cMarkerMap\n                markers={markers}\n                center={[2.3522, 48.8566]}\n                zoom={5}\n                fitBounds\n                height={500}\n                width=\"100%\"\n                onMapClick={(lng, lat, marker) =\u003e {\n                    console.log(\"Clicked at:\", lng, lat);\n                    if (marker) console.log(\"Marker clicked:\", marker);\n                }}\n            /\u003e\n        \u003c/MapProvider\u003e\n    );\n}\n```\n\n---\n\n## 🧭 Components Overview\n\n### `MapProvider`\n\nWraps your map components and injects required providers (theme, tokens, MUI X license).\n\n**Required Props:**\n- `licenseMuiX` — Your MUI X license key\n- `licenceMapbox` — Your Mapbox access token\n```tsx\n\u003cMapProvider\n    licenseMuiX=\"your-license\"\n    licenceMapbox=\"your-token\"\n\u003e\n    {/* Your map components */}\n\u003c/MapProvider\u003e\n```\n\n### `MapView` / `MarkerMap`\n\nMain map component that handles:\n- Marker rendering with custom icons or React components\n- Interactive popups with hover/click modes\n- Automatic bounds fitting\n- Map click events\n- Responsive container sizing\n\n### Specialized Components\n\n- **`RouteMap`** → Draw routes between two points using OSRM or Mapbox\n- **`IsochroneMap`** → Compute and display travel-time polygons\n- **`FeatureMap`** → Display custom GeoJSON layers with styling\n\n---\n\n## 🧱 Props Reference\n\n### `MapView` Props\n\n#### Core Map Props\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `center` | `LngLatLike \\| number[]` | `[2.3522, 48.8566]` | Initial map center coordinates [lng, lat] |\n| `zoom` | `number` | `5` | Initial zoom level (0-22) |\n| `width` | `string \\| number` | `\"100%\"` | Map container width |\n| `height` | `string \\| number` | `300` | Map container height |\n| `loading` | `boolean` | `false` | Show skeleton loader |\n| `square` | `boolean` | `false` | Enforce 1:1 aspect ratio |\n| `containerStyle` | `SxProps` | `undefined` | Custom MUI sx styles |\n\n#### Map Appearance\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `theme` | `\"light\" \\| \"dark\"` | `\"light\"` | Map color theme |\n| `baseMapView` | `\"street\" \\| \"satellite\"` | `\"street\"` | Base map layer type |\n| `mapStyle` | `string` | - | Custom Mapbox style URL |\n| `projection` | `ProjectionSpecification` | `\"mercator\"` | Map projection system |\n\n#### Interaction Props\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `cooperativeGestures` | `boolean` | `true` | Require modifier key for zoom/pan |\n| `doubleClickZoom` | `boolean` | `true` | Enable double-click to zoom |\n| `onMapClick` | `(lng, lat, marker?) =\u003e void` | - | Callback for map clicks (includes clicked marker if applicable) |\n\n#### Marker Props\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `markers` | `MarkerProps[]` | `[]` | Array of markers to display |\n| `markerImageURL` | `string` | - | Custom marker icon URL |\n| `openPopup` | `string \\| number` | `undefined` | ID of marker with open popup |\n| `openPopupOnHover` | `boolean` | `false` | Open popups on hover instead of click |\n| `popupMaxWidth` | `string` | `\"300px\"` | Maximum popup width |\n\n#### Bounds \u0026 Animation\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `fitBounds` | `boolean` | `true` | Auto-fit map to show all markers |\n| `fitBoundsPadding` | `number` | `0` | Padding (px) around fitted bounds |\n| `fitBoundDuration` | `number` | `500` | Animation duration (ms) |\n| `disableAnimation` | `boolean` | `false` | Disable all animations |\n| `fitBoundsAnimationKey` | `unknown` | - | Change to re-trigger fit bounds |\n\n---\n\n### Marker Props (`MarkerProps`)\n\n| Prop | Type | Required | Description |\n|------|------|----------|-------------|\n| `id` | `string \\| number` | ✅ | Unique marker identifier |\n| `lng` | `number` | ✅ | Longitude coordinate |\n| `lat` | `number` | ✅ | Latitude coordinate |\n| `Tooltip` | `ReactNode` | - | Content for popup/tooltip |\n| `IconComponent` | `React.ComponentType` | - | Custom React icon component |\n| `iconProps` | `object` | - | Props passed to IconComponent |\n| `color` | `string` | - | Marker color (MUI palette) |\n| `variant` | `string` | - | Marker style variant |\n\n**Example with custom icon:**\n```tsx\nimport LocationOnIcon from '@mui/icons-material/LocationOn';\n\nconst marker = {\n  id: 1,\n  lng: 2.3522,\n  lat: 48.8566,\n  IconComponent: LocationOnIcon,\n  iconProps: { fontSize: 'large', color: 'error' },\n  Tooltip: \u003cdiv\u003eCustom Icon Marker\u003c/div\u003e\n};\n```\n\n---\n\n### Itinerary Props (`itineraryParams`)\n\nDraw a route between two points with customizable styling and routing engines.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `from` | `[number, number]` | - | Route starting point [lng, lat] |\n| `to` | `[number, number]` | - | Route ending point [lng, lat] |\n| `profile` | `\"driving\" \\| \"walking\" \\| \"cycling\"` | `\"driving\"` | Transportation mode |\n| `engine` | `\"OSRM\" \\| \"Mapbox\"` | `\"OSRM\"` | Routing service to use |\n| `itineraryLineStyle` | `Partial\u003cItineraryLineStyle\u003e` | `{ color: \"#3b82f6\", width: 4, opacity: 0.8 }` | Route line appearance |\n| `initialRoute` | `Feature\u003cLineString\u003e` | - | Precomputed GeoJSON route |\n| `onRouteComputed` | `(route) =\u003e void` | - | Callback fired when route is computed |\n| `itineraryLabel` | `ReactNode` | - | Label displayed along the route (e.g., \"12 min\") |\n\n**Example:**\n```tsx\n\u003cMapView\n  itineraryParams={{\n    from: [2.3522, 48.8566], // Paris\n    to: [-0.1276, 51.5074],   // London\n    profile: \"driving\",\n    engine: \"OSRM\",\n    itineraryLineStyle: {\n      color: \"#10b981\",\n      width: 5,\n      opacity: 0.9\n    },\n    itineraryLabel: \u003cspan\u003eRoute principale\u003c/span\u003e,\n    onRouteComputed: (route) =\u003e {\n      console.log(\"Route computed:\", route);\n    }\n  }}\n/\u003e\n```\n\n---\n\n### Nearest Marker Search (`findNearestMarker`)\n\nFind and highlight the closest marker to a given point within a maximum distance.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `origin` | `[number, number]` | - | Starting point for search [lng, lat] |\n| `destinations` | `Array\u003c{id, lng, lat}\u003e` | - | Candidate destinations |\n| `maxDistanceMeters` | `number` | - | Maximum search radius in meters |\n| `profile` | `\"driving\" \\| \"walking\" \\| \"cycling\"` | `\"driving\"` | Routing profile for distance calculation |\n| `engine` | `\"OSRM\" \\| \"Mapbox\"` | `\"OSRM\"` | Routing engine to use |\n| `onNearestFound` | `(results) =\u003e void` | - | Callback with all nearest results |\n| `initialNearestResults` | `NearestResult[]` | - | Precomputed nearest results |\n| `itineraryLineStyle` | `Partial\u003cItineraryLineStyle\u003e` | - | Style override for auto-generated itinerary |\n\n**NearestResult Type:**\n```tsx\ninterface NearestResult {\n  id: number | string;\n  point: [number, number]; // [lng, lat]\n  distance: number; // in meters\n  routeFeature?: Feature\u003cLineString\u003e | null;\n}\n```\n\n**Example:**\n```tsx\n\u003cMapView\n  findNearestMarker={{\n    origin: [2.3522, 48.8566],\n    destinations: markers.map(m =\u003e ({ \n      id: m.id, \n      lng: m.lng, \n      lat: m.lat \n    })),\n    maxDistanceMeters: 5000,\n    profile: \"walking\",\n    engine: \"OSRM\",\n    onNearestFound: (results) =\u003e {\n      console.log(`Found ${results.length} markers within range`);\n      results.forEach(r =\u003e {\n        console.log(`Marker ${r.id} at ${r.distance}m`);\n      });\n    }\n  }}\n/\u003e\n```\n\n---\n\n### Isochrone Props (`isochrone`)\n\nCompute and display areas reachable within specific time intervals.\n\n| Prop | Type | Default | Description |\n|------|------|---------|-------------|\n| `origin` | `[number, number]` | - | Center point for isochrone [lng, lat] |\n| `profile` | `\"driving\" \\| \"walking\" \\| \"cycling\"` | `\"driving\"` | Transportation mode |\n| `intervals` | `number[]` | `[5, 10, 15]` | Time intervals in minutes |\n| `onIsochroneLoaded` | `(data) =\u003e void` | - | Callback with GeoJSON result |\n\n**Example:**\n```tsx\n\u003cMapView\n  isochrone={{\n    origin: [2.3522, 48.8566],\n    profile: \"driving\",\n    intervals: [5, 10, 15, 20], // 5, 10, 15, 20 minutes\n    onIsochroneLoaded: (geojson) =\u003e {\n      console.log(\"Isochrone data:\", geojson);\n    }\n  }}\n/\u003e\n```\n\n---\n\n### GeoJSON Features (`features`)\n\nDisplay custom vector features like polygons, lines, or points.\n\n| Prop | Type | Description |\n|------|------|-------------|\n| `features` | `Feature \\| Feature[] \\| FeatureCollection` | GeoJSON data to render |\n\n**Example:**\n```tsx\n\u003cMapView\n  features={{\n    type: \"Feature\",\n    geometry: {\n      type: \"LineString\",\n      coordinates: [\n        [2.3, 48.8],\n        [2.4, 48.9],\n        [2.5, 48.85]\n      ]\n    },\n    properties: {\n      color: \"#ef4444\"\n    }\n  }}\n/\u003e\n```\n\n---\n\n## 🧠 Advanced Use Cases\n\n### 🧭 Real-time GPS Tracking\n```tsx\nfunction LiveTracking() {\n  const [position, setPosition] = useState([2.3522, 48.8566]);\n  \n  useEffect(() =\u003e {\n    const watchId = navigator.geolocation.watchPosition((pos) =\u003e {\n      setPosition([pos.coords.longitude, pos.coords.latitude]);\n    });\n    return () =\u003e navigator.geolocation.clearWatch(watchId);\n  }, []);\n\n  return (\n    \u003cMapView\n      markers={[{\n        id: 'current',\n        lng: position[0],\n        lat: position[1],\n        Tooltip: \u003cdiv\u003eYou are here\u003c/div\u003e\n      }]}\n      center={position}\n      zoom={15}\n      fitBounds={false}\n    /\u003e\n  );\n}\n```\n\n### 🔄 Dynamic Data with React Query\n```tsx\nimport { useQuery } from '@tanstack/react-query';\n\nfunction DynamicMarkers() {\n  const { data: markers } = useQuery({\n    queryKey: ['locations'],\n    queryFn: fetchLocations,\n    refetchInterval: 5000 // Refresh every 5s\n  });\n\n  return (\n    \u003cMapView\n      markers={markers}\n      fitBounds\n      fitBoundsAnimationKey={markers?.length}\n    /\u003e\n  );\n}\n```\n\n### 🎨 Custom Marker Components\n```tsx\nfunction CustomMarker({ isActive, count }) {\n  return (\n    \u003cBox\n      sx={{\n        width: 40,\n        height: 40,\n        borderRadius: '50%',\n        bgcolor: isActive ? 'success.main' : 'grey.500',\n        display: 'flex',\n        alignItems: 'center',\n        justifyContent: 'center',\n        color: 'white',\n        fontWeight: 'bold',\n        border: '2px solid white',\n        boxShadow: 2\n      }}\n    \u003e\n      {count}\n    \u003c/Box\u003e\n  );\n}\n\n\u003cMapView\n  markers={[{\n    id: 1,\n    lng: 2.3522,\n    lat: 48.8566,\n    IconComponent: CustomMarker,\n    iconProps: { isActive: true, count: 5 }\n  }]}\n/\u003e\n```\n\n### 🗺️ Multi-Route Comparison\n```tsx\n\u003cMapView\n  features={[\n    {\n      type: \"Feature\",\n      geometry: {\n        type: \"LineString\",\n        coordinates: route1\n      },\n      properties: { color: \"#3b82f6\" }\n    },\n    {\n      type: \"Feature\",\n      geometry: {\n        type: \"LineString\",\n        coordinates: route2\n      },\n      properties: { color: \"#ef4444\" }\n    }\n  ]}\n/\u003e\n```\n\n### 🎯 Click-to-Add Markers\n```tsx\nfunction InteractiveMap() {\n  const [markers, setMarkers] = useState([]);\n\n  const handleMapClick = (lng, lat) =\u003e {\n    setMarkers(prev =\u003e [...prev, {\n      id: Date.now(),\n      lng,\n      lat,\n      Tooltip: \u003cdiv\u003ePoint {markers.length + 1}\u003c/div\u003e\n    }]);\n  };\n\n  return (\n    \u003cMapView\n      markers={markers}\n      onMapClick={handleMapClick}\n    /\u003e\n  );\n}\n```\n\n### 🚗 Combined Routing \u0026 Nearest Search\n```tsx\nfunction DeliveryMap() {\n  const [origin] = useState([2.3522, 48.8566]);\n  const [destinations] = useState([\n    { id: 1, lng: 2.35, lat: 48.86 },\n    { id: 2, lng: 2.36, lat: 48.85 },\n    { id: 3, lng: 2.34, lat: 48.87 }\n  ]);\n\n  return (\n    \u003cMapView\n      markers={destinations.map(d =\u003e ({\n        id: d.id,\n        lng: d.lng,\n        lat: d.lat,\n        Tooltip: \u003cdiv\u003eDestination {d.id}\u003c/div\u003e\n      }))}\n      findNearestMarker={{\n        origin,\n        destinations,\n        maxDistanceMeters: 10000,\n        profile: \"driving\",\n        engine: \"OSRM\",\n        itineraryLineStyle: {\n          color: \"#22c55e\",\n          width: 4,\n          opacity: 0.8\n        },\n        onNearestFound: (results) =\u003e {\n          console.log(\"Nearest destinations:\", results);\n        }\n      }}\n    /\u003e\n  );\n}\n```\n\n---\n\n## 💡 Tips \u0026 Best Practices\n\n### Performance Optimization\n\n- **Memoize marker data** to prevent unnecessary re-renders\n- **Use `fitBoundsAnimationKey`** to control when bounds recalculate\n- **Disable animations** for large datasets: `disableAnimation={true}`\n- **Debounce dynamic updates** when tracking real-time data\n- **Use `initialRoute` and `initialNearestResults`** to avoid redundant API calls\n\n### UX Improvements\n\n- Combine `openPopupOnHover` and `disableAnimation` for smooth interactions\n- Use `fitBoundsPadding` to ensure markers aren't at screen edges\n- Set appropriate `popupMaxWidth` for mobile responsiveness\n- Provide visual feedback with custom `IconComponent` states\n- Use `itineraryLabel` to display route duration or distance\n\n### Routing Best Practices\n\n- **Use OSRM** (free) for basic routing needs\n- **Use Mapbox** for production apps requiring SLA and support\n- Cache route results with `initialRoute` to minimize API calls\n- Handle network errors gracefully with `onRouteComputed` callback\n- Combine `findNearestMarker` with `itineraryParams` for optimal routing workflows\n\n---\n\n## 🧑‍💻 Development\n\n### Prerequisites\n\n- **Bun** ≥1.1.0 (recommended) or Node.js 18+\n- Git\n\n### Setup\n```bash\n# Clone the repository\ngit clone https://github.com/tracktor-tech/tracktor-map.git\ncd tracktor-map\n\n# Install dependencies\nbun install\n\n# Start development sandbox\nbun run sandbox\n# or\nbun run dev:sandbox\n```\n\n### Available Scripts\n\n| Command | Description |\n|---------|-------------|\n| `bun run sandbox` | Start interactive development playground |\n| `bun run build` | Build library for production |\n| `bun run build:sandbox` | Build sandbox demo site |\n| `bun run deploy:sandbox` | Deploy sandbox to GitHub Pages |\n| `bun run lint` | Check code quality and types |\n| `bun run lint:fix` | Auto-fix linting issues |\n| `bun run test` | Run test suite |\n| `bun run test:watch` | Run tests in watch mode |\n| `bun run version` | Bump version with changelog |\n| `bun run release` | Build and publish to npm |\n\n### Project Structure\n```\n@tracktor/map/\n├── src/\n│   ├── components/       # Reusable map and UI components (Marker, Popup, etc.)\n│   ├── constants/        # Shared configuration values and styling constants\n│   ├── context/          # React context providers (e.g. map state)\n│   ├── features/         # Core map features (routes, isochrones, nearest, etc.)\n│   ├── services/         # External APIs and utility services\n│   ├── types/            # TypeScript interfaces and types\n│   ├── utils/            # Generic helpers and formatting functions\n│   └── main.ts           # Library entry point\n│\n├── sandbox/              # Development playground (example app \u0026 live demos)\n│   ├── context/          # Demo context providers\n│   ├── examples/         # Interactive usage examples\n│   ├── features/         # Components used in the docs/demo\n│   ├── public/           # Static assets (images, previews, etc.)\n│   ├── App.tsx           # Sandbox root component\n│   └── index.tsx         # Sandbox entry file\n│\n└── test/                 # Unit and integration tests\n```\n\n### Testing\n```bash\n# Run all tests\nbun test\n\n# Watch mode\nbun test:watch\n\n# Run specific test file\nbun test src/components/MapView.test.tsx\n```\n\n### Contributing\n\nWe welcome contributions! Please:\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/amazing-feature`)\n3. Make your changes\n4. Run tests and linting (`bun run test \u0026\u0026 bun run lint`)\n5. Commit your changes (`git commit -m 'Add amazing feature'`)\n6. Push to the branch (`git push origin feature/amazing-feature`)\n7. Open a Pull Request\n\n**Code Style:**\n- Follow existing patterns and conventions\n- Use TypeScript for all new code\n- Add tests for new features\n- Update documentation as needed\n\n---\n\n## 📘 Documentation \u0026 Examples\n\nExplore interactive examples and comprehensive API documentation:\n\n👉 **[Live Documentation \u0026 Sandbox](https://tracktor.github.io/map)**\n\nThe sandbox includes:\n- Interactive code examples\n- Live preview of all features\n- Copy-paste ready snippets\n- API reference with search\n\n---\n\n## 📦 Publishing \u0026 Deployment\n\n### Publish to npm\n```bash\n# Update version and generate changelog\nbun run version\n\n# Build and publish\nbun run release\n```\n\n### Deploy Sandbox to GitHub Pages\n```bash\nbun run deploy:sandbox\n```\n\nThis will:\n1. Build the sandbox with production optimizations\n2. Generate a 404.html for client-side routing\n3. Push to the `gh-pages` branch\n4. Update the live documentation site\n\n---\n\n## 🔧 Troubleshooting\n\n### Common Issues\n\n**Map not rendering:**\n- Verify your Mapbox token is valid\n- Check browser console for errors\n- Ensure mapbox-gl CSS is imported\n\n**TypeScript errors:**\n- Run `bun install` to update type definitions\n- Check peer dependency versions match\n\n**Performance issues:**\n- Reduce marker count or use clustering\n- Disable animations for large datasets\n- Memoize marker data\n- Use `initialRoute` and `initialNearestResults` for cached data\n\n**Routing not working:**\n- Verify coordinates are in [lng, lat] format (not lat, lng)\n- Check that routing engine is accessible\n- Ensure profile matches your use case\n- Verify maxDistanceMeters is reasonable for nearest search\n\n### Getting Help\n\n- 📖 Check the [documentation](https://github.com/Tracktor/map)\n- 🐛 [Report bugs](https://github.com/tracktor-tech/tracktor-map/issues)\n- 💬 Join discussions in GitHub Discussions\n\n---\n\n## 📄 License\n\n**UNLICENSED** — This package is proprietary software.  \n© [Tracktor — Kevin Graff]\n\n---\n\n## 🧭 Links\n\n- 📦 **npm**: [@tracktor/map](https://www.npmjs.com/package/@tracktor/map)\n- 💻 **GitHub**: [@tracktor/map](https://github.com/Tracktor/map)\n- 🌐 **Docs**: [tracktor.github.io/map](https://tracktor.github.io/map)\n- 🎨 **Design System**: [@tracktor/design-system](https://www.npmjs.com/package/@tracktor/design-system)\n- Sandbox Demo: [tracktor.github.io/map/sandbox](https://tracktor.github.io/map)\n\n---\n\n## 🙏 Acknowledgments\n\nBuilt with:\n- [Mapbox GL JS](https://docs.mapbox.com/mapbox-gl-js/) — Powerful map rendering\n- [react-map-gl](https://visgl.github.io/react-map-gl/) — React wrapper for Mapbox\n- [OSRM](http://project-osrm.org/) — Free routing engine\n- [@tracktor/design-system](https://www.npmjs.com/package/@tracktor/design-system) — UI components","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftracktor%2Fmap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftracktor%2Fmap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftracktor%2Fmap/lists"}