A few weeks ago I shipped a feature I'd been putting off because it felt like it needed a backend: subscribable calendar feeds. "Add this holiday to Google Calendar." "Subscribe to all your country's public holidays so they show up in Apple Calendar forever."

Every calendar competitor has this. My site had none. The catch: the whole thing is a static export — next build produces a folder of HTML/CSS/JS that I drop on Cloudflare Pages. No server, no API routes at request time, no ISR. So how do you serve a .ics feed that a calendar app polls every few hours?

Turns out you don't need a server at all. Here's the approach, the RFC 5545 gotchas that bit me, and the parts I'd tell my past self.

The "aha": a feed is just a file

A .ics subscription feed is not a live API. It's a static text file that calendar clients re-fetch on a schedule. So for a static site, the idiomatic move is a post-build emitter: after next build, run a Node script that walks your data and writes assets straight into out/.