Publish a subscribable calendar
This publishes your published meal plans as a single calendar
file (.ics) to a GitHub repository you own, served by
GitHub Pages as text/calendar. A calendar app (e.g. Google
Calendar) can then subscribe to its URL and refresh it
as you republish. It is optional and device-local:
your token and settings stay in this browser and are never shared or
synced to your account.
Before you start — the tradeoff
Publishing needs a GitHub token that can write to your repository, and that token lives in your browser. By default arecipe keeps it in the service worker's memory so page scripts can't read it, and re-asks for it after a period of inactivity. If you tick “Remember on this device”, the token is stored in this browser instead — more convenient, but readable by any script running on this origin. Reduce the blast radius:
- Use a dedicated repository that holds nothing else.
- Scope the token to Contents only (see step 2). A Contents token can't create or change GitHub Actions workflows, so a leak can't run code — even though Actions must stay enabled for Pages to publish (see step 1).
- Give the token the shortest expiry you can live with.
- Revoke it the moment you're done experimenting.
1 · Create the repository + enable Pages
- Create a new repository (private is fine) — e.g.
your-name/meals-calendar. - Open Settings → Pages and set the source to
Deploy from a branch → your default branch,
/ (root). GitHub Pages serves.icsfiles astext/calendar, which is what calendar apps require. - Add an empty file named
.nojekyllat the repository root (Add file → Create new file). It tells Pages to publish your files as-is instead of running a Jekyll build over them. - Leave Actions enabled (Settings → Actions →
General → Allow …). This is required: Pages rebuilds the
published site by running its built-in deployment on every push, so
with Actions disabled your
.icsstill commits but the public site never updates. Your token has only Contents access, so it still can't define or alter workflows.
2 · Create a fine-grained token
- Go to fine-grained personal access tokens.
- Repository access: “Only select repositories” → just the calendar repo above.
- Permissions: Repository permissions → Contents: Read and write. (Metadata: Read-only is added automatically.)
- Set a short expiration and generate the token. Copy it once — GitHub won't show it again.
3 · Connect it in arecipe
- On the account page, open “Publish a subscribable calendar (advanced)” and tick Enable on this device.
- Enter the repository (
owner/repo) and, if you like, a file path (defaultmeals.ics). - Paste the token and Save token. Decide whether to tick “Remember on this device” (see the tradeoff above).
- Press Publish now to write the first calendar file.
After this, publishing a meal plan (or deleting a published one) updates the calendar automatically; the Meals page shows a small status chip with a manual Resync.
4 · Subscribe in your calendar app
Your file lives at your Pages URL, e.g.
https://your-name.github.io/meals-calendar/meals.ics (or
your custom domain). In Google Calendar: Other calendars → “+”
→ From URL, paste that URL.
Note: calendar apps poll subscribed URLs on their own schedule — Google's can take several hours — so updates are not instant. This is a subscription that refreshes eventually, not a live feed.
Two subscribe gotchas. Google shows
“Unable to add calendar. Check the URL” when that URL is
already subscribed — check your calendar list before
re-adding. And to force a fresh pull after a change, remove the calendar
and re-add it with a throwaway query string, e.g.
…/meals.ics?v=2: Pages serves the same file, but the new
URL makes the calendar app fetch fresh instead of using its cache.
Troubleshooting — the file updates but my calendar doesn't
The usual cause is a frozen GitHub Pages build.
Publishing writes meals.ics to your repository, but the
public URL is served by Pages, which only refreshes when its deployment
runs on each push.
- Open Settings → Pages and check “Last deployed”. If it's older than your last publish, the served file is stale.
- Open the Actions tab. If Actions is disabled, or
the
pages-build-deploymentrun is missing or red, that's the break — enable Actions and confirm a.nojekyllfile exists at the repo root (step 1), then Publish now again. - A Pages rebuild takes a minute or two after each publish; after that, your calendar app still refreshes on its own schedule (hours for Google). To confirm the file itself is current, open the URL directly in a browser and check the events are there.
Revoking
Remove the token any time from your GitHub token settings, and press Clear token on the account page. If you ever suspect the token leaked, revoke it immediately — that is the whole point of the short expiry and dedicated repo.