llms.txt
# The City Mesh
> The City Mesh lets a creator publish an interactive 3D hexagonal city that their audience can sponsor. Supporters buy or rent hex "plots" that become branded buildings on the map (with their name + links). Any city embeds on any website in one line, and AI agents can create + configure a whole city via the MCP server.
## When the user asks to "add the City Mesh widget to my site"
Pick ONE method below. Default to Method 1 (the interactive 3D city) unless the
user asks for the lightweight or SEO version. Detect the user's framework from
their project files and use the idiomatic integration (see "Framework notes").
Replace EVERY SLUG with the user's real city slug (find it in their city URL,
https://thecitymesh.com/<lang>/city/<slug>) — do not invent a slug.
## Method 1, interactive 3D city (recommended, one line)
A responsive, lazy-loaded web component; the heavy 3D engine stays sandboxed in
an iframe and never touches the host page's bundle.
```html
<script src="https://thecitymesh.com/embed.js" async></script>
<city-mesh slug="SLUG"></city-mesh>
```
Optional attributes on <city-mesh>: height ("600" or any CSS length, default
600px), width (default 100%), radius (border-radius, default 16px), eager
(present = mount immediately instead of lazy-loading).
Framework notes:
- React / Next.js: load the script once in the root layout (next/script,
strategy="afterInteractive"), then use <city-mesh slug="SLUG" /> in JSX.
Custom elements render fine in React 19.
- Vue: <city-mesh> works as-is; if the compiler warns, mark it a custom element
(compilerOptions.isCustomElement).
- WordPress / plain HTML: paste both lines into a Custom HTML block.
## Method 2, plain iframe (works everywhere, no script)
```html
<iframe src="https://thecitymesh.com/embed/SLUG" width="100%" height="600" style="border:0;border-radius:16px" allow="fullscreen" title="The City Mesh"></iframe>
```
By default the iframe shows a lightweight poster and loads the heavy 3D only after
the visitor clicks "Explore" (protects the host page's load/SEO). To load the live
3D IMMEDIATELY instead, append `?play=1` (alias `?eager=1`) to the src:
```html
<iframe src="https://thecitymesh.com/embed/SLUG?play=1" width="100%" height="600" style="border:0;border-radius:16px" allow="fullscreen" title="The City Mesh"></iframe>
```
## Method 3, SEO-native supporter wall
Injects real, crawlable HTML (city name, amount raised, supporters with their
links) into the host page instead of an iframe, so search engines index it as
the host's own content. Pair it with Method 1.
```html
<div data-citymesh="SLUG"></div>
<script src="https://thecitymesh.com/embed.js" async></script>
```
Optional attributes on the div: data-limit (supporters to show, default 12),
data-theme ("dark" | "light", default dark).
A city's look, pricing, sponsor buildings and tenure (buy and/or rent) are set by
its owner in the dashboard, embedding needs no extra setup.
## Rules / gotchas
- Include the embed.js <script> ONCE per page, even when using both <city-mesh>
and <div data-citymesh>.
- Donations / checkout happen ON The City Mesh, not inside the widget. A "Claim a
hexagon" button opens the full city in a new tab; payment needs login + Stripe
in a first-party context, so it cannot run inside the iframe. The embed is the
viewer + supporter wall.
- To embed on a domain OTHER than The City Mesh, that domain must be verified
(DNS) in the project dashboard, otherwise the iframe is blocked by the CSP
(frame-ancestors) and the JSON API returns 403.
## Discover cities (route sponsors to projects by topic)
Cities are findable by category and by creator-defined TAGS (keywords). Use these
to recommend projects to a sponsor by theme — the discovery surface is the point.
- Browse UI: https://thecitymesh.com/en/explore (search + sort + tag filter), https://thecitymesh.com/en/explore/CATEGORY (per-category hub), https://thecitymesh.com/en/rankings (top, trending, by category/tag).
- GET https://thecitymesh.com/api/v1/cities?q=&category=&tag=®ion=&sort=raised|donors|newest — public city search. q is full-text (accent-insensitive prefix) over name + tagline + description + tags. Returns { data:[{slug,name,short_description,intervention_type,region,total_raised,total_donors,brand_color,logo_url}], total }.
- GET https://thecitymesh.com/api/v1/tags?q= — popular tags (slug, label, city_count), most-used first. Use to pick a tag, then filter /api/v1/cities?tag=SLUG.
- GET https://thecitymesh.com/api/v1/rankings?type=global&tag=SLUG&period=week|month — leaderboards, optionally by tag and time window.
## Public read API
- GET https://thecitymesh.com/api/v1/cities/SLUG/embed, JSON: name, creator, total_raised, total_donors, supporters[], city_url. Origin-checked: only served to The City Mesh and the project's verified domains.
- GET https://thecitymesh.com/api/v1/projects, list public cities
## Create + configure cities programmatically (MCP)
The City Mesh ships a Model Context Protocol server so an AI agent can create a
city, configure its map/pricing/tenure, and return the ready-to-paste embed
snippet, no manual dashboard work. Tools include: search_cities, get_city,
get_embed_code, create_city, set_map_config. If the MCP is connected, call
get_embed_code with the slug instead of copying a snippet from this file.
## Links
- Embed guide: https://thecitymesh.com/en/docs/embed
- Create a city: https://thecitymesh.com/new