Angkor Now is a tourism & culture guide for Cambodia’s temple town: events, venues, festivals, maps and guides. Behind its quiet editorial surface sits an autonomous ingestion pipeline that reads the web, extracts structure with an LLM, de-duplicates, and stages everything for a human before it ever goes live.

Siem Reap’s nightlife, events and venue scene lives scattered across Facebook pages, partner listings and word-of-mouth. No single source is complete, none are structured, and most are out of date within a week.
Angkor Now’s premise: a city guide that maintains itself. The site continuously reads those messy sources, uses a language model to pull clean structured records out of them, and routes everything through automated de-duplication and a single human approval gate before publishing, so the public site stays trustworthy while the grind stays automated.
The result is a fast, warm, editorial product that reads like it has a full newsroom behind it, built and sponsored by AI Boffin Hub as a functional demonstrator of exactly that idea.
Cormorant Garamond headlines, warm paper, a forest-and-turmeric palette and theme switching: every surface is editorial first, database second. A tour of what a visitor actually sees.

The default question a traveller asks, answered first. A timezone-correct timeline of tonight’s events, all-day then by start time, with category and price tags inline, rolling straight into “coming up next” for tomorrow.

The full directory of upcoming events with faceted filtering by category, date and venue. Each record is an AI-extracted, human-approved entry: recurring nights, ticketed shows and free meetups all normalised into one schema.

The same event corpus, pivoted into a monthly calendar for trip planning. Days light up with what’s happening; click through to the day or the event. Built from the identical prerendered data, with no second source of truth.

A browsable venue directory across bars, restaurants, cafés, music and entertainment venues. Each has its own prerendered detail page, opening hours, neighbourhood and a generated QR code for sharing on the ground.

All 176 venues plotted on a MapLibre GL map over CARTO tiles, with marker clustering, category-coloured pins, an “Open Now” filter and a neighbourhoods overlay. The side rail and map stay in sync as you filter and search.

Hand-shaped guides (the best rooftop bars, apsara dance, getting around, family-friendly days, healthcare & emergencies) that wrap the structured data in human context. This is where the machine-run guide still reads like a person wrote it.

One search box across venues, events and guides, with suggestion chips for common intents: cocktail bar, apsara dance, kandal village, festival. Below it, a persistent emergency band keeps the Royal Angkor Hospital line one glance away.
The polish a traveller never notices but always benefits from: correctness, speed and resilience baked into the architecture.
All dates normalise to Asia/Phnom_Penh at intake, so “tonight” means tonight in Siem Reap regardless of where the visitor or the server sits.
An exact key match catches re-scrapes; a fuzzy title-date-venue similarity score catches the same event described two different ways across sources.
MapLibre GL clusters hundreds of geocoded pins into readable groups, recolouring and recounting live as you zoom, pan, filter by category or toggle open-now.
SvelteKit prerenders every route to static HTML on deploy: instant first paint, no cold database calls in the request path, trivially cacheable on a CDN.
A three-accent theme system (forest, turmeric, oxblood) plus light/dark, all driven by CSS custom properties set in one token file. No hardcoded brand colours anywhere.
Venue pages generate QR codes server-side for on-the-ground sharing, with clean Open Graph metadata so any link unfurls into a proper card.
A seven-stage intake pipeline turns messy public sources into clean, de-duplicated, human-approved records. Every stage is isolated, and the one irreversible action, publishing, always needs a person.
RawEvent[] shape. New sources plug in without touching the rest of the pipeline.Asia/Phnom_Penh, slugs generated, categories mapped, and a blocklist drops spam and non-events before they go further.insert, merge or stage.// fetch → normalise → dedup-check → (insert | merge | stage)
const raw = await fetchSource(source); // RawEvent[]
const events = raw.map(normalise); // → events schema, TZ-correct
const clean = events.filter(notBlocked); // blocklist
for (const ev of clean) {
const verdict = await dedupCheck(ev); // exact + fuzzy
if (verdict.kind === 'duplicate') skip(ev);
else if (verdict.kind === 'merge') mergeInto(verdict.target, ev);
else stageForReview(ev); // ← human gate
}
// the scraper itself? it only ever wrote a .json file.A deliberately lean, mostly-static architecture: sophisticated where it counts, boring everywhere else.
Angkor Now is live: a real, self-maintaining city guide built and sponsored by AI Boffin Hub to show what an LLM-run editorial product looks like in production.