Building a bilingual browser game with Astro and Cloudflare (and making the HTML actually cache)
I recently shipped Cá Viên Chiên , a small cooking game about Vietnamese fried fish ball street carts. It runs in the browser, works best on phones, and ships in Vietnamese and English. Here are the parts that were more interesting than I expected. Why Astro for a game Most of the site isn't the game — it's the landing page, guide, tips, menu and FAQ in two languages. Those pages matter for…
I recently launched Cá Viên Chiên, a small Vietnamese cooking game that runs in a browser and supports both Vietnamese and English. The game comprises various pages like the landing page, guide, tips, menu, and FAQ, which are essential for search purposes, making them static HTML. Astro enables this setup, with the game itself being a standalone vanilla JS file (~26 KB) and minimal CSS (under 5 KB).
The game's language routing is handled by /vi/ and /en/ sections, each pointing to the other via hreflang alternates. The root page (/) redirects based on the Accept-Language header but cannot be cached effectively. Players save their progress using localStorage, allowing them to pick up where they left off on a different device by copying a save code and pasting it onto another device.
Since no backend or sign-up system is involved, the game operates without a server. To optimize performance, static assets under _astro/* are already hashed and served with a max-age of 31536000 (one year) and marked as immutable, ensuring they are served from the edge. However, the HTML requests were taking about 250 ms and were being served dynamically, with a Time to First Byte (TTFB) coming from the origin.
Adding a Cloudflare Cache Rule for both /vi/* and /en/* directories made them cacheable but didn't significantly improve the TTFB. The reason for this was that the origin server continued to send cache-control headers with max-age set to 0, causing the edge to repeatedly revalidate the content. To address this issue, Cloudflare's CDN-Cache-Control header was implemented, which takes precedence over the origin's cache-control headers.
This change allowed the edge to serve cached content with a max-age of 86400 seconds (24 hours), drastically reducing TTFB. Additionally, the language redirect on the root page was moved to the edge, further enabling caching per language. Lastly, the game's font was self-hosted to eliminate two extra origins. The game can be played at cavienchien.net, and feedback on the difficulty curve is highly encouraged.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.