lkmail Update 1.20_6: The Invisible Wall Between Build Time and Runtime
Welcome to Update 1.20_6 of the lkmail development journey!
With the MDX blog fully stabilized on Cloudflare's Edge network, I navigated to the /projects page to check my automated GitHub portfolio. To my surprise, the live site proudly displayed: "No projects found. Please check the GitHub token."
The code worked perfectly on my local machine. I had also securely uploaded my GITHUB_TOKEN to Cloudflare using the wrangler secret put command. So, why was the API call failing in production?
The answer lies in the invisible wall between Build Time and Runtime.
The Autopsy: Hardcoding the Error
Because we are building a Static Site Generation (SSG) architecture, Next.js executes our data-fetching code during the compilation phase (next build) on a remote CI server, before the site is ever deployed.
- On my local machine, Next.js easily read the token from my
.env.localfile, fetched the repos, and built the HTML. - However, Cloudflare's CI build container (running in
/opt/buildhome/repo) is completely isolated. It respects.gitignore, so it didn't have my.env.localfile. - Because my
process.env.GITHUB_TOKENevaluated toundefinedduring the build, GitHub rejected the API request. - Next.js happily took the empty array, triggered the fallback UI, and permanently baked the "No projects found" message into the static HTML.
The Misconception: wrangler secret put
My mistake was assuming that uploading the secret via Wrangler made it available everywhere.
By diving into the Cloudflare CI/CD documentation, I discovered a strict architectural boundary:
- Runtime Secrets:
wrangler secret putencrypts variables and sends them strictly to the Edge Worker. They are only accessible when a user triggers dynamic server code at request time. - Build Variables: The CI compilation step has its own, entirely separate vault. Build variables are explicitly hidden from the runtime environment, and vice versa.
The KISS Fix
To fix this, we had to satisfy both the code architecture and the Cloudflare infrastructure.
1. Unifying the Code Architecture
First, we updated src/app/[lang]/projects/page.tsx to match the strict SSG rules we established for the blog, ensuring Next.js never tries to fetch this data dynamically:
// 🔒 STRICT SSG: Keep architecture perfectly uniform
export const dynamicParams = false;
export function generateStaticParams() {
return [{ lang: "en" }, { lang: "fr" }];
}
2. Injecting the Build Secret
Next, we navigated to the Cloudflare Dashboard to explicitly hand the token to the build compiler:
- Go to Settings > Build (Not the Variables & Secrets tab).
- Scroll to Build variables and secrets.
- Add
GITHUB_TOKENand mark it as an encrypted secret.
Conclusion
Once the new build variable was saved, the next deployment triggered flawlessly. The isolated CI container finally had the key to unlock the GitHub API, and my repositories, star counts, and language badges were successfully baked into the static HTML!
When deploying SSG apps to edge networks, you must always ask yourself: "Does my code need this data right now to build the page, or does the user need this data later when they click a button?" With our environments finally perfectly aligned, it is time to build the Contact UI!