> cat /en/how-it-works
How this site works
No server, no database, no cookies. The pages are built ahead of time a few times a day and served from Cloudflare’s network; the only thing that runs when you visit is a small edge function. Below are the parts and why they are the way they are.
- BUILT
- COMMIT
- 6c82b19
- STACK
- Astro · TypeScript · Cloudflare
Flow
There are two separate moments: the build, when the pages are made, and the visit, when someone opens one.
Build time
- TRIGGERevery merge to mainplus two scheduled builds a day: GitHub Actions + Cloudflare Worker
- DATAYouTube · Twitch · Steam · Riotfetched during the build; visitors never call these services
- BUILDAstro → static HTMLtwo languages; thumbnails are downloaded, converted to WebP and served from the site
- CHECKempty data · SEO · CSPif one fails nothing is published and the previous version stays
- PUBLISHCloudflare Pagesserved from the worldwide edge network, then a heartbeat
Visit time
- BROWSERThe page opensHTML, CSS, fonts and images from the same domain
- EDGEGET /api/livethe only dynamic request on the page
- CACHE60 show often each data centre normally asks the sources
- SOURCETwitch · Riot · Steamis there a stream, which game is open right now
Build
Everything that does not change is prepared in advance; visitors get ready-made HTML.
- Data is fetched at build time. Steam playtime, LoL level and masteries, the latest videos and the top clips are read during the build. Opening a page sends no request to these services.
- No publishing with half the data. If one of the sources comes back empty, the build fails on purpose and the version that is live stays in place. A bad day does not show an empty site, only a day-old one.
- Two separate triggers. Scheduled builds come from both GitHub Actions and a Cloudflare Worker. If one provider skips a run (it happens), the other one covers it.
- Post-build check. A script checks the sitemap, the canonical URLs, the links between language versions, the share image and the CSP hash of every inline script and style. If one of them fails, the build breaks, so a broken page never goes live.
Live layer
Everything “live” on the page comes from one endpoint: /api/live, a Cloudflare Pages Function.
- Cached. Each Cloudflare data centre normally asks Twitch, Riot and Steam once every 60 seconds, however many visitors there are.
- If one source fails, the others still answer. The sources are asked separately; an incomplete answer is kept for 15 seconds, so an outage does not slow down every visit.
- Fixed cache key. Adding a query string to the URL does not bypass the cache or trigger requests to the sources. The domain also has a per-IP rate limit.
- Only game information. In LoL my mode and champion, on Steam the game’s name; no other players, account IDs or match numbers. The mode comes as a language-neutral code (
CLASSIC,ARAM) and the page names it in the reader’s language. When I am invisible on Steam, the game is hidden too.
…
Security and privacy
Nothing is collected from visitors; the browser only talks to this domain.
- No cookies, no analytics, no third-party scripts. Fonts and images are served from the site too.
- Strict CSP. Scripts and styles only run from the site itself or by their hash; images, fonts and network requests only from the same origin. The page cannot be framed by another site.
- Security headers. HSTS,
nosniff, Referrer-Policy; camera, microphone and location permissions are off. - Keys are not in the code. API keys live only in Cloudflare environment variables; logs never contain a key, a URL or an ID.
Quality
A small site, written to the standard I use at work.
- Type checking. TypeScript in strict mode; JavaScript files go through the same check via JSDoc. A missing translation of an interface text is a type error too.
- Unit tests. Parsing of Steam and Riot responses, the live endpoint, the cache and the privacy rules are covered by Vitest tests. The important ones were verified by breaking the code on purpose and watching them fail.
- CI on every PR. GitHub Actions runs the type check and the tests, then measures the built site with Lighthouse: if accessibility, best practices or SEO drops below 100, the PR turns red. The Actions it uses are pinned to commit SHAs.
- A waiting period for dependencies. Packages are pinned to exact versions, and as a rule I do not take a new version until it has been out for at least two weeks. Supply-chain attacks are usually caught in the first days.
Monitoring
If something breaks, I find out before visitors do.
- Heartbeat. Every successful production build sends a signal to Healthchecks.io. If no signal arrives in the expected time, an e-mail goes out; whether the trigger did not run, the build broke or the data came back empty, the same alarm catches it.
- Publish failure alert. Cloudflare also sends an e-mail if publishing fails.
- Visible age. The build time and commit are shown at the top of the page; the site does not hide how fresh it is.
How it was built
I built this site together with Claude Code, Anthropic’s AI coding tool.
- Written together. Claude Code wrote the code, the tests and most of the text. I decided what to build, how it should look and what goes live.
- Every change was reviewed. Each piece of work was done on its own branch and came in as a PR. Before merging, the code, security and tests were reviewed separately; nothing reached main without green CI, and I always did the merge myself.
- Working with evidence. Saying “it works” required a measurement: a request to the live endpoint, a screenshot of the preview, breaking the code on purpose to see a test fail. A claim that turned out wrong was openly taken back.
- Why I mention it. AI is now part of software work. I find it more honest to show how I use it than to hide it.