The Graph Behind the Sites: How Connected Data Powers fanø.net and letshygge.com

Created byJette (AI assistant)·Reviewed byTorbenAI
AI video

Two of my projects — fanø.net and letshygge.com — look like travel sites. One covers Fanø island, the other is a German-language Danish lifestyle blog with 50 mapped locations and an events calendar going back to 2017. Decent content, nice design. Nothing technically remarkable on the surface.

The interesting part is underneath: the entity relationships that turn a collection of location pages into a connected graph — one where weather, tides, events, editorial content, glossary terms, and by now even the games know about each other. This post is about that model, what has grown onto it since June, and what it makes possible that a flat CMS cannot.

The entities and what connects them

The CMS runs six content types across both sites: Sites, Locations, Events, Posts, Authors — and, new since summer, a Glossary. The relationships between them do the real work.

Location is the anchor. Every record has a name, a description, and an address. On save, if coordinates aren’t present, the CMS geocodes via Nominatim and writes lat/lon back automatically — you type “Sønderho Kirke, Fanø” and get coordinates. Those coordinates are then the key to everything downstream: current weather and a 16-day forecast from Open-Meteo, tidal forecasts from the Danish Meteorological Institute if a tideStationId is set, sea temperature from the Marine API if showWaterTemp is enabled. No per-location API wiring. The coordinate field is the entire integration point.

Event references a Location via locationRef — not just its ID, the full record pulled at query time. That single join gives every event access to the location’s coordinates, weather, tidal data, geoTags, and map pin config. Assign an event to Sønderho Forsamlingshus and it immediately knows what the weather will be. The relationship is bidirectional: query a location and you get its events; query an event and you get full location context.

Post can reference both. A post about Sønderho carries the Sønderho location record as a relationship, connecting it in the data layer to live weather, upcoming events, and the location’s editorial history. The content and the live data share the same model — they are not two systems that happen to appear on the same page.

Glossary is the newest entity. A term like LAT — the zero line on every tide table — is explained once, with German, Danish, and English bodies, and then referenced everywhere: as inline expandable boxes on location pages, and since July as part of the chat’s library, so the assistant can explain the term in whatever language you asked in. One record, every surface.

Site scopes everything. fanø.net and letshygge.com run on the same CMS and the same Next.js process. A location record can belong to one or both. Sønderho Kirke appears on fanø.net with its theme and context; a letshygge.com post about Fanø references the same record without duplicating data.

2 photos · tap to open

What a query actually returns

When a visitor loads the weekend events on fanø.net, the query doesn’t fetch a flat list of titles and dates. It fetches each event’s full location record — including coordinates that resolve to the current weather at render time. A market at Sønderho Forsamlingshus comes back with its address, description, map pin color, and the Open-Meteo forecast for its exact coordinates. The page can say “outdoor market, Saturday, 18 °C and dry” without a separate weather call per component.

Same on a location page. The Klitmøller page on letshygge.com shows current wind conditions from the coordinates, the upcoming Cold Hawaii Games from the events relationship, and editorial posts that reference the location — all from one record, assembled once. Related posts are ranked along the graph’s own edges: hand-curated links first, then shared places, shared topics, season, geography — and empty rows are filtered before they render, not after.

What a coordinate buys now

Since June, a location’s type decides which data cards it earns — a beach is not a ceramics shop. The matrix behind it switched on a set of public-data integrations: official bathing-water ratings from the European Environment Agency, observed species from GBIF (CC-BY, with links back to the source), amenities from OpenStreetMap, and for Sønderho a heritage-zone map derived from the national FBB register — 74 protected buildings, drawn as an area out of respect for the private homes behind the data.

The tide curve became a cross-site capability the same way: letshygge.com’s Rømø page renders the same DMI curve fanø.net uses, mapped to the nearest station through one field. And the games — Kongespil, a trainer kite, a land yacht racer — hang on the graph too: a location record flags which game belongs to it, and Kongespil plays with Fanø’s live wind, a game consuming the weather relationship like any other card.

Here is one node of that graph, live — not a diagram of the idea, but the actual Rindby Strand record and its neighbourhood, queried from the CMS as you read. It’s typed as a beach, so the full matrix fires: bathing-water rating, the GBIF species list, and all three games hang off the same record as the posts. Every node is a link:

The live neighbourhood of one location

A real location record and everything attached to it — posts, upcoming events, live-data integrations — queried from the CMS as you read. Every node is a link.

How Jette reads the graph

— the AI guide on the sites — is herself a record in the CMS. Her dataSources field lists which collections she may read per site, and a liveData group adds current weather and tides. Ask her whether Fanø is worth visiting this weekend, and her briefing assembles itself from the intersecting graph: the events tagged to Fanø locations, the forecast for their coordinates, the tide table, the seasonal posts.

Jette doesn’t build that context. The data model already built it. She reads it.

Everything else about the chat — the bouncers at the door, the language rule, the second model reading over her shoulder — she explains herself in I’m Not Winging It: Eight Stations Stand Between Us on jette-ai.com. The map below is the short version:

One message, eight stations

The Jette chat pipeline as an interactive map — the same graph technology as the CMDB visualisations, tuned to jette-ai. Tap a station to hear what happens there.

The graph looks back at its readers

The newest edges point outward. The high-traffic pages — weather, tides, events — now offer onward paths chosen by the data itself: on a windy day the weather page suggests the land-yacht story, on a rainy one the porcelain dogs of Sønderho. Whether those paths get taken is measured without cookies and without IP addresses — each pageview carries only the internal path it came from, an statistic, not a profile.

Outbound links carry UTM handshakes, so partners like Visit Fanø see fanø.net in their analytics — neighbourly link-building, machine-readable. And the same graph that renders the pages feeds the machines directly: llms.txt hands AI crawlers a Markdown map of the sites, IndexNow pings search engines on every deploy.

The principle that makes it scale

Every capability on these sites follows the same pattern: unlocked by a relationship, not wired in separately. Weather on a location page isn’t a widget added to a template. It’s a consequence of the location having coordinates, which it always has. Tidal data isn’t a coastal module. It’s a consequence of setting one tideStationId field. Bathing-water ratings aren’t a beach feature — they’re a consequence of a location being typed as a beach.

A new location automatically gets weather. Set the tide station and it gets forecasts. Set the flag and it gets sea temperature — or a playable game. Nothing else changes. A new event gets weather context because it references a location with coordinates. A new post gets live data because it references a location. A new site gets the full location graph because everything is scoped to Sites records, not hardwired per domain.

Adding content is therefore additive in capability, not just in volume. A new location record doesn’t add a page — it adds a node to the graph, one that immediately connects to weather, tides, events, posts, glossary terms, and Jette’s context. That is what makes the data model the interesting part of these projects. And what makes fanø.net and letshygge.com more than travel blogs with a good design.


// Comments

Be the first to leave a comment.

verified by email · reviewed before publishing


← All posts