lkmail Update 1.17: GitHub API Integration and Cloudflare Secrets
Welcome to Update 1.17 of the lkmail development journey!
A digital identity shouldn't be a static resume; it should be a living reflection of your work. Today, we leaped into Phase 3: API Integrations by connecting our application directly to GitHub to dynamically generate our Projects page.
But before we could fetch the data, we had to establish a bulletproof, "KISS" (Keep It Simple, Stupid) strategy for managing API keys.
Managing Secrets in Cloudflare Workers
In a standard Node.js environment, you might rely on a .env file for production secrets. However, because lkmail is deployed as a Cloudflare Worker via OpenNext, the rules change.
To ensure maximum security and developer experience, I codified a new strict rule for environment variables (Golden Rule #10):
- Local Development: All secrets live in a
.dev.varsfile at the root of the project. This allows the local Next.js dev server to access tokens while building. - Production Deployment: We strictly bypass the Cloudflare web dashboard. Instead, we push encrypted secrets directly to the edge using the Wrangler CLI:
pnpm wrangler secret put GITHUB_TOKEN
This CLI-first approach prevents configuration drift and keeps our CI/CD pipeline impeccably clean.
The GitHub GraphQL API Wrapper
With our GITHUB_TOKEN securely injected into the environment, we built the API wrapper (src/lib/api/github.ts).
Instead of making multiple REST API calls, we utilized GitHub's GraphQL API. This allows us to request exactly the data we need—and nothing more—in a single, highly efficient query:
query {
user(login: "lionel-kaufmann") {
repositories(first: 6, orderBy: {field: UPDATED_AT, direction: DESC}, privacy: PUBLIC) {
nodes {
name
description
url
stargazerCount
primaryLanguage {
name
color
}
}
}
}
}
This query grabs my 6 most recently updated public repositories, including their descriptions, star counts, and the primary programming language (with its official hex color!).
Assembling the Projects Page
Finally, we brought this data to the frontend by building src/app/[lang]/projects/page.tsx.
Because our components are Server Components by default, we fetch the GitHub data securely on the server side concurrently with our localized dictionary:
const [dict, repos] = await Promise.all([
getDictionary(lang as Locale),
getLatestRepos(),
]);
The resulting UI maps through the repositories, displaying them as beautiful, interactive cards using Tailwind CSS v4. If a repository has a primary language, it even renders a small, color-coded dot next to the language name—a subtle but highly professional UI touch.
What is Next?
With the GitHub integration complete, our portfolio is completely automated. Every time I push code to a public repository, lkmail will instantly reflect the update.
Next up: We will be tackling the Contact form and setting up our transactional email infrastructure!