How I built this personal blog using OpenCode
Why Build Another Blog?
I usually write on medium mostly and have been avoiding it due to work. So i wanted to explore what if I can built something using github free hosting as a personal space to write. My initial thoughts were:
- Posts could be written in Markdown and auto-published from GitHub Issues
- Readers could like and comment without yet another login wall
- Everything was free to run
- I own the content and the code
The Stack
| Layer | Choice | Why |
|---|---|---|
| Hosting | Cloudflare Pages | Free tier, generous limits |
| CSS | Tailwind v4 via CDN | No build step |
| Auth | GitHub OAuth | Already have a GitHub account |
| Comments | GitHub Issues API | Free, uses the same issue as the post |
| Automation | GitHub Actions | Free for public repos |
| MD→HTML | marked |
Lightweight, one dependency |
Building with OpenCode
The entire site — frontend, API functions, CI/CD, blog pipeline — was built through conversations with OpenCode. I didn't write a single line of code from scratch. Every feature was described in natural language, reviewed, iterated, and committed.
The model used was DeepSeek V4 Flash (opencode-go/deepseek-v4-flash). I don't have exact token counts or cost — OpenCode abstracts that away — but the entire project (roughly 5 hours of active sessions, many conversation turns) was well within a reasonable monthly plan.
Estimate: 240,825 tokens (in/out) Estimate Cost: $10.99 spent
What Got Built
Over roughly two days, in roughly this order:
- Site scaffold — Single
index.html, minimal, no frameworks - Theme & animations — Dark mode, circular unwrap transition, brightness flash
- Hero section — Cursor coordinates, Konami code easter egg, typewriter animations
- CV, contact, footer — Layout sections
- Blog system —
blogs/directory, template, listing page with search/filter - Likes & Comments — Cloudflare Pages Functions backed by GitHub Issues API
- GitHub OAuth — Sign in with GitHub to like and comment
- Issue-to-post pipeline — Create a GitHub issue with label
blog, and it auto-publishes as HTML - CI/CD — GitHub Actions deploys to Cloudflare Pages on push or issue events
Surprise: User-Agent Headers
GitHub's API requires a User-Agent header on every request. Without it, you get a 403. Our /api/me endpoint was silently failing because of this. The entire sign-in flow worked (cookie was set correctly), but the UI showed "Sign in with GitHub" because the auth check was hitting GitHub's API without a User-Agent header.
One line fix: 'User-Agent': 'singhamarbir.com'
The Blog Pipeline
The most satisfying feature: create a GitHub issue with label blog, paste Markdown, and it's published automatically.
- Issue body has YAML frontmatter (
excerpt,tags) - CI picks it up, converts Markdown to HTML via
marked - Wraps it in the site template
- Adds
publishedlabel and a comment with the URL - Deploys to Cloudflare Pages
Editing the issue re-publishes. No manual HTML files to manage.
Performance & Scale
The full rebuild (processing all blog issues) takes under a second even for hundreds of posts. The bottleneck is Cloudflare Pages deploy, not the script.
Pagination was added when the issue list exceeded 100 — GitHub's API only returns one page at a time by default.
Cost Breakdown
| Item | Cost |
|---|---|
| Cloudflare Pages | Free |
| GitHub (repo + Actions) | Free |
| OpenCode subscription | ~$5/month (first month and then $10/month) |
| Domain | ~$30/year |
| Total | Domain cost + OpenCode subscription |
Exact model pricing and token counts aren't something I tracked, but the productivity gain versus writing everything by hand or wrestling with a static site generator was enormous.
Try It Yourself
The code is at github.com/a-5ingh/personal. OpenCode is at opencode.ai.