# Tint
> Tint turns the embedded map on a website into an on-brand asset. A map is designed visually in the Tint Studio (theme, brand color, pins, opening hours), published, and embedded with one line of HTML. Maps render with MapLibre GL from https://embed.tintmap.dev and are domain-locked, lazy-loaded, and carry automatic OpenStreetMap attribution.
This file is for AI agents and LLMs (Cursor, Claude, Copilot, v0, etc.). It explains how Tint works and exactly how to implement a Tint map on a website.
## How it works
- A map is created and themed in the Tint Studio (no-code) at https://tintmap.dev, then published.
- Every published map has a stable public ID shaped like `m_ab12cd34`. You can find it on the map's publish screen or in the dashboard.
- To put a map on a page you only need its ID plus one embed snippet. The map itself is served from the embed origin: https://embed.tintmap.dev
- Embeds are domain-locked (the site's domain must be allow-listed in the Tint dashboard), lazy-loaded, and include OpenStreetMap attribution that must remain visible.
- Free-plan maps display a small "Made with Tint" badge; paid plans can remove it.
## Implementing a map (pick ONE method)
Replace `MAP_ID` with a real published map ID (e.g. `m_ab12cd34`).
### 1. Script tag — simplest, auto-injects a responsive iframe
```html
```
### 2. iframe — fully isolated, no JavaScript
```html
```
### 3. React
```jsx
import { TintMap } from '@tint/react';
export default function Map() {
return ;
}
```
### 4. Web Component
```html
```
## Styling: make the map match the website (this is the whole point of Tint)
Tint's value is that the map looks like part of the site instead of a generic grey Google Map. If you know the site's look — its background, its primary/brand color, and whether it is light or dark — you can generate a map that matches it. Styling is set in the map config (the Studio, or the `theme` / `brand` / `custom` fields of `POST /v1/maps`). There are three approaches, and they combine:
### 1. Brand-match — one color becomes a whole palette (best for LIGHT sites with a brand color)
Set `theme: "brand"` and `brand: "#RRGGBB"` to the site's primary brand color. Tint derives a coherent LIGHT map palette (land, water, roads, labels) harmonised around that one color.
```json
{ "theme": "brand", "brand": "#7C3AED", "center": [40.71, -74.0], "zoom": 12 }
```
### 2. Preset theme — pick the closest vibe (best for DARK sites, or a specific aesthetic)
Set `theme` to one of the preset ids. Pick a `dark:true` theme for a dark website, a light one for a light site. The `brand` hex still colors the pins.
- Light: `minimal` (clean neutral), `pastel` (soft), `terrain` (green/outdoors), `vintage` (warm print), `mono` (greyscale), `sand` (desert warm), `mint` (fresh green), `candy` (playful bright), `accessible` (high-contrast/WCAG).
- Dark: `midnight` (navy, dashboards), `blueprint` (cyan on ink), `noir` (mono night), `slate` (blue-grey), `neon` (vivid night), `ember` (coffee/gold), `forest` (deep green), `plum` (aubergine).
Fetch the full list with exact palettes — **no API key required**:
```bash
curl https://tintmap.dev/v1/themes
```
Each theme returns `{ id, name, dark, blurb, palette: { land, green, water, building, road, roadMajor, label, halo } }`. Compare a theme's palette to the site's colors to pick the closest match.
### 3. Custom palette — exact colors
Add a `custom` object to override individual map layers on top of any theme. Keys (all optional, hex values): `land`, `green` (parks), `water`, `building`, `road`, `roadMajor` (highways), `label` (text). Use it to inject a brand accent onto a preset theme, or to match exact site colors.
```json
{ "theme": "midnight", "brand": "#22D3EE", "custom": { "roadMajor": "#22D3EE", "label": "#cfe8ff" } }
```
### How to choose (decision guide for an agent)
- Site is **light** with a clear brand color → brand-match (`theme:"brand"` + `brand`).
- Site is **dark** → a dark preset theme (`dark:true`), optionally + `custom` for the accent.
- Need **specific colors** → `custom` palette on top of the nearest theme.
- **Always** set `brand` to the site's accent color — it colors the pins on every theme.
## Markers (pins)
Two ways to put pins on a map.
### Static markers — baked into the map config (Studio or `POST /v1/maps`)
Add a `markers` array; each marker is `{ lat, lng, label, address }` (label + address show in the popup). Tune appearance with:
- `markerStyle`: `pin` (default), `dot`, `pulse`, or `ring`.
- `popupMode`: `click` (default), `hover`, `always`, or `none`.
- Pin color = the `brand` hex.
```json
{
"name": "Our stores", "theme": "brand", "brand": "#E2553A",
"center": [41.0289, 28.974], "zoom": 12,
"markerStyle": "pin", "popupMode": "click",
"markers": [
{ "lat": 41.0289, "lng": 28.974, "label": "Karaköy", "address": "Open until 9pm" },
{ "lat": 41.0369, "lng": 28.985, "label": "Nişantaşı", "address": "Open until 8pm" }
]
}
```
### Runtime markers — from your own data after the map loads (JavaScript SDK, Starter plan and up)
Embed with the Script method, then drive markers from JS. The global `Tint` object is available once `embed.js` loads.
```html
```
SDK methods: `Tint.ready(id, cb)`, and on the map handle: `get()`, `setMarkers(array)`, `addMarker(obj)`, `clearMarkers()`, `flyTo(lat, lng, zoom)`, `on("markerClick" | "ready", cb)`.
## Rules an agent must follow
- Use a real published map ID. If you do not have one, the human must create and publish a map in the Studio at https://tintmap.dev first.
- The site's domain must be added to the map's allow-list in the Tint dashboard, or the embed will refuse to render on that origin.
- Do not remove or hide the OpenStreetMap attribution.
- The JS SDK (`Tint.ready`) requires a Starter plan or higher; on the Free plan the embed still renders but SDK calls are ignored.
## Programmatic map creation (REST API)
Create and publish a map over HTTP, then embed the returned ID. This is how an AI agent generates a brand-new map end to end.
- Base URL: `https://tintmap.dev/v1`
- Auth: every request needs `Authorization: Bearer sk_live_...` (a secret key — create one in the dashboard under API Keys). Secret keys are server-side only; never put them in client/browser code.
- Plan: the REST API requires a Pro plan or higher.
- Rate limit: up to 60 map creations per minute per key. Exceeding it returns HTTP 429 with a `Retry-After` header (seconds).
Create + publish a map in one call:
```bash
curl -X POST https://tintmap.dev/v1/maps \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Our stores",
"theme": "midnight",
"brand": "#E2553A",
"center": [41.0289, 28.974],
"zoom": 12,
"markers": [
{ "lat": 41.0289, "lng": 28.974, "label": "HQ", "address": "Open until 9pm" }
]
}'
```
Response (201) — the map is already published and live:
```json
{
"id": "m_ab12cd34",
"status": "published",
"url": "https://embed.tintmap.dev/m/m_ab12cd34",
"embed": {
"script": "\n",
"iframe": ""
}
}
```
Take `embed.script` from the response and paste it into the page — done.
Config fields for the body: `name`, `theme` (a preset id or `"brand"` — see **Styling** above), `brand` (hex; the brand-match source and the pin color), `custom` (per-layer hex overrides — see Styling), `center` (`[lat, lng]`), `zoom`, `markers` (`[{ lat, lng, label, address }]` — see **Markers**), `markerStyle`, `popupMode`, plus optional `directions`, `openNow`, `hours`, `badge`. To make the map on-brand, set `theme`/`brand`/`custom` per the Styling section.
Other endpoints:
- `GET /v1/themes` — every theme with its exact palette, plus brand-match + custom-palette docs. **PUBLIC, no API key** — call it first to pick a style that matches the site.
- `GET /v1/maps` — list maps in the workspace (Bearer auth)
- `GET /v1/maps/{id}` — fetch a map's config + embed snippets (Bearer auth)
- `GET /v1/usage` — current plan and monthly load quota (Bearer auth)
## Links
- App & Studio: https://tintmap.dev
- Embed origin: https://embed.tintmap.dev
- Human docs: https://tintmap.dev → Docs