TR

> 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
BUS

Flow

There are two separate moments: the build, when the pages are made, and the visit, when someone opens one.

Build time

  1. TRIGGERevery merge to mainplus two scheduled builds a day: GitHub Actions + Cloudflare Worker
  2. DATAYouTube · Twitch · Steam · Riotfetched during the build; visitors never call these services
  3. BUILDAstro → static HTMLtwo languages; thumbnails are downloaded, converted to WebP and served from the site
  4. CHECKempty data · SEO · CSPif one fails nothing is published and the previous version stays
  5. PUBLISHCloudflare Pagesserved from the worldwide edge network, then a heartbeat

Visit time

  1. BROWSERThe page opensHTML, CSS, fonts and images from the same domain
  2. EDGEGET /api/livethe only dynamic request on the page
  3. CACHE60 show often each data centre normally asks the sources
  4. SOURCETwitch · Riot · Steamis there a stream, which game is open right now
BUILD

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.
EDGE

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.
GET /api/live asking…
…
SEC

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.
QA

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.
MON

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.
DEV

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.

Back to the home page