Two Astro gotchas I hit building this very blog
I built this devlog on Astro content collections, and at first I wanted it in three locales — one markdown file per language. Wiring that up, I hit two traps worth writing down; neither fix is obvious.
Gotcha 1: a frontmatter `slug` *is* the entry id
I gave every post a `slug` field so the three language versions of the same story could share one URL:
lang: "en-us"
slug: "unify-mac-ios-downloads"
It built fine. But only the Chinese index listed the post — English and Japanese said "No posts yet."
The glob loader treats a `slug` frontmatter field as the entry **id**. All three files declared the *same* slug, so they collapsed into a single entry, and the last one loaded (`zh-tw`, alphabetically) won. The other two simply vanished from the collection — no error, no warning.
Fix: drop the `slug` field. Let the id be the file path (`en-us/unify-mac-ios-downloads`), which is unique per locale, and derive the URL slug from the filename instead:
const slug = post.id.replace(/^[^/]+\//, ''); // strip the locale folderGotcha 2: `getStaticPaths` runs in its own scope
With the ids fixed, the next build failed harder:
slugOf is not defined
I'd factored that little `replace` into a helper at the top of the route file, then called it inside `getStaticPaths`. But `getStaticPaths` is special — Astro extracts and runs it in isolation, so it **can't see other top-level consts** in the same frontmatter. The helper existed for the rest of the component; just not in there.
Fix: keep the derivation inline, or define it *inside* `getStaticPaths`:
export async function getStaticPaths() {
const posts = (await getCollection('blog')).filter((p) => p.data.lang === 'en-us');
return posts.map((post) => ({
params: { slug: post.id.replace(/^[^/]+\//, '') },
props: { post },
}));
}
Both are the kind of trap that builds green on the happy path and only bites once you have more than one entry, or share a helper. Now you know — the blog you're reading shipped right after.
Keep reading
-
The cube solver that refuses to be confidently wrong
cubeconjure reads a Rubik's cube through your Mac's camera and tells you how to solve it. The hard part was never the solving — it was reading six colors honestly under real light. This is the story of how 'just read the stickers' turned into a lesson about not being confidently wrong, on either side of the camera.
-
Why your Mac cleaner found 47 GB (and where it really went)
A friendly teardown of how black-box Mac cleaners work — the big scary number, the invisible delete, the one thing almost none of them tell you about APFS snapshots — so you can judge any cleaner, including ours.
-
The despair that became a library
bleedblend started as a bug in reef — a sticky banner whose blur kept getting clipped at the notch. Instead of fighting Safari's chrome, we learned to paint it on purpose. This is the rabbit hole we fell down so you don't have to.