Documentation

tileserver-rs includes an AI assistant that lets you interact with your maps using natural language. It can run on three backends:

ProviderWhere inference runsKeyPrompts leave the device?
Local (WebLLM) — defaultYour browser, via WebGPUNoneNo
OpenAI-compatible / AnthropicYour own provider (bring your own key)Yours, in your browserYes, to your provider
Server providerThe provider configured in [llm]Held by the serverYes, via this server

Pick the provider with the settings button (gear icon) in the chat palette header.

How It Works

The AI chat is powered by WebLLM, which runs open-source language models directly in your browser using WebGPU acceleration. The assistant can:

  • Navigate the map — fly to cities, countries, or coordinates
  • Query features — find what's visible in the viewport or search tile data
  • Modify styles — change colors, opacity, visibility of map layers
  • Highlight features — temporarily highlight features matching a filter
  • Inspect data — get layer schemas, source statistics, and spatial queries

The entire conversation stays in your browser. Chat history is persisted to localStorage via TanStack DB and survives page refreshes.

Requirements

Info

WebGPU is required. Use Chrome 113+, Edge 113+, or any Chromium-based browser with WebGPU support. Firefox and Safari do not fully support WebGPU yet.

RequirementMinimumRecommended
BrowserChrome 113+Chrome 120+
GPU VRAM2 GB6 GB
Free RAM2 GB8 GB
Disk Space1 GB5 GB (for larger models)

