Zero-Cost AI Blog Writer
Git-triggered article factory
01 · Executive Summary
A blog is only an asset if it stays alive. The friction of writing, formatting, and deploying means most developer blogs go stale within months. Hosted CMS platforms solve the friction but add a bill, a database, and a runtime to maintain.
The Zero-Cost AI Blog Writer removes both problems. It is a pipeline native to this very repository: on a schedule, an agent drafts a post with Gemini, writes it as Markdown, commits it, and GitHub Pages redeploys the static site. There is no server and no database — only files in Git — so the running cost is exactly $0.
Who it's for: engineers who want a continuously growing, SEO-ready technical blog without owning any infrastructure or touching a CMS.
02 · The Stack
- Framework
- Next.js (App Router) with output: 'export' — pure static HTML.
- Content
- MDX files + gray-matter frontmatter, compiled at build with remark/rehype.
- Agent
- Python + the google-genai SDK calling gemini-2.5-flash.
- Runtime / CD
- GitHub Actions — a scheduled writer job and a deploy job.
- Hosting
- GitHub Pages — free static hosting, no server runtime.
- Queue
- scripts/topics.txt — one topic per line, consumed top-down.
03 · System Architecture Flow
- 1Cron Trigger
GitHub Actions fires on schedule: 0 10 * * 1,3 (Mon & Wed, 10:00 UTC).
- 2Topic Extract
ai_writer.py reads the top line of scripts/topics.txt.
- 3Model Call
google-genai calls gemini-2.5-flash for a strict-Markdown article.
- 4File Output
A frontmatter .mdx is written to src/content/blog/<slug>.mdx.
- 5Commit & Push
The new post and the popped topic are committed back to main.
- 6CD Deploy
deploy.yml builds output: export and ships ./out to GitHub Pages.
04 · Deep Technical Breakdown
Git-driven static file generation lifecycle
The pipeline has no runtime of its own — its "database" is the Git history and its "deploy hook" is a push to main. The writer workflow generates a file and commits it; that commit triggers the deploy workflow, which rebuilds the static export and publishes it. Every published article is therefore a normal commit you can diff, revert, or edit by hand.
The google-genai SDK with gemini-2.5-flash
Content is generated with Google's current SDK (the legacy google-generativeai package is end-of-life). The agent constructs a client from an API key supplied via environment and requests a strict-Markdown article; the script — not the model — owns the slug, date, and reading time, so a malformed response can never corrupt the typed build.
from google import genai
client = genai.Client(api_key=os.environ["GEMINI_API_KEY"])
resp = client.models.generate_content(
model="gemini-2.5-flash",
contents=build_prompt(topic),
)
article = resp.textAutomated topic extraction from topics.txt
The backlog is a plain text file — one topic per line. The agent reads the top non-empty line, generates from it, then removes exactly that line so the next run advances automatically. The queue is human-editable: reorder, add, or delete topics with a normal commit.
topic = next(l.strip() for l in TOPICS.read_text().splitlines() if l.strip())
# ...generate + write the .mdx...
remaining = [l for l in lines if l.strip() != topic]
TOPICS.write_text("\n".join(remaining))Zero-cost builds via output: 'export'
Because Next.js is configured for static export, the entire site compiles to plain HTML/CSS/JS in ./out with no Node server to host. The MDX is parsed and compiled at build time, so posts render with zero client-side runtime cost. GitHub Actions builds it and GitHub Pages serves it — both free tiers — which is what makes the steady-state cost genuinely zero.
// next.config.mjs
const nextConfig = {
output: "export", // static HTML -> ./out
images: { unoptimized: true },
trailingSlash: true,
};Explore the source
It's this site — scripts/ai_writer.py and the Actions workflows.