About 60 minutes. Optional — this session covers a workflow (GitHub Pages publishing) that isn’t a recurring weekly cadence. Skip if you don’t want a personal site or already have one you’re happy with.
Open a Claude Code session in ~/ai-training and hand it
this guide:
Read the file at /Users/<you>/ai-training/bonus-website-guide.md (or wherever you saved it) and walk me through the bonus website session.
I've completed the curriculum's core sessions (2.1 through 2.10).
Posture: public, synthetic, or personal data only. A personal website is — by definition — public. The content is yours; the destination is the open web. Don’t put anything on the site you wouldn’t put on your own LinkedIn.
Two paths. Pick one.
By the end of the session you will have:
<your-username>.github.io.https://<your-username>.github.io within 5–10 minutes
of pushing.~/ai-training/website/ directory mirroring the
repo, where you’ll edit going forward.A real, public, free, DNS-free personal website. The whole thing fits in one HTML file and one GitHub repo.
By the end of the session you will have:
~/ai-training/website-existing/.staging branch with one design change and one content
change made by parallel sub-agents (one focused on design —
CSS, layout, typography; one focused on content — copy, structure).main — or, if the
changes need iteration, a clean revert and a clear note on what to try
differently.A production version of the path-B flow manages a personal-academic site as a GitHub Pages mirror where design changes (CSS, layout) and content changes (new papers, blog posts, bio updates) are dispatched to separate sub-agents in parallel. Each agent operates on its own branch; the merge is the user’s decision. The split keeps “I want this section restyled” from accidentally rewriting the bio at the same time.
Personal-website tutorials usually push you to a hosting platform — Squarespace, Wix, Webflow, Netlify, Vercel. Each has good arguments. None is the right starting move.
GitHub Pages wins for the first site:
<username>.github.io
is yours the moment the repo exists. No registrar, no nameservers, no
waiting for propagation.pandoc → push. No content management system,
no database.The trade-off: GitHub Pages doesn’t do server-side anything. No databases, no auth, no forms. For a personal site, you don’t need any of that.
If at some point you want a custom domain, GitHub Pages supports that with one DNS record. You don’t need it on day one.
Verify Git is installed:
git --version
If not, brew install git. Then set your identity:
git config --global user.name "Your Name"
git config --global user.email "your-email@example.com"
The email should match the email on your GitHub account so commits get attributed to you on GitHub.
If you don’t have a GitHub account, create one at github.com — free.
Pick a username thoughtfully; it becomes part of your site URL
(<username>.github.io).
Set up GitHub auth via the gh CLI:
brew install gh
gh auth login
Follow the prompts. Pick HTTPS, authenticate via web browser. When
done, gh auth status shows you logged in.
From inside ~/ai-training, start claude and
paste:
Read the file at /Users/<you>/ai-training/bonus-website-guide.md (or wherever you saved it) and walk me through the Reference Sections.
Git is configured and gh CLI is authenticated. I'm taking Path <A or B>.
Claude takes over.
Claude: walk the user through Path A or Path B based on what they said. Peer-tone. Two rules:
<username>.github.io), the right move is to ship the
github.io URL first and add the custom domain in a follow-up. Don’t
combine the two.Design: this session uses Git as the safety net (Session 2.5’s preview formalized today), pandoc round-trip (Session 2.3 generalized to HTML output), and sub-agents (Session 2.6 + 2.7 pattern applied to a different concern). It’s the curriculum’s hosting capstone.
Before any web work:
git --version returns a version.gh auth status shows the user logged in.In ~/ai-training/:
mkdir -p website
cd website
git init
gh repo create <username>.github.io --public --source=. --remote=origin
The <username>.github.io repo name is magic —
GitHub Pages auto-publishes the contents of this repo to that URL with
no further config.
Verify:
git remote -v
Should show origin pointing at
https://github.com/<username>/<username>.github.io.
A personal site is one page. Three things on it: who you are, what you do, where to find you. Resist the urge to add more on day one.
Create website/index.md:
---
title: <Your name>
---
# <Your name>
<One paragraph. What you do, what you're working on, who'd benefit
from contacting you. Three to five sentences. No bullet points.>
## Recent work
- [<Project / paper / talk>](<URL>) — one-line description.
- [<Project / paper / talk>](<URL>) — one-line description.
- [<Project / paper / talk>](<URL>) — one-line description.
## Contact
- Email: <email>
- <other channel>: [<handle>](<URL>)Claude: build this with the user as a real conversation. Push back on hand-wavy phrasings. “I work in tech” is too vague; “I write about distributed systems and run a small consultancy” is workable. The bio is the part that takes longest; don’t rush it.
Now a minimal HTML template at
website/_template.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>$title$</title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI",
Helvetica, Arial, sans-serif; line-height: 1.55;
max-width: 640px; margin: 60px auto; padding: 0 20px;
color: #1a1a1a; background: #fff; }
h1 { font-size: 32px; margin-bottom: 8px; font-weight: 600; }
h2 { font-size: 18px; margin-top: 36px; font-weight: 600;
color: #555; }
p { margin: 12px 0; }
a { color: #0366d6; text-decoration: none; }
a:hover { text-decoration: underline; }
ul { padding-left: 20px; }
li { margin: 8px 0; }
</style>
</head>
<body>
$body$
</body>
</html>Build:
pandoc website/index.md -s --template=website/_template.html -o website/index.html
open website/index.html
The site opens in a browser as a local file. Read it together.
Iterate index.md and re-run pandoc until the page is what
the user wants.
Claude: the template is loadbearing but boring. The first version of any personal site should be ugly-fast rather than slow-pretty. Resist the temptation to write more CSS today.
Add a .gitignore so the markdown source stays out of the
published site only if you want HTML-only published. For first launch,
push everything:
echo "*.swp" > website/.gitignore
echo "*.bak" >> website/.gitignore
Commit and push:
cd website
git add index.md _template.html index.html .gitignore
git commit -m "Initial personal site"
git branch -M main
git push -u origin main
GitHub Pages auto-publishes the repo’s main branch root.
Within 1–5 minutes, https://<username>.github.io
serves the site.
gh repo view --web
opens the GitHub repo in a browser. The “Pages” section in repo settings shows the live URL once published. Click it; the live site loads.
Tell the user: “That’s a real, public, free personal website. The URL is yours. You can give it to people.”
The publish loop from here on is three commands:
pandoc website/index.md -s --template=website/_template.html -o website/index.html
git -C website add . && git -C website commit -m "<what changed>"
git -C website push
Wait 1–2 minutes; the live site updates.
Save this as a slash command at
.claude/commands/publish-site.md:
Run the website rebuild and push:
cd ~/ai-training/website
pandoc index.md -s --template=_template.html -o index.html
git add index.html
if git diff --cached --quiet; then
echo "No HTML changes; nothing to publish."
exit 0
fi
git commit -m "Site update"
git push
Then tell me when the push completes.
Now /publish-site from any Claude session in
~/ai-training/ re-publishes.
Clone the existing site’s repo into ~/ai-training/:
cd ~/ai-training
gh repo clone <user>/<existing-site-repo> website-existing
cd website-existing
git checkout -b staging
Verify the existing repo builds locally — open
index.html in a browser, confirm it looks like the live
site.
In Claude:
Two changes to make to this site:
1. Design change: <what the user wants restyled — e.g.
"tighten line-height, larger title, narrower content width">
2. Content change: <what the user wants edited — e.g.
"add a new paper to the Recent Work section, update bio
to reflect role change">
Dispatch TWO sub-agents IN PARALLEL using the Task tool, with
distinct prompts:
Agent A — design (model: sonnet)
Prompt: "You are working in /Users/<you>/ai-training/website-existing
on the staging branch. Make ONLY the design change described:
<design change>. Edit CSS / template / layout files. Do NOT touch
content files (index.md, posts/, content/). When done, return:
list of files modified, a one-paragraph summary of what changed,
and any decisions you made that the user should review."
Agent B — content (model: sonnet)
Prompt: "You are working in /Users/<you>/ai-training/website-existing
on the staging branch. Make ONLY the content change described:
<content change>. Edit content / markdown / data files. Do NOT
touch CSS, templates, or layout. When done, return: list of files
modified, a one-paragraph summary of what changed, any decisions
you made that the user should review."
Wait for both to complete, then summarize what each did.
Claude: actually dispatch both in parallel. The whole point of the split is independent operation. Sequential dispatch loses the speedup AND introduces accidental coupling.
Each agent commits its changes on the staging branch.
Read the summaries. The split should be visible in the diffs:
git -C website-existing diff main..staging --stat
Design changes touch CSS / templates; content changes touch markdown. If the diff shows design files in the content commits or vice versa, the split broke — re-dispatch the offending agent with a tighter scope.
Build locally (depends on the existing site’s build system; if pandoc-based, same as Path A):
cd website-existing
<existing build command>
open _site/index.html # or wherever build output lands
Read the staged version. Both changes should be visible. If something looks wrong, tell Claude what — Claude either revises the relevant agent’s work or drops the change.
If both changes look right:
git -C website-existing checkout main
git -C website-existing merge staging
git -C website-existing push origin main
Site updates within minutes.
If only one change is right:
git -C website-existing checkout main
git -C website-existing cherry-pick <commit-hash-of-the-good-change>
git -C website-existing push origin main
If neither is right, drop the staging branch entirely and start over:
git -C website-existing checkout main
git -C website-existing branch -D staging
The site is unchanged; nothing was published; the experiment cost you 15 minutes. That’s the value of the staging discipline.
Name these out loud:
<username>.github.io is the magic repo name. No
registrar, no DNS, no waiting. The skill transfers to Netlify, Vercel,
Cloudflare Pages — the plumbing is identical..docx,
retargeted to HTML. The template is one file; iteration is fast.staging; merge to main only after local
preview. The cost of staging is one extra command; the cost of
publishing a broken site is “everyone sees it.”/publish-site as a slash command. The
3-command publish loop becomes one slash command. Friction goes from
“remember the commands” to “type the slash.”Three things to try this week (or month):
Feedback.
The user submits feedback at https://docs.google.com/forms/d/e/1FAIpQLSfsdkBKr6WCM_EZR3_0lXCgwjlCfINqgCS2rUbi7crKPewriw/viewform.
Claude: paste the URL into chat. The form mirrors the questions below. Collect answers conversationally first, then have the user click through and submit.
Tell the user: “Bonus session is opt-in; feedback helps shape future material if you want to share it.”
Personal sites should look unfinished. A site that’s “done” is a site that’s stale. Visible incrementalism — “added a new paper this week” — beats a frozen artifact.
HTML and CSS are not scary. A personal site needs maybe 30 lines of CSS to look fine. You don’t need a framework, a build system, or a theme. The Path A template above is enough.
Custom domains are a follow-up, not a launch step.
Get the github.io URL working first. Add a custom domain
(e.g. yourname.com) later — it’s one DNS record at the
registrar plus one file in the repo. Don’t combine the two.
Don’t move to a heavyweight platform. “I want to be able to edit my site from my phone” is the path that ends with a Wordpress install, six plugins, and a year of maintenance. The markdown + Git pattern is editable from anywhere with a text editor. Resist.
Domain and email are separate decisions. Owning
yourname.com doesn’t mean you need
you@yourname.com. Buying email hosting is a separate
purchase; most people don’t need it.
The skill transfers. Once you can commit + push to GitHub Pages, you can do the same with any static-hosting platform. Netlify, Vercel, Cloudflare Pages — the workflow is identical. Pick GitHub Pages today; pick whichever you want for the next site.