This blog is fully static, completely version-controlled, and hosted on Cloudflare Pages. It uses AsciiDoc for content, and it’s 100% JavaScript-free. Here’s how I set the whole thing up.
1. Why AsciiDoc?
-
Cleaner than Markdown for long-form writing
-
Supports tables, footnotes, admonitions, callouts — out of the box
-
Plays well with
asciidoctor, which converts.adocto clean HTML
2. Project Structure
blog/
├── index.adoc
├── posts/
│ ├── post1.adoc
│ ├── post2.adoc
├── custom.css
├── build.sh
└── _site/ # final output (what Cloudflare serves)
-
Posts are stored in
posts/ -
A
build.shscript compiles all.adocfiles to.html -
Everything goes to
_site/, which is the deploy directory
3. The Build Script
The script compiles each .adoc file using asciidoctor:
#!/bin/bash
rm -rf _site
mkdir -p _site/posts
for file in posts/*.adoc; do
asciidoctor "$file" -o "_site/posts/$(basename "${file%.adoc}.html")"
done
asciidoctor index.adoc -o _site/index.html
cp custom.css _site/
Make it executable:
chmod +x build.sh
4. Styling
AsciiDoctor has great defaults, but I added a minimal custom.css for:
-
Dark red headings in light mode
-
Dark mode with black background and grey/white text
-
Respect for
prefers-color-scheme
h2, h3 {
color: #c0392b;
}
@media (prefers-color-scheme: dark) {
body {
background-color: #121212;
color: #dddddd;
}
}
5. Deploying to Cloudflare Pages
Cloudflare makes it stupidly easy.
-
Connect your GitHub repo
-
Set build command to
./build.sh -
Set output directory to
_site -
Done. It builds on every
git push
6. Why This Rocks
-
I write blog posts in plain text
-
No JS, frameworks, or bloat
-
Pure HTML output is SEO-friendly and super fast
-
Can be version-controlled and edited in VSCode
Final Thoughts
Most blogs are overengineered. Mine is aggressively underengineered — and that’s the point.
If you want a blog that feels like writing a README file, but looks like a clean academic site, this setup slaps.