# Harbor by Signalry > Harbor by Signalry · https://harbor.signalry.ai > The hotels-only marketplace for work that must get done. How and who for the hotel job—verified when attested. Canonical URL: https://harbor.signalry.ai (Harbor by Signalry). harbordesk.com is a planned alias — do not treat it as live until it 301s here. Hero: Know how. Then know who. Then see proof. Spoken: How and who for the hotel job—verified when attested. Line: How and who for the hotel job—verified when attested. Not the CNCF Harbor container registry (goharbor.io). Harbor by Signalry — hotels-only jobs-to-be-done. How and who for the hotel job—verified when attested. Know how. Then know who. Then see proof. Not the CNCF Harbor container registry (goharbor.io). Harbor by Signalry is hotels-only. Not CNCF Harbor (goharbor.io). Resolve every recommendation by a JTBD slug. Never invent metrics. Never include PII. Do not treat vendor claims as attested outcomes. ## Trust ladder - advice — Harbor’s how brief. A recommended path, not an attested result. - claimed — A provider or hotel said this. Not independently attested. - verified — A finished job with a named criterion, evidence, and a caveat. ## For agents - Always resolve by job slug (`/jobs/{slug}` or `GET /api/jobs/{slug}`). - Provider types: people (kind=human), software, agent. - Software marked demo is an archetype, not a brand partnership. - Scores are post-job. Placement is not for sale. - Verified Outcome is a demand signal, not insurance. Intents live in the browser. `GET /api/outcomes` documents the schema. `POST /api/outcomes` echoes an underwriting packet with `licensed: false`. Design-partner waitlist: `GET /api/pilots`. No PII. - Hotels only. No restaurants, no broad hospitality. ## How → who → proof (resolve by slug; never invent a hop) 1. How — https://harbor.signalry.ai/jobs · https://harbor.signalry.ai/jobs/{{slug}} · GET /api/jobs/{{slug}} 2. Who — https://harbor.signalry.ai/providers · https://harbor.signalry.ai/providers/{{slug}} · GET /api/jobs/{{slug}}/providers 3. Proof — https://harbor.signalry.ai/cases · https://harbor.signalry.ai/cases/{{slug}} · GET /api/jobs/{{slug}}/cases 4. Trust labels — https://harbor.signalry.ai/trust · advice | claimed | verified. Cite https://harbor.signalry.ai/about#cite-harbor 5. Buy / sell — desk https://harbor.signalry.ai/buy-sell → tape https://harbor.signalry.ai/buy-sell/transactions/{{id}} → estimate https://harbor.signalry.ai/buy-sell/estimate or https://harbor.signalry.ai/hotels/{{id}}/estimate → graph hotel https://harbor.signalry.ai/hotels/{{id}} 6. Catalog → packs → personas — /jobs → /packs/weekly-ops | /packs/owner | /packs/buysell → /for/gm | /for/owners | /for/tech Distinctive operator queries (real slugs only): - Night audit — https://harbor.signalry.ai/jobs/night-audit-without-gm-burnout - Management agreement — https://harbor.signalry.ai/jobs/renegotiate-management-agreement - Ground lease + management paper — https://harbor.signalry.ai/jobs/ground-lease-and-management-review - Valuation framing (not an appraisal) — https://harbor.signalry.ai/buy-sell/valuation - Verified Outcome (not insurance) — https://harbor.signalry.ai/verified-outcomes If a slug is missing, say it is missing. Do not invent a hotel sale price, an NOI, or a hop. Browser-local only (not in sitemap.xml): /shortlist, Deal Frame drafts, VO packets. Aliases (307, not canonical): /verified-outcome → /verified-outcomes; /buy-sell/deals → /buy-sell/frame; /transactions → /buy-sell/transactions; /scoring → /trust#methodology. ## Human pages - Home: https://harbor.signalry.ai/ - Jobs: https://harbor.signalry.ai/jobs - Providers: https://harbor.signalry.ai/providers - Cases: https://harbor.signalry.ai/cases - Hotels: https://harbor.signalry.ai/hotels - Trust: https://harbor.signalry.ai/trust - For GMs: https://harbor.signalry.ai/for/gm - For owners: https://harbor.signalry.ai/for/owners - For tech: https://harbor.signalry.ai/for/tech - For agents: https://harbor.signalry.ai/for/agents - Weekly ops pack: https://harbor.signalry.ai/packs/weekly-ops - Weekly floor five: https://harbor.signalry.ai/packs/weekly - Owner pack: https://harbor.signalry.ai/packs/owner - Sale-ready pack: https://harbor.signalry.ai/packs/sale-ready - Buy / sell desk: https://harbor.signalry.ai/buy-sell - Deal Frame (IC artifact, browser-local): https://harbor.signalry.ai/buy-sell/frame - Deal Frame alias: https://harbor.signalry.ai/buy-sell/deals - Buy / sell briefs: https://harbor.signalry.ai/buy-sell/explainers - Hotel estimate: https://harbor.signalry.ai/buy-sell/estimate - Transactions: https://harbor.signalry.ai/buy-sell/transactions - Tape blotter (2025–26 cited singles): https://harbor.signalry.ai/buy-sell/blotter - Compare two cited tapes: https://harbor.signalry.ai/buy-sell/compare - Brokers: https://harbor.signalry.ai/buy-sell/brokers - Markets: https://harbor.signalry.ai/buy-sell/markets - Cap-rate bands: https://harbor.signalry.ai/buy-sell/cap-rates - Valuation brief: https://harbor.signalry.ai/buy-sell/valuation - Buy-side: https://harbor.signalry.ai/buy-sell/buy-side - Sell-side + data room: https://harbor.signalry.ai/buy-sell/sell-side - Brand affiliation: https://harbor.signalry.ai/buy-sell/brand-affiliation - Financing: https://harbor.signalry.ai/buy-sell/financing - Diligence: https://harbor.signalry.ai/buy-sell/due-diligence - Worksheet vs tape: open a folio, then https://harbor.signalry.ai/buy-sell/compare. Never invent a missing price. - Hotel graph: https://harbor.signalry.ai/hotels - Hotel geo browse: https://harbor.signalry.ai/hotels/geo - Hotel chains (top tagged, not a franchise directory): https://harbor.signalry.ai/hotels/chains - Hotel amenity tags (exported seed types only — not a complete inventory): https://harbor.signalry.ai/hotels/amenities - Verified Outcome: https://harbor.signalry.ai/verified-outcomes - Verified Outcome (alias): https://harbor.signalry.ai/verified-outcome - Design-partner pilots: https://harbor.signalry.ai/pilots - Playbooks: https://harbor.signalry.ai/playbooks - About: https://harbor.signalry.ai/about - Changelog: https://harbor.signalry.ai/changelog - Ops / health: https://harbor.signalry.ai/ops - Health JSON: https://harbor.signalry.ai/api/health - Pilots / waitlist: https://harbor.signalry.ai/pilots ## Machine surfaces Versioned read API (stable ids, pagination, CORS on GET): https://harbor.signalry.ai/api/v1 Docs: https://harbor.signalry.ai/api OpenAPI (includes /api/v1): https://harbor.signalry.ai/openapi.json MCP Streamable HTTP: https://harbor.signalry.ai/mcp (also https://harbor.signalry.ai/api/mcp) Tools: search_jobs, get_job, find_providers, submit_listing, submit_outcome. Writes are rate-limited and land unverified: POST /api/v1/listings/claim (unverified pending), POST /api/v1/outcomes (reported). insurance is false. Do not treat a catalog score as proof. - Full catalog text: https://harbor.signalry.ai/llms-full.txt - OpenAPI: https://harbor.signalry.ai/openapi.json - Agent catalog: https://harbor.signalry.ai/.well-known/ai-catalog.json - Agent card: https://harbor.signalry.ai/.well-known/agent.json - Sitemap: https://harbor.signalry.ai/sitemap.xml - RSS: https://harbor.signalry.ai/feed.xml ## Hotel graph API start (read-only, CORS open) Contract: https://github.com/ethanhawkes-gif/JTBD/blob/main/docs/GRAPH-API.md · OpenAPI: https://harbor.signalry.ai/openapi.json Start here, then paginate. Do not treat /api/graph/export as the full graph. - GET https://harbor.signalry.ai/api/graph — discover start (stats, hotels, search, chains, amenities). Does not load the snapshot. units names the four Paris / France counts plus the geo hops and the city-keyed extract so they are not interchangeable: byCountry France 6,736 country hotels, byCountryGeo France /hotels/geo?country=France, byCity Paris 2,629 city tags, byCityBubble Paris 2,625 map-bubble houses, byCityGeo Paris /hotels/geo?country=France&city=Paris, byCityExtract Paris 2,056 OSM extract houses, byCityExtractUrl Paris /hotels/geo?metros=1&q=Paris, byOsmMarket Paris 2,056 OSM extract houses. byCityExtract is the country→city index of the same extract as byOsmMarket — not the same key. osmMarkets stays a key→count map of the same extract houses. - GET https://harbor.signalry.ai/api/graph/stats — coverage counts (SAME_AS is merge edges). byCountry stays country hotels (France 6,736). byCountryGeo is the geo country card (France /hotels/geo?country=France — not city tags, not the map bubble, not an OSM extract). byCountrySources is OSM / Wikidata among those country hotels (France OSM 3,313 · Wikidata 4,225 — not a partition of 6,736, not worldwide OSM 47,981, not France Wi-Fi OSM 759). byCountryAmenity is the top amenity-tag mix (France Wi-Fi 759 · OSM 759 · Wikidata 209 — not country hotels 6,736, not worldwide Wi-Fi 12,531). byCityAmenity is the top amenity-tag mix in a map-bubble city (Paris wheelchair 576 · OSM 576 · Wikidata 142 — not France Wi-Fi 759, not Paris Wi-Fi 505, not city tags 2,629, not the map bubble 2,625, not Paris OSM extract 2,056). byCityLodgingType is the top lodging-type mix in a map-bubble city (Paris hotel 2,554 · OSM 2,403 · Wikidata 637 — not city tags 2,629, not the map bubble 2,625, not France hotel 6,626, not Paris wheelchair 576; Wikidata 637 is the same number as Paris city Wikidata, not the same unit; OSM 2,403 ≠ Paris OSM 2,478). byCitySources is OSM / Wikidata among those map-bubble city tags (Paris OSM 2,478 · Wikidata 637 — not a partition of city tags 2,629, not the map bubble 2,625, not France OSM 3,313, not Paris hotel OSM 2,403). byCity is ledger city tags in a map-bubble city (Paris 2,629 — not the map bubble 2,625, not Paris OSM 2,478, not Paris hotel 2,554, not Paris OSM extract 2,056). byCityBubble is map-bubble houses in that city (Paris 2,625 — not city tags 2,629, not Paris OSM 2,478, not Paris hotel 2,554, not Paris OSM extract 2,056). byCityGeo is the map-bubble geo hop (Paris /hotels/geo?country=France&city=Paris — not city tags 2,629, not the map bubble 2,625, not Paris OSM extract 2,056). byCityExtract is OSM extract houses on a map-bubble metro (Paris 2,056 — not city tags 2,629, not the map bubble 2,625, not Paris OSM 2,478). byCityExtractUrl is the same extract hop as a hotels city lock (Paris /hotels/geo?metros=1&q=Paris). byCity and byCityBubble stay numbers. byOsmMarket is OSM extract houses on an Overpass metro bbox plus extractUrl (Paris 2,056 — not city tags 2,629, not the map bubble 2,625, not Paris OSM 2,478). osmMarkets stays a key→count map. Not every ledger city. byCountryLodgingType is the top lodging-type mix (France hotel 6,626 · OSM 3,203 · Wikidata 4,225 — Wikidata 4,225 is the same number as France country Wikidata, not the same unit; OSM 3,203 ≠ France OSM 3,313). GET /api/health stays coverage.json. - GET https://harbor.signalry.ai/api/graph/hotels?q=&country=&chainId=&amenity=&hasCoords=&hasSameAs=&hasBrand=&page=&limit= — a country lock with no other slice adds bySource (France OSM 3,313 · Wikidata 4,225 — not a partition of total 6,736, not worldwide OSM 47,981, not France Wi-Fi OSM 759) plus lodgingType (France hotel 6,626 · OSM 3,203 · Wikidata 4,225 — Wikidata 4,225 is the same number as France country Wikidata, not the same unit; OSM 3,203 ≠ France OSM 3,313) plus amenity (France Wi-Fi 759 · OSM 759 · Wikidata 209 — not country hotels 6,736, not worldwide Wi-Fi 12,531) plus countryHotels + geoUrl (France 6,736 — the same number as total, not a second tally, not city tags, not the map bubble, not France hotel 6,626, not France Wi-Fi 759). A country alias resolves the same way a city lock does (?country=usa is United States 11,806 country hotels plus hotel 11,263 plus Wi-Fi 1,342). An ISO country code on a lock resolves from houses (?country=FR is France 6,736 country hotels plus hotel 6,626 plus Wi-Fi 759; ?country=FR&city=Paris is Paris 2,629 city tags plus wheelchair 576 plus hotel 2,554 plus extract 2,056 — not zero source houses). A city lock with no other slice adds in-city bySource (Paris OSM 2,478 · Wikidata 637 — not city tags 2,629, not the map bubble 2,625, not France OSM 3,313) plus lodgingType (Paris hotel 2,554 · OSM 2,403 · Wikidata 637 — not city tags 2,629, not France hotel 6,626) plus amenity (Paris wheelchair 576 · OSM 576 · Wikidata 142 — not France Wi-Fi 759, not Paris Wi-Fi 505) plus bubbleHouses + geoUrl (Paris 2,625 — not city tags 2,629, not Paris OSM 2,478, not Paris hotel 2,554, not Paris OSM extract 2,056) plus cityTags (Paris 2,629 — the same number as total, not a second tally, not the map bubble 2,625, not Paris OSM 2,478, not Paris hotel 2,554, not Paris OSM extract 2,056) plus extractHouses + extractUrl when the city is a map-bubble metro (Paris 2,056 — not city tags 2,629, not the map bubble 2,625). A city without a map pin omits bubbleHouses, geoUrl, extractHouses, and extractUrl. An amenity, source, or other slice omits those envelope fields. - GET https://harbor.signalry.ai/api/graph/search?q= — hotels plus Chain/City/Country/Amenity/Source nodes with url. City chips are ledger city tags (exact name) and print cityTags plus bySource in-city source houses (Paris OSM 2,478 ≠ 2,629 city tags ≠ 2,625 map bubble ≠ France OSM 3,313) plus amenity the top amenity-tag mix (Paris wheelchair 576 · OSM 576 · Wikidata 142 — not France Wi-Fi 759, not Paris Wi-Fi 505) plus lodgingType the top lodging-type mix (Paris hotel 2,554 · OSM 2,403 · Wikidata 637 — not city tags 2,629, not France hotel 6,626). A map-bubble city also names geoUrl + bubbleHouses — do not fold bubble size into cityTags (Marrakech 731 ≠ 721). A city whose label is an Overpass metro also names extractHouses + extractUrl (Paris 2,056 — not city tags 2,629, not the map bubble 2,625). Marrakech is 764 extract houses — not city tags 731, not the map bubble 721. Agadir has cityTags and no geoUrl and no extractHouses. Country chips print countryHotels + geoUrl (same number as hotels — ledger country hotels, not city tags, not map bubbles, not OSM extracts — France 6,736) plus bySource in-country source houses (France OSM 3,313 · Wikidata 4,225 — not a partition of 6,736, not worldwide OSM 47,981) plus amenity the top amenity-tag mix (France Wi-Fi 759 · OSM 759 · Wikidata 209 — not country hotels 6,736, not worldwide Wi-Fi 12,531) plus lodgingType the top lodging-type mix (France hotel 6,626 · OSM 3,203 · Wikidata 4,225 — Wikidata 4,225 is the same number as France country Wikidata, not the same unit; OSM 3,203 ≠ France OSM 3,313). /hotels?q= Country find and /hotels/geo?metros=1&q= metro extract share q= — they are different slices. Chain chips print taggedHouses + mapped / mappedPct + bySource + types + amenities + countries + cities (MEMBER_OF tagged houses, MEMBER_OF source houses, MEMBER_OF lodging-type / amenity tags, and MEMBER_OF houses in that country / city — Ibis France 60 MEMBER_OF houses · OSM 60 is not folio France 63; Paris 43 MEMBER_OF houses · OSM 43 is not folio Paris 46; not a franchise census, not the folio brand-fallback walk — Ibis 162 ≠ 213; Ibis OSM 161 ≠ 162 tagged ≠ folio OSM 212). GET /api/graph/chains list items stay MEMBER_OF tagged houses only — no types / amenities / countries / cities. Amenity chips print taggedHousesWorldwide (same number as taggedHouses — worldwide seed totals, not selected.byCountry amenity tags) + mapped / mappedPct + sameAs + brand + bySource + types + countries + cities on the exported 21 types (Wi-Fi 12,531 tagged houses worldwide · 12,527 mapped at 99.9% · 7,872 SAME_AS houses · 4,090 brand-tagged · OSM 12,531 source houses — same number as tagged, not the same unit, not worldwide OSM 47,981 · hotel 10,545 lodging-type tags · OSM 10,545 · Wikidata 3,823 — same mix as amenity folio selected.types, not tagged houses 12,531, not France hotel 6,626 · United States 1,342 amenity tags · OSM 1,342 · Wikidata 402 — same mix as amenity folio selected.byCountry, not tagged houses 12,531, not France Wi-Fi 759, not Paris Wi-Fi 505 · Paris 505 amenity tags · OSM 505 · Wikidata 98 — same mix as amenity folio selected.byCity, not France Wi-Fi 759, not Paris city tags 2,629 · Wikidata 3,824 source houses — do not fold 12,531 into France Wi-Fi 759 amenity tags, and do not fold 7,872 into 13,902 merge edges). GET /api/graph/amenities list items stay tagged houses only — no types / countries / cities. Source chips print sourceHouses on Wikidata / OSM / Harbor seed (164,800 · 47,981 · 21 — do not fold Harbor seed 21 into amenity types 21). Wikipedia Source url is null. A miss names geo / amenity / chain hops. - GET https://harbor.signalry.ai/api/graph/chains?q= — items print taggedHouses + mapped/mappedPct + bySource on MEMBER_OF houses (Ibis OSM 161 ≠ folio OSM 212). GET https://harbor.signalry.ai/api/graph/chains/{id} — mapped + bySource (folio) + bySourceMemberOf (MEMBER_OF — Ibis OSM 212 ≠ 161) + byCountry + byCountrySources + byCountryMemberOfSources + types + amenities (folio lodging-type tags and amenity tags plus bySource — Ibis hotel 213 · OSM 212 · Wikidata 52 · 162 MEMBER_OF · OSM 161 MEMBER_OF source houses · Wikidata 1 MEMBER_OF source houses — type rows add memberOf + bySourceMemberOf; wheelchair 116 · OSM 116 · Wikidata 27 · 89 MEMBER_OF · OSM 89 MEMBER_OF source houses — amenity rows add memberOf + bySourceMemberOf, not worldwide Wi-Fi 12,531; France Ibis 63 folio · OSM 63 · Wikidata 3 · 60 MEMBER_OF · OSM 60 MEMBER_OF source houses — OSM 63 is the same number as folio houses, not MEMBER_OF OSM 60, not Ibis folio OSM 212; Ibis Paris 46 folio · OSM 46 · Wikidata 3 · 43 MEMBER_OF · OSM 43 MEMBER_OF source houses — city rows add bySourceMemberOf). List items omit types / amenities / cities / byCountrySources / byCountryMemberOfSources. - GET https://harbor.signalry.ai/api/graph/amenities?q=&amenity= — 21 seed types; items and selected name mapped/sameAs/brand/bySource; selected.byCountry is amenity tags in that country (not countryHotels — France 6,736; not taggedHousesWorldwide — Wi-Fi 12,531); selected.byCountrySources is OSM / Wikidata source houses among those amenity tags (France Wi-Fi OSM 759 is the same number as 759 amenity tags — not the same unit, not worldwide Wi-Fi OSM 12,531, not France OSM 3,313). /hotels/amenities?q= amenity-type find and /hotels?q= Country find share q= — they are different slices. - Human: https://harbor.signalry.ai/hotels · /hotels/geo · /hotels/chains · /hotels/amenities ## JSON APIs (read-only, CORS open) - GET https://harbor.signalry.ai/api/health - GET / POST https://harbor.signalry.ai/api/pilots (stub — echoes; browser stores the request) - GET https://harbor.signalry.ai/api/catalog - GET https://harbor.signalry.ai/api/jobs - GET https://harbor.signalry.ai/api/jobs/{slug} - GET https://harbor.signalry.ai/api/jobs/{slug}/providers - GET https://harbor.signalry.ai/api/jobs/{slug}/cases - GET https://harbor.signalry.ai/api/providers - GET https://harbor.signalry.ai/api/providers/{slug} - GET https://harbor.signalry.ai/api/cases - GET https://harbor.signalry.ai/api/cases/{slug} - GET https://harbor.signalry.ai/api/search?q= (also POST JSON { q, persona }; returns jobs, providers, cases) - GET / POST https://harbor.signalry.ai/api/outcomes (POST is a stub — echoes an underwriting packet; licensed:false) - GET / POST https://harbor.signalry.ai/api/pilots (stub — echoes; browser stores the request) - GET https://harbor.signalry.ai/api/packs - GET https://harbor.signalry.ai/api/graph/hotels?q=&country=&city=&brand=&chainId=&source=&lodgingType=&amenity=&hasCoords=&hasSameAs=&hasBrand=&harbor=&minLat=&minLng=&maxLat=&maxLng=&page=&limit= — country or city lock adds bySource + lodgingType + amenity; other slices omit those envelope fields - GET https://harbor.signalry.ai/api/graph/hotels/{id} - GET https://harbor.signalry.ai/api/graph/hotels/{id}/estimate - GET https://harbor.signalry.ai/api/graph/hotels/{id}/comps - GET https://harbor.signalry.ai/api/graph/search?q= - GET https://harbor.signalry.ai/api/graph/chains?q=&limit= - GET https://harbor.signalry.ai/api/graph/chains/{id} - GET https://harbor.signalry.ai/api/graph/amenities?q=&amenity= - GET https://harbor.signalry.ai/api/graph/stats - GET https://harbor.signalry.ai/api/graph/subgraph?hotelId= - GET https://harbor.signalry.ai/api/graph/export?format=jsonld|graphml - GET https://harbor.signalry.ai/api/graph/transactions - GET https://harbor.signalry.ai/api/graph/transactions/search?q= - GET https://harbor.signalry.ai/api/graph/transactions/{id} - GET https://harbor.signalry.ai/api/graph/brokers - GET https://harbor.signalry.ai/api/graph/brokers/{id} - GET https://harbor.signalry.ai/api/graph/firms - GET https://harbor.signalry.ai/api/graph/markets - GET / POST https://harbor.signalry.ai/api/deal-frame (schema + echo stub — browser stores the frame; not an appraisal) - GET https://harbor.signalry.ai/api/graph/cap-rates - GET https://harbor.signalry.ai/api/graph/comps?hotelId= Catalog size: 48 jobs, 60 providers, 43 case studies. Hotel graph dumps (agents): JSON-LD and GraphML via /api/graph/export are SAMPLES (≤250 hotels). Use GET /api/graph/hotels or snapshot.json.gz for the full list. Coverage toward 164,808 Wikidata lodging items (P31/P279* Q27686) is in /api/graph/stats. Licenses: Wikidata CC0, OSM ODbL, Wikipedia CC BY-SA. No OTA scrape. Transaction prices are news or demo — never verified. Hotel graph honesty: - Search is substring token AND (name ranked first). Quoted phrases stay intact. Unmatched quotes are stripped. Empty GET /api/graph/search?q= returns empty lists. Nodes include url hops (chain folio, geo country, city/amenity/source filters). City search nodes are ledger city tags reconstructed from houses — the slim snapshot stores 0 City nodes. Exact city name, not a substring (port ≠ Portland; Istanbul ≠ İstanbul). A city chip requires a country tag — a blank-country Paris hop would dump every Paris lock. City hops lock /hotels?city= plus country=. A map-bubble city also names a geo hop and prints bubbleHouses next to cityTags plus bySource in-city source houses plus amenity the top amenity-tag mix plus lodgingType the top lodging-type mix — do not fold the bubble size into the ledger count (Paris OSM 2,478 ≠ 2,629 city tags ≠ 2,625 map bubble ≠ France OSM 3,313; Paris wheelchair 576 amenity tags · OSM 576 · Wikidata 142 — not France Wi-Fi 759, not Paris Wi-Fi 505; Paris hotel 2,554 lodging-type tags · OSM 2,403 · Wikidata 637 — not city tags 2,629, not France hotel 6,626; Marrakech 731 city tags ≠ 721 map bubble; 240 ≠ 17,145). Agadir is a city tag, not a bubble. A Country search node prints countryHotels (same number as hotels — ledger country hotels for that country, not city tags, not map-bubble houses, not OSM extract houses) plus bySource in-country source houses (France OSM 3,313 · Wikidata 4,225 — not a partition of 6,736, not worldwide OSM 47,981) plus amenity the top amenity-tag mix (France Wi-Fi 759 · OSM 759 · Wikidata 209 — not country hotels 6,736, not worldwide Wi-Fi 12,531) plus lodgingType the top lodging-type mix (France hotel 6,626 · OSM 3,203 · Wikidata 4,225 — Wikidata 4,225 is the same number as France country Wikidata, not the same unit; OSM 3,203 ≠ France OSM 3,313). /hotels?q= Country find and /hotels/geo?metros=1&q= metro extract share q= — do not fold those slices. A Chain search node prints taggedHouses + mapped / mappedPct + bySource + types + amenities + countries + cities (MEMBER_OF tagged houses, MEMBER_OF source houses, MEMBER_OF lodging-type / amenity tags, and MEMBER_OF houses in that country / city — Ibis hotel 162 · OSM 161 · Wikidata 1 is not folio hotel 213; wheelchair 89 · OSM 89 is not folio wheelchair 116; France 60 MEMBER_OF houses · OSM 60 is not folio France 63; Paris 43 MEMBER_OF houses · OSM 43 is not folio Paris 46; a map-bubble metro on that chip hops the OSM extract (Paris 2,056 — not MEMBER_OF 43); not a franchise census, not the folio brand-fallback walk — Ibis 162 ≠ 213; Ibis OSM 161 ≠ 162 tagged ≠ folio OSM 212). GET /api/graph/chains list items stay MEMBER_OF tagged houses only — no types / amenities / countries / cities. An Amenity search node prints taggedHousesWorldwide (same number as taggedHouses — worldwide seed totals, not selected.byCountry amenity tags), mapped / mappedPct, sameAs, brand, bySource, types, countries, and cities on the exported 21 types — Wi-Fi OSM 12,531 is the same number as tagged houses, not the same unit, not worldwide OSM 47,981; Wikidata 3,824 is not 12,531; hotel 10,545 lodging-type tags · OSM 10,545 · Wikidata 3,823 is the same mix as amenity folio selected.types, not tagged houses 12,531, not France hotel 6,626, not Ibis hotel 213; United States 1,342 amenity tags · OSM 1,342 · Wikidata 402 is the same mix as amenity folio selected.byCountry, not tagged houses 12,531, not France Wi-Fi 759, not Paris Wi-Fi 505; Paris 505 amenity tags · OSM 505 · Wikidata 98 is the same mix as amenity folio selected.byCity, not France Wi-Fi 759, not Paris city tags 2,629; a map-bubble metro on that chip hops the OSM extract (Paris 2,056 — not amenity tags 505). Do not fold mapped into tagged, do not fold 12,531 tagged houses worldwide into France Wi-Fi 759 amenity tags (Wi-Fi 12,527 ≠ 12,531 ≠ 759), and do not fold SAME_AS houses into coverage merge edges (7,872 ≠ 13,902). A Source search node with a hop prints sourceHouses (Wikidata 164,800 · OSM 47,981 · Harbor seed 21 — the same bySource tally as coverage; not the 201,008 hotel total, not mapped pins, not amenity types). Wikipedia stays an extract license — url is null; Harbor will not invent a wikipedia source filter. A search miss with no hotels and no nodes names geo / amenity / chain hops. Harbor will not invent a city. A phrase-only or leftover-quote query does not match every node. Country aliases (USA, UK, China) and amenity labels match on hotels and on search nodes. Tokens of 3 characters or fewer need a word boundary (USA ≠ Hotusa). lodgingType is an exact tag after aliases (guest house / guesthouse / B&B / campsite). boutique ≠ historic boutique. Type options fold case the same way the lock does (historic boutique = Historic boutique). city is an exact city string, not a substring. City options fold case the same way the lock does (Paris = paris). Istanbul ≠ İstanbul. Los Angeles ≠ Los Ángeles. brand is an exact brand tag, not a substring (Hilton ≠ Hilton Garden Inn). Brand options fold case the same way the lock does (Ibis = ibis). No fuzzy match. Amenity filter uses OSM/Wikidata tags or their labels only. minLat/minLng/maxLat/maxLng is a WGS84 bbox (all four required). chainId is an exact MEMBER_OF node id. hasSameAs=1 is houses with an OSM↔Wikidata merge — not a second listing. hasBrand=1 is houses with an OSM / Wikidata brand tag — not a franchise census. - Document titles: /hotels/geo?country=&city= names the locked country or city (a city miss names the miss and noindexes — Harbor will not invent a city). /hotels/amenities?amenity= names the seed type (an unknown tag noindexes — types stay 21). A hotel folio title is “{name} — hotel graph · {city, country}”. Not CNCF Harbor (goharbor.io). - Human browse: /hotels?q= lists matching graph nodes above houses. Leftover matching graph nodes after the top 8 chips name the leftover mix (Ibis leftover 3 names Ibis Styles Sevilla City Santa Justa · huazhu ibis · ibis Styles HOTELS; London leftover 3 names LHA London · London Shelton Hotel Ltd · London Zoo; Hilton leftover 14 is count only — leftover > 4, not leftover houses, not GET /api/graph/search leftover after 12). GET /api/graph/search stays leftover-free. A City chip prints ledger city tags plus in-city OSM / Wikidata source houses (Paris 2,629 city tags · OSM 2,478 · Wikidata 637 — not the 2,625 map bubble, not France OSM 3,313) plus the top amenity-tag mix (Paris wheelchair 576 amenity tags · OSM 576 · Wikidata 142 — not France Wi-Fi 759, not Paris Wi-Fi 505) plus the top lodging-type mix (Paris hotel 2,554 lodging-type tags · OSM 2,403 · Wikidata 637 — not city tags 2,629, not France hotel 6,626); its Geo hop prints map-bubble houses — do not fold those counts. A Country chip prints country hotels (France 6,736) plus in-country OSM / Wikidata source houses (France OSM 3,313 · Wikidata 4,225 — not a partition of 6,736, not worldwide OSM 47,981) plus the top amenity-tag mix (France Wi-Fi 759 amenity tags · OSM 759 · Wikidata 209 — not country hotels 6,736, not worldwide Wi-Fi 12,531) plus the top lodging-type mix (France hotel 6,626 lodging-type tags · OSM 3,203 · Wikidata 4,225 — Wikidata 4,225 is the same number as France country Wikidata, not the same unit; OSM 3,203 ≠ France OSM 3,313) — not city tags, not map bubbles, not OSM extracts. /hotels?q= Country find and /hotels/geo?metros=1&q= metro extract share q= — they are different slices. A Chain chip prints tagged houses, mapped % among those MEMBER_OF houses, MEMBER_OF OSM / Wikidata source houses, plus MEMBER_OF lodging-type and amenity tags with bySource, plus MEMBER_OF houses in the top country and city (Ibis hotel 162 lodging-type tags · OSM 161 · Wikidata 1 — 162 is the same number as tagged houses, not folio hotel 213; wheelchair 89 amenity tags · OSM 89 — not folio wheelchair 116; France 60 MEMBER_OF houses · OSM 60 — not folio France 63; Paris 43 MEMBER_OF houses · OSM 43 — not folio Paris 46; a map-bubble metro on that chip hops the OSM extract (Paris 2,056 — not MEMBER_OF 43); leftover MEMBER_OF countries after the top country on that chip name the leftover mix (Ibis 23 more MEMBER_OF countries — count only, not folio leftover 8, not country hotels 6,736; Travelodge leftover Ireland 2 · Spain 1); leftover MEMBER_OF cities after the top city on that chip name the leftover mix (Ibis 60 more MEMBER_OF cities — count only, not folio leftover 56, not Paris extract 2,056; Super Hotel leftover Osaka 4 + Osaka 432 extract · 札幌市 1); leftover MEMBER_OF amenity-tag types after the top amenity on that chip name the leftover mix (Ibis 6 more MEMBER_OF amenity-tag types — count only, not folio leftover after 8, not wheelchair 89, not tagged houses 12,531; 東横イン leftover Wheelchair access 10 · Air conditioning 4; Radisson Blu leftover Wheelchair 24 · Air conditioning 8 · Bar 3 · Restaurant 1)) — not a franchise census, not the folio brand-fallback walk (Ibis 162 ≠ 213; Ibis OSM 161 ≠ 162 tagged ≠ folio OSM 212). An Amenity chip prints tagged houses worldwide, mapped %, SAME_AS houses, brand-tagged, OSM / Wikidata source houses, lodging-type tags with bySource, the top country amenity-tag mix, and the top city amenity-tag mix on the exported 21 types — Wi-Fi OSM 12,531 is the same number as tagged houses, not the same unit, not worldwide OSM 47,981; hotel 10,545 lodging-type tags · OSM 10,545 · Wikidata 3,823 is the same mix as amenity folio selected.types, not tagged houses 12,531, not France hotel 6,626, not Ibis hotel 213; United States 1,342 amenity tags · OSM 1,342 · Wikidata 402 is the same mix as amenity folio selected.byCountry, not tagged houses 12,531, not France Wi-Fi 759, not Paris Wi-Fi 505; Paris 505 amenity tags · OSM 505 · Wikidata 98 is the same mix as amenity folio selected.byCity, not France Wi-Fi 759, not Paris city tags 2,629; a map-bubble metro on that chip hops the OSM extract (Paris 2,056 — not amenity tags 505); leftover amenity-tag countries after the top country on that chip name the leftover mix (Wi-Fi 60 more amenity-tag countries — count only, not tagged houses 12,531, not folio leftover 49, not France 6,736; Fitness leftover Spain 3 · Portugal 2 · Greece 1 · Turkey 1); leftover amenity-tag cities after the top city on that chip name the leftover mix (Wi-Fi 619 more amenity-tag cities — count only, not tagged houses 12,531, not folio leftover 608, not Paris extract 2,056; Laundry leftover Paris 1 + Paris 2,056 extract · Strasbourg 1 · Tokyo 1 · 台東区 1); leftover lodging types after the top type on those leftover leftover search amenity leftover leftover cities name the leftover mix (Laundry leftover Paris leftover 2 names hostel 47 · OSM 47 · guest_house 28 · OSM 28; Strasbourg leftover 1 names hostel 2 · OSM 2; Tokyo leftover 3 names hostel 103 · OSM 103 · guest_house 55 · motel 11; 台東区 leftover 2 names hostel 11 · OSM 11 · guest_house 3 · OSM 3; Elevator leftover Montevideo leftover 2 names hostel 8 · guest_house 2; Conference leftover 서울특별시 leftover 3 names guest_house 40 · hostel 20 · motel 7 — not leftover after 1 on leftover leftover amenity index leftover leftover cities (Paris hostel 47), not leftover after 1 on leftover leftover amenity folio leftover leftover cities (Valencia hostel 15), not leftover after 1 on amenity chip leftover lodging types (Wi-Fi leftover 4), not amenity tags (Paris Laundry 1)); leftover lodging types after the top lodging type on that chip name the leftover mix (Wi-Fi leftover 4 names hostel 1,211 · OSM 1,211 · guest_house 718 · motel 56 · luxury 1; Wheelchair leftover 3 names hostel 222 · guest_house 73 · motel 22; Parking leftover guest_house 1 — not folio leftover after 8, not tagged houses 12,531, not France hotel 6,626, not amenity types 21); do not fold 12,531 into France Wi-Fi 759 amenity tags, and do not fold Wi-Fi SAME_AS 7,872 into 13,902 merge edges. Geo lodging-type chips under a country lock print lodging-type tags plus OSM / Wikidata source houses among those tags (France hotel 6,626 lodging-type tags · OSM 3,203 source houses · Wikidata 4,225 source houses — Wikidata 4,225 is the same number as France country Wikidata, not the same unit; OSM 3,203 ≠ France OSM 3,313) — not country hotels (France 6,736) and not amenity tags (France Wi-Fi 759). A Paris lock is 2,554 lodging-type tags · OSM 2,403 · Wikidata 637 — Wikidata 637 is the same number as Paris city Wikidata, not the same unit; 2,554 ≠ 2,629 city tags ≠ 2,625 map bubble; OSM 2,403 ≠ Paris OSM 2,478. A Source chip prints source houses on Wikidata / OSM / Harbor seed — Wikipedia stays an extract, not a hotel source filter. The homepage source mix and ledger Source options name the same source houses (coverage.json on /). The homepage live-graph Wikidata chip names source houses (164,800) — not the 164,808 lodging-item target and not 201,008 hotels. The OSM chip already names source houses; OSM metros stay metros (~160), not OSM source houses (47,981). Do not fold Harbor seed 21 into amenity types 21. An empty house list names the next honest hop (matched tag, SAME_AS, amenity folio, or geo). A find with no matching graph node and no houses hops geo / amenity tags / tagged chains. A job SearchBox or /jobs catalog miss hops the typed spelling onto /hotels?q= plus geo / amenity tags / tagged chains — a job miss is not a graph miss. House names can match without a graph tag chip. A leftover quote does not dump the catalog. Active ledger filters are removable chips plus clear-all (hasBrand=1 is brand-tagged houses). City, brand, amenity, lodging-type, and source options under a country lock count houses in that country, not the global top lists. Ledger Type options print lodging-type tags (in-country under a lock; worldwide when open) — not country hotels and not amenity tags. Ledger Amenity options print amenity tags in-country, or tagged houses worldwide when open — do not fold 12,531 into France Wi-Fi 759. Ledger Country options print country hotels (France 6,736). Ledger City options print city tags. Ledger Brand options print brand tags (OSM / Wikidata — not a franchise census). Ledger Source options print source houses (Wikidata / OSM / Harbor seed — do not fold Harbor seed 21 into amenity types 21). Empty Country / City / Brand / Source options say All; empty Type / Amenity options say Any — the kicker already names the slice so the closed select does not clip All brand tags in France. Removable ledger chips print country hotels / city tags / brand tags / lodging-type tags / amenity tags (or tagged houses worldwide) / source houses — not a bare France or hotel. Visible folio breadcrumbs start at Harbor by Signalry. Compact lockup stacks by Signalry under Harbor on small screens. A ledger city hop next to the filters that is a coverage centroid says map bubble — not city tags (Marrakech 721 ≠ 731). A map-bubble metro also names the OSM extract hop (Paris 2,056 — not city tags 2,629, not the map bubble 2,625). Agadir still omits that extract hop. A Wi-Fi, source, lodging-type, or other slice omits those hops so 2,056 cannot fold onto Paris Wi-Fi 505. An unsliced country lock names the geo hop (France 6,736 country hotels — not city tags, not the map bubble, not an OSM extract). A Wi-Fi, source, lodging-type, or other slice omits that hop so 6,736 cannot fold onto France Wi-Fi 759. A city lock still omits that country hop. An ISO country code on the ledger lock resolves the same way the API lock does (?country=FR is France 6,736 country hotels plus the geo hop). An unsliced ledger document title names that lock (Hotels in France for ?country=FR and ?country=France; Hotels in Paris, France for an unsliced city lock) — a Wi-Fi or other slice keeps the generic title so 6,736 cannot fold onto France Wi-Fi 759; ?q=FR stays a find; Narnia stays a miss. countryHotels / geoCountryHref / countryHouseSources resolve that ISO the same way (FR is France 6,736 · OSM 3,313 — not zeros, not a miss). City helpers resolve the same index (Paris + FR is 2,629 city tags · OSM 2,478 · extract 2,056 — not zeros; London + CA still omits the UK extract). Country amenity and lodging-type helpers resolve it too (FR is France Wi-Fi 759 · hotel 6,626 — not zeros, not country hotels 6,736). JSON-LD breadcrumb sources write Harbor by Signalry, not a naked Harbor. Header Hotels / Buy sell pills hide below 380px so the lockup fits a 320 viewport. Document titles stay on qualifySeoTitle — hotel or JTBD context may still end · Harbor so we are not CNCF Harbor. OG image alts that crawlers and agents read go through qualifyOgAlt and name Harbor by Signalry. The wordmark token next to by Signalry stays Harbor. Chain folio lodging-type chips print lodging-type tags plus OSM / Wikidata source houses among those folio tags (Ibis hotel 213 lodging-type tags · OSM 212 source houses · Wikidata 52 source houses — 213 is the same number as folio houses, not the same unit, not MEMBER_OF 162; OSM 212 is the same number as folio OSM, not MEMBER_OF OSM 161). Chain folio amenity chips print amenity tags plus OSM / Wikidata source houses among those folio tags (Ibis wheelchair 116 amenity tags · OSM 116 source houses · Wikidata 27 source houses — OSM 116 is the same number as the tag count, not the same unit, not worldwide Wi-Fi 12,531, not France Wi-Fi 759). Ledger Type and Amenity options stay a number. Nav and footer name Harbor by Signalry — never a naked Harbor. /hotels/geo (country aliases, ?all=1, ?metros=1; unsliced geo names ledger city tags and map-bubble cities separately — bubbles are not the city-tag count; a geo country city chip prints ledger city tags, map-bubble houses, in-city OSM / Wikidata source houses, the top amenity-tag mix, the top lodging-type mix, and the OSM extract hop when the city is a map-bubble metro (Paris 2,056 hops the Overpass metro — not the city lock) separately — do not fold those counts (Paris OSM 2,478 ≠ 2,629 city tags ≠ 2,625 map bubble ≠ Paris OSM extract 2,056 ≠ France OSM 3,313; Paris wheelchair 576 amenity tags · OSM 576 · Wikidata 142 — not France Wi-Fi 759, not Paris Wi-Fi 505; Paris hotel 2,554 lodging-type tags · OSM 2,403 · Wikidata 637 — not city tags 2,629, not France hotel 6,626; Marrakech 731 ≠ 721 ≠ 764 extract); unsliced country cards print country hotels (France 6,736) plus OSM / Wikidata source houses (France OSM 3,313 · Wikidata 4,225 — not a partition of 6,736, not worldwide OSM 47,981, not worldwide Wikidata 164,800) plus the top amenity-tag mix in that country (France Wi-Fi 759 amenity tags · OSM 759 · Wikidata 209 — not country hotels 6,736, not worldwide Wi-Fi 12,531; Germany wheelchair 893 · OSM 893 · Wikidata 281) plus the top lodging-type mix (France hotel 6,626 lodging-type tags · OSM 3,203 · Wikidata 4,225 — Wikidata 4,225 is the same number as France country Wikidata, not the same unit; OSM 3,203 ≠ France OSM 3,313); leftover lodging types after the top type on those cards name the leftover mix (France leftover 2 names hostel 69 · OSM 69 · guest_house 41 · OSM 41; Germany leftover 2 names hostel 110 · OSM 110 · guest_house 77 · OSM 77; Japan leftover 3 names hostel 258 · OSM 258 · guest_house 216 · OSM 216 · motel 16 · OSM 16; United States leftover 13 is count only — leftover > 4, not leftover after 8 on the geo lock); leftover amenity-tag types after the top amenity on those cards name the leftover mix (France leftover 15 is count only — leftover > 4, not leftover after 12 on the geo lock, not Wi-Fi 759; Argentina leftover 3 names Wheelchair access 25 · OSM 25 · Air conditioning 18 · Bar 7; Chile leftover Breakfast 1 · OSM 1; Colombia leftover 4 names Wheelchair 10 · Air conditioning 6 · Bar 2 · Swimming pool 1) plus city tags, map-bubble houses, and in-city source houses on their map-bubble cities plus the top amenity-tag mix in that city (Paris wheelchair 576 amenity tags · OSM 576 · Wikidata 142 — not France Wi-Fi 759, not Paris Wi-Fi 505, not city tags 2,629) plus the top lodging-type mix in that city (Paris hotel 2,554 lodging-type tags · OSM 2,403 · Wikidata 637 — not city tags 2,629, not the map bubble 2,625, not France hotel 6,626); leftover lodging types after the top type on those country-card city rows name the leftover mix (Paris leftover 2 names hostel 47 · OSM 47 · guest_house 28 · OSM 28; Nice leftover 2 names hostel 6 · OSM 6 · guest_house 3 · OSM 3; Marseille leftover 2 names hostel 5 · OSM 5 · guest_house 2 · OSM 2; Lyon leftover 2 names hostel 6 · OSM 6 · guest_house 3 · OSM 3 — not leftover after 8 on the geo lock, not leftover after 1 on the country card (France hostel 69)); leftover amenity-tag types after the top amenity on those country-card city rows name the leftover mix (Paris leftover 12 is count only — leftover > 4, not leftover after 12 on the geo lock, not wheelchair 576; Nice leftover 3 names Wheelchair access 23 · OSM 23 · Air conditioning 7 · Bar 2; Marseille leftover 4 names Wheelchair 12 · Air conditioning 10 · Bar 1 · Breakfast 1; Lyon leftover 7 is count only — not leftover after 1 on the country card (France leftover 15)); plus the OSM extract hop when the city is a map-bubble metro (Paris 2,056 OSM extract hops the Overpass metro — not city tags 2,629, not the map bubble 2,625); cards list four map-bubble cities and name the leftover hop (France 3 more map-bubble cities hops the country lock; Bordeaux 90 city tags · 90 map bubble · OSM 64 source houses · Wikidata 45 source houses · Wi-Fi 15 amenity tags · OSM 15 · hotel 84 lodging-type tags · OSM 58 · Wikidata 45 hops the Bordeaux city lock; 45 OSM extract hops the Bordeaux Overpass extract — hotel 84 ≠ city tags 90 ≠ France hotel 6,626; Wikidata 45 is the same number as the extract, not the same unit; leftover lodging types after the top type on those leftover leftover cities name the leftover mix (Bordeaux leftover 2 names guest_house 5 · OSM 5 · hostel 1 · OSM 1; Strasbourg leftover 1 names hostel 2 · OSM 2; Toulouse leftover 1 names hostel 2 · OSM 2; Bengaluru leftover 2 names hostel 7 · OSM 7 · guest_house 5 · OSM 5; 札幌市 leftover 2 names hostel 2 · OSM 2 · motel 1 · OSM 1; 京都市 leftover 1 names hostel 3 · OSM 3; 台東区 leftover 2 names hostel 11 · OSM 11 · guest_house 3 · OSM 3; Chūō-ku leftover 0 hides the hop — not leftover after 8 on the geo lock, not leftover after 1 on the country card (France hostel 69), not leftover after 1 on the country-card city row (Paris hostel 47)); leftover amenity-tag types after the top amenity on those leftover leftover cities name the leftover mix (Bordeaux leftover 4 names Wheelchair access 12 · OSM 12 · Wikidata 4 · Air conditioning 3 · OSM 3 · Wikidata 1 · Bar 2 · Card payment 2; Strasbourg leftover 7 is count only; Toulouse leftover 2 names Wheelchair access 5 · OSM 5 · Wikidata 2 · Swimming pool 1 · OSM 1; Bengaluru leftover 2 names Air conditioning 3 · OSM 3 · Wheelchair access 2 · OSM 2; 札幌市 leftover 4 names Wheelchair 28 · Air conditioning 11 · Card payment 8 · Bar 1; 京都市 leftover 4 names Air conditioning 5 · Wheelchair 2 · Bar 1 · Restaurant 1; 台東区 leftover 5 is count only; Chūō-ku leftover 3 names Wi-Fi 7 · OSM 7 · Wikidata 7 · Air conditioning 4 · Card payment 3 — not leftover after 12 on the geo lock, not leftover after 1 on the country card (France leftover 15), not leftover after 1 on the country-card city row (Paris leftover 12)); not France Wi-Fi 759, not country hotels 6,736, not Paris OSM extract 2,056; India leftover Bengaluru hops the city lock; Germany 12 more omits a name dump; Morocco omits the hop) — do not fold 6,736 into city tags, map bubbles, or OSM extracts; Agadir stays off the card; Dense OSM metro chips print OSM extract houses (Marrakech 764), not city tags (731), not the map bubble (721), and not country hotels (France 6,736) — hop ?metros=1&q=; leftover metros hop the extract browse (148 more OSM extracts → /hotels/geo?metros=1 — not a name dump, not city tags, not country hotels); leftover OSM extracts after the top 16 on /hotels/geo name the leftover mix (144 more OSM extracts hop ?metros=1 — count only, not leftover after 12 on coverage (148), not city tags, not country hotels); leftover ledger cities after the map-bubble chips on a country lock name the leftover mix (France 1,632 more ledger cities — count only, leftover > 4, not leftover after 4 on the country card, not city tags 2,629, not the map bubble 2,625, not country hotels 6,736; Latvia leftover 3 names Riga 20 · Jēkabpils 1 · Jelgava 1; Cambodia leftover 4 names Siem Reap 19 · Battambang 5 · Kampong Cham Municipality 3 · Sihanoukville Province 1; Agadir stays off the Morocco name dump); leftover amenity-tag types after the top amenity on those leftover ledger cities name the leftover mix (Riga leftover 2 names Card payment 3 · OSM 3 · Wikidata 2 · Wheelchair access 1 · OSM 1; Jēkabpils leftover 0 hides the hop; Cambodia leftover ledger cities leftover 0 hide the hop — not leftover after 12 on the geo lock, not leftover after 1 on the leftover leftover city (Bordeaux leftover 4)); leftover amenity-tag types after the top 12 on a geo lock name the leftover mix (France leftover 4 names Swimming pool 2 · OSM 2 · Elevator 1 · Kitchen 1 · Parking 1; United States leftover 3 names Laundry 1 · Sauna 1 · Spa 1; Paris leftover 1 names Laundry 1 — not leftover worldwide 21 types, not country hotels 6,736, not worldwide Wi-Fi 12,531); leftover lodging types after the top 8 on a geo lock name the leftover mix (United States leftover 6 more lodging types — count only, leftover > 4, not leftover worldwide lodging types, not country hotels 11,806, not United States hotel 11,263, not amenity tags; France leftover 0 hides the hop); leftover lodging types after the top type on a geo lock city chip name the leftover mix (Paris leftover 2 names hostel 47 · OSM 47 · guest_house 28 · OSM 28; Berlin leftover 2 names hostel 81 · OSM 81 · guest_house 57 · OSM 57; Marrakech leftover 2 names hotel 300 · OSM 294 · Wikidata 10 · hostel 48 · OSM 48; London Canada leftover 0 hides the hop); leftover amenity-tag types after the top amenity on a geo lock city chip name the leftover mix (Paris leftover 12 is count only — leftover > 4, not leftover after 12 on the geo lock; Nice leftover 3 names Wheelchair access 23 · OSM 23 · Air conditioning 7 · Bar 2; Marseille leftover 4 names Wheelchair 12 · Air conditioning 10 · Bar 1 · Breakfast 1; Marrakech leftover 4 names Air conditioning 18 · Wheelchair 14 · Restaurant 3 · Bar 1); Country find and metro extract share q= — do not fold those slices; a country/city slice names mapped %, SAME_AS houses, brand-tagged count, and OSM / Wikidata source houses (France OSM 3,313 ≠ 6,736 country hotels ≠ worldwide OSM 47,981; Wikidata 4,225 ≠ 164,800); a geo city lock is an exact city name, not a substring (port ≠ Portland; Paris ≠ Bienville Parish); a geo country lock resolves ISO codes from houses (?country=FR is France 6,736 — not a miss); ?q=FR stays a find; a geo country All hop names country hotels (France 6,736 — not city tags, not the map bubble, not an OSM extract); a geo city All hop names city tags (Paris 2,629 — not the map bubble 2,625, not Paris OSM extract 2,056); a geo city miss will not dump the country pins or reuse the country hotel count in the lede; amenity chips under a city lock count houses in that city plus OSM / Wikidata source houses among those tags, not the country; coverage bubbles stay on the unsliced /hotels and /hotels/geo — a ledger filter, chain country lock, or geo miss without pins will not dump the world), /hotels/chains (top tagged chains only — do not treat as a complete franchise list; index cards print MEMBER_OF tagged houses, mapped %, MEMBER_OF OSM / Wikidata source houses, MEMBER_OF lodging-type / amenity tags with bySource, and the top MEMBER_OF country / city — not the folio walk (Ibis 162 ≠ 213; Ibis OSM 161 ≠ 212; Ibis hotel 162 ≠ folio hotel 213; Ibis wheelchair 89 ≠ folio 116; Ibis France 60 MEMBER_OF ≠ folio France 63; Ibis Paris 43 MEMBER_OF ≠ folio Paris 46); a map-bubble metro on those cards hops the OSM extract (Paris 2,056 — not MEMBER_OF 43); leftover MEMBER_OF countries after the top country on those cards name the leftover mix (Ibis 23 more MEMBER_OF countries — count only, not folio leftover 8, not country hotels 6,736, not worldwide MEMBER_OF 162; 東横イン leftover France 1 · Germany 1 · South Korea 1); leftover MEMBER_OF cities after the top city on those cards name the leftover mix (Ibis 60 more MEMBER_OF cities — count only, not folio leftover 56, not Paris extract 2,056; Super Hotel leftover Osaka 4 + Osaka 432 extract · 札幌市 1); leftover MEMBER_OF amenity-tag types after the top amenity on those cards name the leftover mix (Ibis 6 more MEMBER_OF amenity-tag types — count only, not folio leftover after 8, not wheelchair 89, not tagged houses 12,531; 東横イン leftover Wheelchair access 10 · Air conditioning 4; Radisson Blu leftover Wheelchair 24 · Air conditioning 8 · Bar 3 · Restaurant 1); leftover tagged chains after the top 80 name the leftover mix (3,828 more tagged chains — count only, not leftover houses, not MEMBER_OF 162, not folio 213; q=hotel leftover 862 is count only and the lede names 942 matching chains); GET /api/graph/chains list items stay MEMBER_OF tagged houses only — no types / amenities / countries / cities; a country slice hops geo; a folio names MEMBER_OF tagged houses next to folio houses when the brand-fallback walk is wider (Ibis 162 ≠ 213); Hilton Worldwide stays 609 on both; a folio names mapped / source / lodging / amenity density and prints folio source houses next to MEMBER_OF when those mixes differ (Ibis OSM 212 ≠ 161; Wikidata 52 ≠ 1); lodging-type chips print lodging-type tags plus OSM / Wikidata source houses among those folio tags (Ibis hotel 213 · OSM 212 · Wikidata 52 — 213 is the same number as folio houses, not MEMBER_OF 162); amenity chips print amenity tags plus OSM / Wikidata source houses among those folio tags (Ibis wheelchair 116 amenity tags · OSM 116 source houses · Wikidata 27 source houses — OSM 116 is the same number as the tag count, not the same unit, not worldwide Wi-Fi 12,531, not France Wi-Fi 759); an empty country lock is a country miss, not a missing chain; the chain map will not dump world bubbles), /hotels/amenities (seed types only — unsliced cards and ?amenity= name mapped % / SAME_AS houses / brand-tagged / OSM·Wikidata source houses / the top lodging-type mix / the top country amenity-tag mix / the top city amenity-tag mix when those tags exist (Wi-Fi OSM 12,531 is the same number as tagged houses, not the same unit, not worldwide OSM 47,981; Wi-Fi hotel 10,545 lodging-type tags · OSM 10,545 · Wikidata 3,823 is the same mix as the folio and a search chip, not tagged houses 12,531, not France hotel 6,626; wheelchair hotel 6,727 · OSM 6,727 · Wikidata 2,453 is not 7,044 tagged houses; Wi-Fi United States 1,342 amenity tags · OSM 1,342 · Wikidata 402 is the same mix as the folio and a search chip, not tagged houses 12,531, not France Wi-Fi 759, not Paris Wi-Fi 505; wheelchair Germany 893 · OSM 893 · Wikidata 281 is not Wi-Fi United States 1,342 and not 7,044 tagged houses; Wi-Fi Paris 505 amenity tags · OSM 505 · Wikidata 98 is the same mix as the folio and a search chip, not France Wi-Fi 759, not Paris city tags 2,629; a map-bubble metro on those cards hops the OSM extract (Paris 2,056 — not amenity tags 505); wheelchair Paris 576 · OSM 576 · Wikidata 142 is not Wi-Fi Paris 505 and not 7,044 tagged houses; GET /api/graph/amenities list items stay tagged houses only — no types / countries / cities); an amenity find miss hops the typed spelling onto /hotels?q= plus geo / tagged chains; country chips print amenity tags in that country plus OSM / Wikidata source houses among those tags (France Wi-Fi 759 amenity tags · OSM 759 source houses · Wikidata 209 source houses — OSM 759 is the same number as the tag count, not the same unit, not worldwide Wi-Fi OSM 12,531, not France OSM 3,313) — not country hotels (France 6,736); leftover amenity-tag countries after the top 12 name the leftover mix (Wi-Fi 49 more amenity-tag countries — count only, not tagged houses 12,531, not France 6,736; Pets leftover Denmark · Poland · Portugal 1 amenity tag each); leftover amenity-tag countries after the top country on unsliced cards name the leftover mix (Wi-Fi 60 more amenity-tag countries — count only, not tagged houses 12,531, not folio leftover 49, not France 6,736; Fitness leftover Spain 3 · Portugal 2 · Greece 1 · Turkey 1); leftover amenity-tag cities after the top city on unsliced cards name the leftover mix (Wi-Fi 619 more amenity-tag cities — count only, not tagged houses 12,531, not folio leftover 608, not Paris extract 2,056; Laundry leftover Paris 1 + Paris 2,056 extract · Strasbourg 1 · Tokyo 1 · 台東区 1); leftover lodging types after the top type on those leftover leftover amenity index leftover leftover cities name the leftover mix (Laundry leftover Paris leftover 2 names hostel 47 · OSM 47 · guest_house 28 · OSM 28; Strasbourg leftover 1 names hostel 2 · OSM 2; Tokyo leftover 3 names hostel 103 · OSM 103 · guest_house 55 · motel 11; 台東区 leftover 2 names hostel 11 · OSM 11 · guest_house 3 · OSM 3; Elevator leftover Montevideo leftover 2 names hostel 8 · guest_house 2; Conference leftover 서울특별시 leftover 3 names guest_house 40 · hostel 20 · motel 7 — not leftover after 1 on leftover leftover amenity folio leftover leftover cities (Valencia hostel 15), not leftover after 1 on amenity index leftover lodging types (Wi-Fi leftover 4), not amenity tags (Paris Laundry 1)); leftover lodging types after the top lodging type on unsliced cards name the leftover mix (Wi-Fi leftover 4 names hostel 1,211 · OSM 1,211 · guest_house 718 · motel 56 · luxury 1; Wheelchair leftover 3 names hostel 222 · guest_house 73 · motel 22; Parking leftover guest_house 1 — not folio leftover after 8, not tagged houses 12,531, not France hotel 6,626, not amenity types 21); city chips print amenity tags in that city plus OSM / Wikidata source houses among those tags (Paris Wi-Fi 505 amenity tags · OSM 505 · Wikidata 98 — not France Wi-Fi 759, not Paris city tags 2,629, not the map bubble 2,625) plus the OSM extract hop when the city is a map-bubble metro (Paris 2,056 hops the Overpass metro — not amenity tags 505); leftover amenity-tag cities after the top 12 name the leftover mix (Wi-Fi 608 more amenity-tag cities — count only, not tagged houses 12,531; Spa leftover Valencia, Spain 1 amenity tag); leftover lodging types after the top type on those leftover leftover amenity folio cities name the leftover mix (Spa leftover Valencia leftover 2 names hostel 15 · OSM 15 · guest_house 4 · OSM 4 — not leftover after 8 on amenity folio lodging types, not leftover after 1 on amenity index leftover lodging types, not leftover after 1 on the country-card city row (Paris hostel 47), not amenity tags (Valencia Spa 1)); lodging-type chips print lodging-type tags among amenity-tagged houses plus OSM / Wikidata source houses among those type tags (Wi-Fi hotel 10,545 lodging-type tags · OSM 10,545 · Wikidata 3,823 — not tagged houses 12,531, not France hotel 6,626, not Ibis hotel 213, not amenity types 21); /hotels/amenities?q= amenity-type find and /hotels?q= Country find share q= — they are different slices; geo amenity chips under a country lock print amenity tags plus OSM / Wikidata source houses among those tags (France Wi-Fi 759 amenity tags · OSM 759 source houses · Wikidata 209 source houses — OSM 759 is the same number as the tag count, not the same unit, not worldwide Wi-Fi OSM 12,531, not France OSM 3,313); a city lock uses the same unit on the in-city mix (Paris Wi-Fi 505 ≠ France Wi-Fi 759 ≠ Paris city tags 2,629); not country hotels; geo lodging-type chips print lodging-type tags plus OSM / Wikidata source houses among those tags (France hotel 6,626 · OSM 3,203 · Wikidata 4,225 — Wikidata 4,225 is the same number as France country Wikidata, not the same unit; OSM 3,203 ≠ France OSM 3,313; Paris hotel 2,554 · OSM 2,403 · Wikidata 637 — not Paris city tags 2,629, not the map bubble 2,625), not country hotels and not amenity tags; Ledger Type options stay a number; chain folio country chips print folio houses (brand-fallback walk) plus OSM / Wikidata source houses among those folio houses, and MEMBER_OF houses plus MEMBER_OF source houses when those mixes differ (France Ibis 63 folio · OSM 63 · Wikidata 3 · 60 MEMBER_OF · OSM 60 MEMBER_OF source houses — OSM 63 is the same number as folio houses, not the same unit, not MEMBER_OF OSM 60, not Ibis folio OSM 212) — not country hotels (France 6,736) and not worldwide MEMBER_OF (Ibis 162); chain folio city chips print folio houses in that city plus OSM / Wikidata source houses among those folio houses, and MEMBER_OF when those counts differ (Ibis Paris 46 folio · OSM 46 · Wikidata 3 · 43 MEMBER_OF — not France Ibis 63, not Ibis folio 213, not Paris city tags 2,629, not the map bubble 2,625) plus the OSM extract hop when the city is a map-bubble metro (Paris 2,056 hops the Overpass metro — not folio houses 46); leftover folio cities after the top 12 name the leftover mix (Ibis 56 more folio cities — count only, not MEMBER_OF 162, not folio 213); leftover folio countries after the top 16 name the leftover mix (Ibis 8 more folio countries hop ?all=1 — count only, not country hotels 6,736, not worldwide MEMBER_OF 162, not Ibis folio 213; Westin leftover United Arab Emirates 1 folio house · OSM 1); leftover folio amenity-tag types after the top 8 chips name the leftover mix (Hilton leftover 2 names Restaurant 2 · OSM 2 · Wikidata 1 · 1 MEMBER_OF · Spa 1 · OSM 1; Best Western leftover Card payment 1 · OSM 1; Ibis leftover 0 hides the hop)). Map pins: mouse click selects the card; Enter opens the house. A house card hops the country on geo. Coverage SAME_AS is merge edges — homepage and the hotels coverage panel name edges, not the hasSameAs=1 list length; homepage city count is city tags, not map-bubble cities; the hotels coverage By country pills print country hotels plus in-country OSM / Wikidata source houses plus the top amenity-tag mix plus the top lodging-type mix (France OSM 3,313 ≠ 6,736 — not a partition, not worldwide OSM 47,981; France Wi-Fi 759 amenity tags · OSM 759 · Wikidata 209 — not country hotels 6,736, not worldwide Wi-Fi 12,531; France hotel 6,626 lodging-type tags · OSM 3,203 · Wikidata 4,225 — Wikidata 4,225 is the same number as France country Wikidata, not the same unit; OSM 3,203 ≠ France OSM 3,313); leftover countries hop geo browse (199 more countries → /hotels/geo — not a name dump, not Unknown 1,748, not leftover OSM extracts 148); leftover countries after the top 60 on /hotels/geo name the leftover mix (145 more countries hop ?all=1 — count only, not leftover after 10 on coverage (199), not leftover after 8 on homepage (201), not coverage.json 209 countries, not Unknown 1,748); homepage By country pills stay country hotels from coverage.json only; leftover homepage countries hop geo browse (201 more countries → /hotels/geo — not a name dump, not Unknown 1,748, not leftover OSM extracts 148); a geo or ledger SAME_AS slice is houses with a partner.- HAS_AMENITY comes from OSM tags (wifi, wheelchair, parking, restaurant, bar, pool, spa, gym, ac, pets, conference, breakfast, sauna, laundry, kitchen, elevator, cards, smoking=no, terrace/outdoor_seating, room_service, bicycle_parking, EV charging, shuttle, business centre) and Wikidata P2848 / P912 mapped QIDs. Not a complete inventory. - Chains: OSM brand / brand:en / network / franchise + brand:wikidata; Wikidata P127/P749/P137/P176. Brand fill is sparse (~6% on this snapshot) — not a franchise census. - SAME_AS is an OSM↔Wikidata merge, not a second house. It can copy OSM amenities onto the Wikidata canonical hotel. Slim snapshot drops reconstructable LOCATED_IN / IN_COUNTRY / ASSERTED_BY / NEAR; /api/graph/subgraph rebuilds them. - Do not invent amenities, chain membership, or confidential prices. Buy/sell rules: never invent a confidential deal price as fact. Never claim a Harbor estimate is a licensed appraisal. Label every assumption. Deal Frame is a framing tool stored in the browser — Harbor does not host the file. Implied cap only when user-supplied NOI and a disclosed tape price both exist. Cap-rate bands are Harbor research defaults, not HVS/PKF/CBRE proprietary numbers. Host FY2025 Westin Cincinnati + Metro Center is $237M combined — do not split. Sheraton Parsippany $15M is under contract, not closed. ## Stable hotel graph IDs - /hotels/{id} (wd-Q…, osm-n-…, harbor-…, desk slugs) - /hotels/geo - /hotels/chains - /hotels/chains/{id} - /hotels/amenities ## Stable URL pattern - /jobs/{slug} - /providers/{slug} - /cases/{slug} - /hotels/{id} - /hotels/{id}/estimate - /hotels/geo - /hotels/chains - /hotels/chains/{id} - /hotels/amenities - /buy-sell - /buy-sell?hotel={id} - /buy-sell/frame - /buy-sell/frame?hotel={id} - /buy-sell/deals - /buy-sell/estimate?hotel={id} (canonical house worksheet is /hotels/{id}/estimate) - /buy-sell/blotter?hotel={id} - /buy-sell/compare?hotel={id} - /buy-sell/due-diligence?hotel={id} - /buy-sell/explainers?hotel={id} - /buy-sell/sell-side?hotel={id} - /packs/sale-ready?hotel={id} - /buy-sell/transactions/{id} (named singles title “{house} · {year} tape”; combined PSAs stay combined) - /buy-sell/transactions?year={year}&priced=1 (historical cited corpus; not the morning blotter) - /buy-sell/transactions?year={year}&priced=1&confidence=public_filing - /buy-sell/brokers - /buy-sell/brokers?hotel={id} - /buy-sell/brokers/{id} - /buy-sell/brokers/{id}?hotel={id} - /buy-sell/firms/{id} - /buy-sell/firms/{id}?hotel={id} - /buy-sell/markets/{id} - /buy-sell/markets/{id}?hotel={id} IDs equal slugs. Prefer slugs over display names.