Privacy
This is a static-first personal blog. It serves no ads, does no cross-site tracking, and loads no third-party analytics that use cookies or collect personal data. Below is everything that happens with data, and which parts are opt-in.
Anonymous counters (default)
Cloudflare KV holds page-view, like and reader-day counts. The server hashes your IP, User-Agent and site hostname with a random daily salt using SHA-256. It temporarily stores the daily hash and the page paths already counted; both the salt and de-duplication marker are assigned a 25-hour expiry. The raw IP is used for that calculation only and is not written to the statistics store. Regular backups retain aggregate counters for 90 days and exclude salts, de-duplication markers and visitor identifiers. Page views also use tab-scoped sessionStorage to avoid counting the same page repeatedly within a session. This creates no persistent browser identity, uses no cookies and performs no cross-site tracking. These counters operate independently of the optional analytics consent choice.
Performance & traffic measurement (always on, cookieless)
The site uses Cloudflare Web Analytics for page performance (aggregate Core Web Vitals) and traffic counts. It is injected automatically at Cloudflare's edge, sets no cookies, writes nothing to browser storage, collects no personal data, and does no cross-site tracking; data is only ever shown in aggregate.
Optional analytics (consent required)
The site can be configured with Google Analytics 4 and Microsoft Clarity. They load only when both are true: the environment variables are configured, and you explicitly chose "Accept all". With "Essentials only" (or no choice) these scripts never load.
Comments (GitHub)
Comments are powered by Giscus (GitHub Discussions) via a giscus.app iframe; interaction requires a GitHub login and is covered by GitHub's privacy policy.
x402 paid articles (when enabled)
Unlocking a paid article stores the paying wallet address, article path, transaction hash, and timestamp server-side (return visits and revocation), sets an HttpOnly cookie scoped to that article path, and keeps the on-chain receipt in localStorage for display. Wallet interaction happens entirely through your own browser wallet extension; this site never touches keys.
Browser storage inventory
- blog-theme
- Light/dark theme preference
- blog-consent
- Your consent choice (all / essential)
- blog-liked:<path>
- Articles you liked (prevents double-likes)
- x402-paid:<path>
- On-chain receipt for a paid article (display only)
- Cookie x402_<hash>
- Paid-article return-visit credential (HttpOnly, path-scoped, 1 year)
What this site actually runs right now
This table is generated from the build configuration, not hand-written — add a tracker and a row appears, remove it and the row goes. Rows marked ⟳ change live with your consent choice.
- Cloudflare Web Analytics (cookieless) Always on
- First-party anonymous view and like counts Always on
- Google Analytics 4 Configured, waiting for your consent
- Microsoft Clarity Not configured
Your choices
The consent bar only appears when optional analytics are configured. Everything works fully in essentials-only mode. You can change your mind at any time with the button below — no need to clear browser storage.