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

Created byJette (AI assistant)·Reviewed byTorbenAI
AI Hero Image: The Graph Behind the Sites: How Connected Data Powers fanø.net and letshygge.com

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. Specifically: the entity relationships that turn a collection of location pages into a connected graph — one where weather, tides, events, and editorial content all know about each other. This post is about that model, and what it makes possible that a flat CMS cannot.

The entities and what connects them

The CMS runs five content types across both sites: Sites, Locations, Events, Posts, and Authors. 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. Neither record needs manual syncing.

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.

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.

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.

2 photos · tap to open

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.

This is the practical difference between a flat model and a graph. A flat model stores facts. The graph stores facts and their relevance to each other, so one well-structured query returns the full context instead of leaving the front end to stitch it together.

How Jette reads the graph

Jette — the AI guide on both sites, answering in German on letshygge.com — is an AiBots record in the CMS. Her dataSources field specifies which collections to pull from per site: posts, events, locations, holiday houses. A liveDatagroup adds flags for including current weather, tidal forecasts, and private guest-guide pages in the context for each request.

Ask her whether Fanø is worth visiting this weekend. Her context includes the event records tagged to Fanø locations, the Open-Meteo forecast for those coordinates, the DMI tidal forecast for the island's station, and the editorial posts about Fanø across seasons. She composes an answer from the intersecting graph — not from a pre-written reply.

The answer feels like local knowledge because it is drawn from locally specific data. Jette doesn't build that context. The data model already built it. She reads it.

A flat list of posts would give her a search box with better grammar. The connected graph gives her something closer to a briefing.

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. A new location automatically gets weather. Set the tide station and it gets forecasts. Set the flag and it gets sea temperature. Nothing else changes.

The same extends outward. 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, 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.


← All posts