Getting Started

  1. Open any style in the map viewer (e.g., http://localhost:8080/styles/protomaps-light/)
  2. Press ⌘K (Mac) or Ctrl+K (Windows/Linux) to open the chat palette
  3. On first use, the model downloads and compiles for your GPU (~30 seconds)
  4. Type a message or select a suggested prompt

Subsequent loads are fast (~2–5 seconds) because the compiled model is cached in IndexedDB.

Suggested Prompts

The chat palette shows suggested prompts when the conversation is empty:

  • "Fly to Paris, France and show me the Eiffel Tower area"
  • "What layers are available on this map?"
  • "Take me to Tokyo, Japan at a good zoom level"
  • "Show me the entire Mediterranean Sea region"

Available Models

The local provider ships with four Qwen3.5 models (WebLLM prebuilt builds). Choose based on your hardware and needs:

ModelVRAMBest For
Qwen3.5 4B (default)3.9 GBBest balance of quality and speed
Qwen3.5 9B6.4 GBBest quality, needs more VRAM
Qwen3.5 2B2.2 GBLightweight, lower VRAM systems
Qwen3.5 0.8B1.6 GBMinimal hardware, basic interactions

Local models use a text-based tool parser — the LLM emits structured [MAP_ACTION] blocks that are parsed and executed client-side. Remote providers use native tool calling and have the full tool set.

You can switch models at any time using the model selector dropdown in the chat palette.

Remote Providers (Bring Your Own Key)

Use a provider you already pay for — Anthropic Claude, OpenAI, OpenRouter, Groq, or a self-hosted server (Ollama, LM Studio, vLLM). Remote mode needs no WebGPU and no model download.

  1. Open the chat palette and click the settings (gear) button.
  2. Choose OpenAI-compatible or Anthropic (Claude).
  3. Enter the base URL, model, and API key, then click Test connection.
ProviderBase URLNotes
Anthropichttps://api.anthropic.comSent with anthropic-dangerous-direct-browser-access: true, which Anthropic provides for bring-your-own-key apps
OpenAIhttps://api.openai.com/v1
OpenRouterhttps://openrouter.ai/api/v1Many models behind one key
Ollamahttp://localhost:11434/v1No key. Start Ollama with OLLAMA_ORIGINS set to this site's origin
LM Studiohttp://localhost:1234/v1No key. Enable CORS in the server settings

The browser calls the provider directly, so the provider must allow browser (CORS) requests. If it does not, use the server proxy instead.

How the key is stored:

  • By default the key is kept in sessionStorage and cleared when you close the tab.
  • Remember key on this device saves it in localStorage instead. Any script running on the page can read it — only enable this on a trusted deployment.
  • Forget key removes it from both.
  • The key is only sent in request headers to the provider you entered. It is never put in a URL, logged, or sent to tileserver-rs.

Server Proxy

Operators can configure one provider on the server. The chat palette then offers a Server provider option; users need no key, and there is no CORS limit.

[llm]
enabled = true
provider = "anthropic"                  # or "openai-compatible"
base_url = "https://api.anthropic.com"
api_key_env = "TILESERVER_LLM_API_KEY"  # the key itself stays in the environment
model = "claude-sonnet-4-5"
allow_user_keys = true                  # set false to offer only Local + Server provider
TILESERVER_LLM_API_KEY=sk-ant-... tileserver-rs --config config.toml
EndpointDescription
GET /api/llm/configWhether the proxy is enabled, its provider family, model, and upstream host. Never returns the key.
POST /api/llm/chatForwards an OpenAI Chat Completions or Anthropic Messages body upstream and streams the response back. The server sets model and the auth headers.

The proxy returns 404 when disabled, 413 for bodies over max_body_bytes, 429 (with Retry-After: 60) over rate_limit_per_minute, and 502 when the upstream cannot be reached. All [llm] keys are listed in the configuration reference.

Map Tools

The AI assistant has access to 13 tools organized into three categories: navigation, styling, and data queries.

fly_to

Animate the map camera to a specific location.

"Fly to the Colosseum in Rome"
"Show me downtown Manhattan at zoom 15"
"Go to coordinates 139.7, 35.7 with a 45° bearing"
ParameterTypeRequiredDescription
lngnumber✅Longitude (-180 to 180)
latnumber✅Latitude (-90 to 90)
zoomnumberZoom level 0–22 (default 12)
bearingnumberBearing in degrees (default 0)
pitchnumberPitch 0–85° (default 0)

fit_bounds

Fit the map camera to a bounding box — useful for countries, regions, or areas.

"Show me all of Japan"
"Zoom to the Mediterranean Sea"
"Fit the map to the continental United States"
ParameterTypeRequiredDescription
westnumber✅West longitude
southnumber✅South latitude
eastnumber✅East longitude
northnumber✅North latitude
paddingnumberPadding in pixels (default 50)

get_map_state

Get the current map center, zoom, bearing, pitch, and visible layers. The assistant uses this to understand what you're looking at before making changes.

Styling Tools

set_layer_visibility

Show or hide a map layer by its ID.

"Hide the water layer"
"Show the buildings layer"
"Turn off all label layers"

set_layer_paint

Change a paint property of a map layer — color, opacity, width, and more.

"Make the water dark blue"
"Set the building fill opacity to 0.5"
"Change road line width to 3"

set_layer_filter

Apply a MapLibre filter expression to a layer. Only features matching the filter are shown.

"Only show parks in the landuse layer"
"Filter buildings taller than 50 meters"

add_highlight

Temporarily highlight features matching a filter with a colored circle. Highlights auto-remove after 8 seconds.

"Highlight all hospitals"
"Show me where the schools are in red"

generate_style

Apply multiple style changes at once from a natural language description.

"Make this a dark mode map"
"Give me a satellite-style color scheme"
"Make all text labels larger"

Data Query Tools

These tools query the tile data served by tileserver-rs — either from the rendered viewport or directly from the vector tile sources.

query_rendered_features

Query features currently visible in the map viewport. Returns properties and geometry type.

"What features are visible right now?"
"Show me the properties of buildings in view"
"List all points of interest I can see"

get_source_schema

Get the schema of a tile source — available layers, field names and types, zoom range, and bounds.

"What layers are in the openmaptiles source?"
"Show me the fields available in the buildings layer"

get_source_stats

Get statistics for a tile source — bounds, zoom range, layer count, attribution.

"What's the zoom range of this data source?"
"Show me the attribution for the terrain data"

spatial_query

Query features from a tile source within a bounding box. This queries the actual vector tile data on the server, not just what's rendered in the viewport.

"Find all buildings within 1km of the Eiffel Tower"
"What points of interest are in this area?"
ParameterTypeRequiredDescription
sourcestring✅Source ID to query
bboxnumberBounding box [west, south, east, north]
zoomnumberTile resolution (default 14)
layersstringLayer IDs to query
limitnumberMax features to return (default 100)

get_overlays

List all user-dropped file overlays on the map — file names, formats, feature counts, colors, and visibility. Works with files dragged onto the map viewer (GeoJSON, KML, GPX, CSV, Shapefiles, PMTiles).

Keyboard Shortcuts

ShortcutAction
⌘K / Ctrl+KToggle chat palette
EscClose chat palette
EnterSend message

Architecture

User Input → Chat Palette (Vue)
    ↓
useLlmPanel (composable) ← useLlmProvider (provider, settings, key)
    ↓
useLlmChat → useChat({ connection: stream(adapter) })
    ↓
stream() adapter — converts provider output → AG-UI protocol events
    ├── Local: WebLLM engine (browser, WebGPU)
    ├── OpenAI-compatible: POST {base}/chat/completions (SSE)
    ├── Anthropic: POST /v1/messages (SSE)
    └── Server provider: POST /api/llm/chat → configured upstream
    ↓
AG-UI events stream back to TanStack AI Vue
    ↓
Tool results auto-executed client-side
    ↓
Chat Palette renders messages + tool results

Key packages:

Chat Persistence

Chat messages are automatically saved to your browser's localStorage via TanStack DB. This includes:

  • All user and assistant messages
  • Tool call records (which tool was called, with what arguments)
  • Spatial query results

Messages persist across page refreshes and browser restarts. They are stored locally; only the active remote provider (if any) receives the conversation, as part of each request.

Troubleshooting

"WebGPU is not supported"

Your browser doesn't support WebGPU. Use Chrome 113+ or Edge 113+. On macOS, Safari technology previews have partial WebGPU support but may not work reliably with WebLLM.

Model download is slow

The first download transfers 1.6–6.4 GB depending on the model. After the first download, the compiled model is cached in IndexedDB and loads in 2–5 seconds. Try a smaller model (Qwen3.5 0.8B at 1.6 GB) if bandwidth is limited, or use a remote provider.

Tool calls don't execute

If the assistant describes an action but doesn't execute it, try a larger model. Qwen3.5 4B or Qwen3.5 9B have the best instruction-following for tool execution. Smaller models (0.8B, 2B) may occasionally describe actions in prose instead of emitting the structured [MAP_ACTION] blocks the parser expects.

"Could not reach …" with a remote provider

The provider is unreachable or blocks browser requests (CORS). Check the base URL; for Ollama set OLLAMA_ORIGINS; otherwise ask the operator to enable the server proxy.

"The API key was rejected"

The provider returned 401/403. Re-enter the key, or click Forget key and paste it again.

Chat palette won't open

Make sure you're on a style viewer page (/styles/{style}/). The AI chat is only available in the map viewer, not on the home page or data inspector.

GPU out of memory

Try a smaller model. Qwen3.5 0.8B requires only ~1.6 GB of VRAM. Close other GPU-intensive tabs or applications. On systems with shared GPU memory (integrated graphics), ensure enough system RAM is available.

Privacy & Security

  • Local (default): no data leaves your browser — the LLM runs entirely via WebGPU, with no keys and no token costs
  • Remote providers send prompts off the device — the palette shows "Prompts are sent to <host>" whenever a remote provider is active, and calls are billed to the provider account in use
  • Your own key never reaches tileserver-rs — it goes from the browser straight to the provider, in request headers only
  • The server proxy key stays on the server — it is read from an environment variable and never returned by any endpoint
  • Chat history is local — stored in localStorage, never uploaded to tileserver-rs
  • Server-side tools query your own data — spatial queries go to your tileserver-rs instance, not any external service

Live Demo

Try the AI chat on the live demo at demo.tileserver.app. Open any style, press ⌘K, and start talking to the map.

Next Steps