Build Your Own Engineering Blog: From Zero to Live
Contents
- The Idea in One Sentence
- The Stack
- The Flow Diagram
- Step 1 β Install Ruby + Jekyll (Windows)
- Step 2 β Folder Layout
- Step 3 β Write Your First Post
- Step 4 β Add Plots and 3D
- Step 5 β Let AI Do the Boring Parts
- Step 6 β Push to GitHub
- Step 7 β Deploy to Cloudflare Pages (Free)
- Step 8 β Buy a Domain (Optional, but Recommended)
- Step 9 β Analytics (Optional, Free)
- Daily Workflow
- Learn Markdown
- Final Cost Breakdown
- Now Go Write Something
You have ideas. You want a place to publish them. With math. With 3D scenes. With interactive plots.
You do not want to pay 20 β¬/month to Squarespace for the privilege. π
Good news. The full stack behind this site costs 0 β¬ if you publish under myblog.pages.dev, or ~12 β¬/year if you want a custom domain like yourname.com. Hosting is free. SSL is free. Build is free. Domain is the only optional bill.
Here is the entire pipeline, start to finish. β
The Idea in One Sentence
You write Markdown. AI fills in the hard parts. Git pushes it. Cloudflare publishes it.
That is the whole loop. Everything below is just plumbing.
The Stack
| Icon | Tool | Layer | Cost |
|---|---|---|---|
| Jekyll 4 + Minima | Static site engine | Free | |
| MathJax | Math rendering | Free | |
| Plotly.js | Interactive plots | Free | |
| Three.js | 3D / WebGL | Free | |
| GitHub | Source control | Free | |
| Cloudflare Pages | Hosting + CDN + SSL | Free | |
| Claude Code | AI co-author | Free tier exists | |
| πΈ | Cloudflare Registrar / Namecheap | Domain name | ~10β15 β¬/year |
One bill per year. That is it.
The Flow Diagram
ββββββββββββββββ
β π‘ Idea β
ββββββββ¬ββββββββ
β
βΌ
ββββββββββββββββββββββββ ββββββββββββββββββββ
β βοΈ Write Markdown β βββββΆ β π€ AI Helper β
β in _posts/ β β (Claude Code) β
ββββββββ¬ββββββββββββββββ ββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββ
β π Preview locally β
β jekyll serve β
ββββββββ¬ββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββ
β π¦ git push β
ββββββββ¬ββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββ
β βοΈ Cloudflare β
β auto-builds + CDN β
ββββββββ¬ββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββ
β π yourname.com β
ββββββββββββββββββββββββ
Push code. Site updates. No FTP. No server. No drama.
Step 1 β Install Ruby + Jekyll (Windows)
Jekyll is the engine. Markdown goes in, HTML comes out.
- Grab Ruby+Devkit from rubyinstaller.org/downloads. Pick the version with
=>next to it. - End of installer runs
ridk install. Choose options1, 2, 3in order. - Open a fresh PowerShell:
gem install bundler jekyll
- Make your blog:
jekyll new myblog
cd myblog
bundle install
- Run it:
ridk enable
bundle exec jekyll serve --livereload
- Open
http://localhost:4000. There it is. π
--livereload auto-refreshes the browser when you save a file. Edit. Save. Watch it update.
Stuck?
bigdecimal.soLoadError β runridk enable && gem pristine bigdecimal. Mac/Linux? Skipridk, install Ruby via your package manager.
π Deep dive: Official Jekyll Quickstart Β· Jekyll on Windows Β· Minima theme docs
Step 2 β Folder Layout
myblog/
βββ _posts/ β your articles (one .md per post)
βββ _includes/ β reusable HTML/MD chunks (3D scenes, demos)
βββ _layouts/ β page templates
βββ _config.yml β site settings (title, author, plugins)
βββ Gemfile β Ruby dependencies
βββ assets/
βββ css/style.css
βββ images/
Open _config.yml first. Set title, author, description, and url. Save. Done with setup.
Drafts: prefix filename with _ or -. Jekyll ignores them. π
π Deep dive: Jekyll directory structure Β· Front matter reference Β· Drafts
Step 3 β Write Your First Post
The whole point. One Markdown file = one published article.
Create _posts/2026-05-01-my-first-post.md (filename must start with YYYY-MM-DD-):
---
layout: post
title: "Why Beams Bend"
date: 2026-05-01
categories: structural-analysis
tags: [beams, FEM]
plotly: true # optional: loads Plotly.js
image: /assets/images/beams-thumb.jpg # optional: thumbnail + og:image
---
Inline math: $\sigma = E\varepsilon$. Display:
$$M = EI \frac{d^2 w}{dx^2}$$
## A Section
Your text here.
Save. Browser auto-reloads. Done. β
MathJax tip: Prefer display math
$$...$$for anything you want to stand out. Inline$...$for short symbols only. Mixing many inline math + Markdown links in one paragraph can break parsing.
π Deep dive: Markdown Guide Β· Jekyll posts Β· MathJax syntax
Step 4 β Add Plots and 3D
Plotly chart
Set plotly: true in front matter, then drop:
<div id="chart" style="width:100%;height:400px;"></div>
<script>
Plotly.newPlot('chart', [{x:[1,2,3], y:[1,4,9], mode:'lines'}]);
</script>
Three.js 3D scene
Three.js needs an importmap so the browser knows where to fetch modules. Drop this once at the top of the post, before any module script:
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.183.2/build/three.module.min.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.183.2/examples/jsm/"
}
}
</script>
Then your scene:
<div id="scene" style="width:100%;height:500px;"></div>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// scene, camera, renderer, animate loop
</script>
Use CSS variables for theme-aware colors. Never hardcode hex. π¨
Pro tip: For long posts with 3D demos, move the scene HTML/JS into
_includes/posts/<slug>/scene.htmland pull it in with{% include posts/<slug>/scene.html %}. Keeps the post file readable.
π Deep dive: Plotly.js getting started Β· Plotly chart types Β· Three.js manual Β· Three.js examples Β· OrbitControls
Step 5 β Let AI Do the Boring Parts
You write the idea. AI writes the code.
You explain in plain words: βdraw an Eshelby ellipsoid that the user can rotate.β AI writes the Three.js. You review. You ship.
Pick your AI
| Tool | Best at | Link |
|---|---|---|
| Claude Code β | My favorite. Best for coding. | claude.com/claude-code |
| ChatGPT | Quick prose, copy-paste flow | chatgpt.com |
| Cursor | AI inside IDE | cursor.com |
| GitHub Copilot | Inline autocomplete | github.com/features/copilot |
| Gemini | General drafting | gemini.google.com |
Pro tip: feed the AI a project brain
Drop a SITE_REFERENCE.md at your repo root. Document your conventions: front matter format, fragment system, theme rules. Any AI tool reads it and stops guessing. π§
Real prompt example
This is what you actually type. Not vague. Specific:
βIn
_posts/2026-05-02-eshelby-ellipsoid.md, create a Three.js block with a 500 px tall canvas. Draw an ellipsoid with semi-axes a=2, b=1, c=0.5 centered at origin, blue wireframe. Add a red X-axis arrow, green Y, blue Z, each length 3, with text labels βXβ, βYβ, βZβ at the tips. Use OrbitControls. Add a control panel below the canvas with three number inputs labeled βaβ, βbβ, βcβ (range 0.1 to 3, step 0.1) that live-update the ellipsoid geometry. Add a βResetβ button that returns axes to (2, 1, 0.5). Use CSS variables--canvas-bgand--panel-bgso it works in dark and light themes. Match the importmap convention from SITE_REFERENCE.md.β
AI reads. AI writes. You preview. You tweak. You ship. β
More examples:
- βAdd a Plotly chart with two traces: Voigt upper bound and Reuss lower bound for Youngβs modulus vs fiber volume fraction (0 to 1, 50 points). E_fiber=230 GPa, E_matrix=3.5 GPa. Log y-axis. Theme-aware colors.β
- βMy Three.js scene flickers when toggling dark mode. The background does not update. Fix using a MutationObserver on the
data-themeattribute.β - βConvert the math block on line 42 from inline
$...$to display$$...$$and number it with\tag{1}.β
π Deep dive: Claude Code docs Β· Claude Code quickstart Β· Cursor docs Β· GitHub Copilot quickstart Β· Effective AI prompting
Step 6 β Push to GitHub
Make a free account at github.com if you do not have one. Install Git if you have not already.
Option A β with GitHub CLI (install gh):
gh auth login # one-time auth
git init
git add .
git commit -m "initial blog"
gh repo create myblog --public --source=. --push
Option B β without gh: Make an empty repo at github.com (no README, no .gitignore), then:
git init
git add .
git commit -m "initial blog"
git remote add origin https://github.com/YOU/myblog.git
git branch -M main
git push -u origin main
π Deep dive: GitHub Hello World Β· Git basics tutorial Β· GitHub CLI manual
Step 7 β Deploy to Cloudflare Pages (Free)
- Sign up at dash.cloudflare.com.
- Workers & Pages β Create β Pages β Connect to Git.
- Authorize and pick your
myblogrepo. - Build settings:
| Field | Value |
|---|---|
| Framework preset | Jekyll |
| Build command | bundle exec jekyll build |
| Build output directory | _site |
| Production branch | main |
| Environment variable | RUBY_VERSION = match what you installed (e.g. 3.2.2). Check with ruby -v. |
- Hit Save and Deploy. Two minutes later, live at
myblog.pages.dev. π
Every git push to main = automatic rebuild. Branches get preview URLs (great for drafting without breaking your live site). No manual deploys ever again.
Free tier limits: 500 builds/month, unlimited bandwidth and requests. Plenty for any blog. You will never hit it.
π Deep dive: Cloudflare Pages β Get started Β· Deploy a Jekyll site Β· Build configuration
Step 8 β Buy a Domain (Optional, but Recommended)
You can stop right here. Your site already works at myblog.pages.dev. Free forever. 0 β¬. β
But yourname.com looks better on a CV, business card, or paper footer. Worth the 10 β¬/year? Up to you.
| Registrar | Price (.com) | Notes |
|---|---|---|
| Cloudflare Registrar β | ~10 β¬/year | At-cost. Cheapest. No upsells. |
| Namecheap | ~12 β¬/year | Good UI, frequent promos |
| Porkbun | ~11 β¬/year | Quirky, cheap |
Process:
- Buy domain (e.g.
yourname.com). - Cloudflare Pages project β Custom domains β add it.
- Domain on Cloudflare? DNS auto-configures. β
- Domain elsewhere? Add the CNAME they show you.
- SSL certificate appears automatically.
Total bill if you go custom domain: ~12 β¬/year. πΈ
Total bill if you stay on pages.dev: 0 β¬. π
π Deep dive: Cloudflare custom domain setup Β· Cloudflare Registrar Β· DNS basics
Step 9 β Analytics (Optional, Free)
Make a free Google Analytics account. Get a measurement ID like G-XXXXXXXXXX.
Edit _config.yml:
google_analytics: G-XXXXXXXXXX
Push. Stats start flowing. Watch your readers in real time. π
π Deep dive: GA4 setup guide Β· Plausible (privacy-friendly, paid) Β· Cloudflare Web Analytics (free, no cookies)
Daily Workflow
# 1. branch (optional but recommended β gives you a Cloudflare preview URL)
git checkout -b post/eshelby
# 2. ask AI to draft
# "draft _posts/2026-05-02-eshelby-tensor.md with a 3D ellipsoid demo"
# 3. preview locally
ridk enable
bundle exec jekyll serve --livereload
# 4. tweak math, prose, animation. save β browser refreshes.
# 5. ship
git add .
git commit -m "add Eshelby post"
git push -u origin post/eshelby
# 6. open PR on GitHub, merge to main β Cloudflare auto-deploys to your live site
Cloudflare deploys before your coffee finishes. β
Faster path for solo blogs: skip the branch, work on
main,git pushstraight to live. Branches matter when you want a preview link before going live.
Learn Markdown
New to Markdown? Skip the cheat sheets. Read the official guide once and you are set:
π Markdown Guide β Basic Syntax
Bonus links:
- Markdown Guide β Extended Syntax (tables, footnotes, task lists)
- GitHub Flavored Markdown Spec (what Jekyll renders)
- Daring Fireball β Original Markdown spec (the source)
Quick Actions
| Want to⦠| Do this |
|---|---|
| New post | Create _posts/YYYY-MM-DD-slug.md |
| Hide a draft | Prefix filename with - |
| Get AI help | Point your AI at SITE_REFERENCE.md |
| Preview locally | bundle exec jekyll serve |
| Deploy | git push |
Final Cost Breakdown
| Item | Yearly cost |
|---|---|
| Hosting (Cloudflare Pages) | 0 β¬ |
| GitHub repo | 0 β¬ |
| SSL certificate | 0 β¬ |
| Build minutes | 0 β¬ |
| AI tools (free tiers) | 0 β¬ |
| Domain name (optional) | ~10β15 β¬ |
TOTAL β myblog.pages.dev |
0 β¬/year π |
TOTAL β yourname.com |
~12 β¬/year β |
Less than one fancy coffee per month for a real engineering blog. With math. With 3D. With your name on the URL.
Now Go Write Something
Markdown in. Beautiful blog out. AI handles the boring bits. You own the content, the brand, the domain.
No excuses left. π
Basem Rajjoub