Publishing.
How to take a finished site and put it online. The two main hosts I use, when to pick which, and the gotchas that show up on your bill if you don't know about them.
The big picture
Publishing has three pieces: getting your code into GitHub (so you have version history and a place to push from), choosing a host (GitHub Pages or Netlify, mostly), and pointing a domain at it (Porkbun is what I use). Let's walk through each.
Step 0: Get a GitHub account
If you've never used GitHub before, here's the quick orientation. GitHub is a free service for storing code online. It's also a backup, a version history (so you can roll back to any earlier version of your project), and the launchpad for putting your site on the web. Free for public projects (which is what we'll use).
-
Sign up at github.com
Click "Sign up." Pick a username — keep it professional, you'll be sharing repo URLs that include this name. Use a real email. Free plan is fine.
-
Verify your email
GitHub will send a confirmation. Click the link.
-
Skip the onboarding fluff
GitHub will try to walk you through tutorials and ask which features you want. You can skip past most of it.
-
Make your first repo
Click the green "+" or "New" button. Name it (e.g.
my-first-siteor your client's name). Set it to Public if you want to use the free GitHub Pages hosting. Don't check "Initialize this repository with a README" — leave it empty so your local files can be the first thing in there. Click "Create repository." -
Leave the resulting page open
GitHub will show you a page with code snippets ("…or push an existing repository from the command line"). You'll use those in the next step.
Step 1: Get your code on GitHub
Even if you never deploy from GitHub, this step is non-negotiable. GitHub is your backup, your version history, and your "I broke it, give me yesterday" insurance.
If you're using Claude Code
Inside your project folder, ask Claude:
Claude will run all the right commands. If it gets stuck on authentication (GitHub asks for a token instead of a password these days), Claude will tell you what to do — usually involves creating a "Personal Access Token" in GitHub settings, which Claude will walk you through.
If you're not using Claude Code
Use GitHub Desktop — it's free, has a graphical interface, and skips the terminal entirely. After installing:
- Sign in with your GitHub account.
- File → "Add Local Repository" → pick your project folder.
- It'll prompt you to create a Git repo if there isn't one — say yes.
- Make your first commit (write a message like "first commit," click Commit).
- Click "Publish repository" at the top → uncheck "Keep this code private" if you want it public → Publish.
Done. Your code is on GitHub.
Step 2: Pick a host
Two realistic free options for static HTML sites: GitHub Pages and Netlify. Here's the comparison:
| Feature | GitHub Pages | Netlify |
|---|---|---|
| Cost (small site) | Free | Free tier, then paid |
| Setup difficulty | Very easy (one toggle in repo settings) | Easy (connect GitHub repo) |
| Auto-deploy on push | Yes | Yes |
| Custom domain | Yes (HTTPS included) | Yes (HTTPS included) |
| Forms (e.g. contact form) | No | Yes (100 submissions/month free) |
| Redirects & rewrites | Limited | Yes |
| Build limits | Generous (effectively unlimited for static sites) | 300 build minutes/month free, then $7/mo for more |
| Bandwidth | 100 GB/month soft limit | 100 GB/month free, then paid |
When to use GitHub Pages
Static site, no forms, no fancy redirects, just HTML/CSS/JS. Most personal sites and small business sites fit here. Free, no surprises, and the URL pattern is username.github.io/repo-name (or your custom domain if you set one up).
When to use Netlify
You need contact form submissions, you want preview URLs for branches, or you're going to use serverless functions later. Most client work that needs a contact form ends up on Netlify.
⚠ Netlify build minutes can sneak up on you
Netlify's free tier gives you 300 build minutes per month. A static site with no build step uses about 30 seconds per deploy — which sounds like a lot of room. But: Netlify deploys every time you push to GitHub. If you're pushing 50 small tweaks during the final review week, you can burn through 300 minutes faster than you'd expect, especially if you have build steps that take longer.
The fix is workflow:
- Develop locally and review in the browser before each push.
- For client review during the build phase, don't put the site on Netlify yet. Use GitHub Pages — it's free, build limits are generous, and the URL is fine for review purposes.
- Switch to Netlify only when the site is final or near-final and the client wants the production URL.
- Bundle small changes. Don't push
fix typo, thenfix another typo, thenfix one more typo— pushfix typos and tighten copyonce.
GitHub Pages walkthrough
-
Push your code to GitHub
Per Step 1 above. Make sure your main file is called
index.htmlat the root of the repo. -
Enable Pages
Go to your repo on github.com → Settings → Pages. Under "Source," pick "Deploy from a branch." Pick
mainand/ (root). Save. -
Wait 1–2 minutes
GitHub will build and deploy your site. Refresh the Pages settings page — when it's ready, the URL appears at the top.
-
Visit and test
Your site is live at
https://yourname.github.io/repo-name/. Open it on your phone. Walk through every page. Check images load.
Netlify walkthrough
-
Sign up
Go to netlify.com and sign up with your GitHub account.
-
Import your repo
Click "Add new site" → "Import existing project" → "Deploy with GitHub" → pick your repo. Netlify auto-detects static sites; you can leave the build settings blank.
-
Wait ~30 seconds
First deploy is fast for static sites. You'll get a random URL like
silver-river-12345.netlify.app. -
Rename the URL
Site Settings → Site information → "Change site name." Pick something clean —
acf-foster-youth.netlify.appbeats the random one. -
Auto-deploys are on
From now on, every push to
maintriggers a new deploy automatically. (See the build minutes warning above.)
Step 3: Custom domain
Both GitHub Pages and Netlify support custom domains. The flow is the same: buy a domain at a registrar, point its DNS at your host. I use Porkbun because it's cheap and the interface isn't aggressive about upsells.
Buy the domain
- Go to porkbun.com, search the domain, buy it. Most .com domains run $10–15/year. Skip the upsells (privacy is included free, hosting upsells you don't need).
- You now own the domain.
Point DNS
The exact steps differ depending on host. The cleanest method is using Porkbun's name servers when you don't need email tied to the domain — but for most clients I use direct A and CNAME records so they keep control.
For Netlify
- In Netlify: Site Settings → Domain management → Add custom domain → enter your domain.
- Netlify shows you the DNS records to add. Usually an
Arecord pointing at Netlify's IP, and aCNAMEfor www. - In Porkbun: Domain Management → DNS Records → add the records Netlify gave you.
- Wait. DNS propagation can take 10 minutes to several hours.
- Netlify will auto-issue an HTTPS certificate (Let's Encrypt) once DNS propagates. No action needed.
For GitHub Pages
- In your repo: Settings → Pages → Custom domain → enter your domain. GitHub creates a
CNAMEfile in your repo. - In Porkbun: add four
Arecords pointing at GitHub Pages' IPs (185.199.108.153, 185.199.109.153, 185.199.110.153, 185.199.111.153) plus aCNAMEfor www pointing atyourname.github.io. - Wait for propagation. Once it lands, in your repo's Pages settings, check "Enforce HTTPS."
⚠ DNS changes are slow
If you point DNS and the domain doesn't work in 5 minutes, don't panic and start changing things. DNS can take anywhere from a few minutes to a full day to propagate. Wait a few hours before assuming something's wrong.
Cost summary across the whole stack
| Service | What it costs | How you can rack up charges |
|---|---|---|
| GitHub | Free for public repos | Private repos with multiple collaborators may need a paid plan ($4/mo) |
| GitHub Pages | Free | Almost impossible to overage at small-site scale |
| Netlify | Free tier, $19/mo Pro | Going over 300 build minutes or 100 GB bandwidth in a month |
| Cloudinary | Free tier (25 GB), then $99/mo+ | Uploading lots of unused images, hot weeks of traffic |
| Porkbun (domain) | $10–15/year | Auto-renewal you forgot about, premium domain markup |
| Anthropic API (Claude Code) | Pay-per-use; usually a few cents per build session | Long sessions with massive context (paste of huge files repeatedly) |
✓ Realistic monthly cost for a small client site
For a typical small business or nonprofit site you build with this workflow, hosted on Netlify with a custom domain, with Cloudinary for images and a healthy free-tier of Anthropic API usage:
~$1–2/month total, mostly the domain renewal divided across 12 months. If you stay on GitHub Pages instead of Netlify, you can drop that even lower.
Common mistakes
- Putting client review on Netlify before the site is final. Use GitHub Pages for review. Move to Netlify when the site is locked.
- Not enforcing HTTPS. Both GitHub Pages and Netlify have a one-click toggle. Always on.
- Pushing 50 tiny commits during the final week. Burns build minutes on Netlify. Bundle changes.
- Forgetting to renew the domain. Set Porkbun to auto-renew. Losing a client's domain is the worst.
- Storing API keys in your repo. If you start using Anthropic API or Stripe in your sites, never commit the keys. Use environment variables.
- Not testing the live site after deploy. Localhost is not the live site. Open the deployed URL on your phone and on a desktop browser. Click every link. Submit forms.
How ACF was published
ACF lives at advancingcommunitiesforward.com. During the build phase, client review was on a temporary GitHub Pages URL. Once everything was finalized, we moved the deployment to Netlify, set up the custom domain through Porkbun, and the production URL went live.
Ongoing costs: $11.16/year for the domain. That's it. Cloudinary and Netlify both stay on free tiers. The whole hosting stack costs less than a coffee.
What's next
Site is live. The hard part is over. Next chapter is the field guide for what tends to go wrong after launch — and how to dodge the most common traps.