Put your website online free with GitHub Pages and Cloudflare Pages
A website is just a folder of files, and two big companies will host that folder for nothing. Your site is live on GitHub Pages in about 35 minutes, then Cloudflare Pages adds preview addresses and one-click rollbacks.
git push- Uploading straight from your PC with Wrangler, no Git needed
- A GitHub Actions workflow for sites with a build step (Vite, Astro and similar), and a clear rule for which host to pick
- Git and Python installed. If
git --versionorpython --versiondoesn't work, do Install anything from GitHub, safely first. Node.js LTS too, for step 6 only. - Comfortable making commits. Use Git without memorising commands covers stage, commit and branches; this mission adds pushing to GitHub.
- A free GitHub account (github.com/signup ↗) with a verified email address. On GitHub Free, Pages only publishes from public repositories (GitHub's docs ↗).
- A free Cloudflare account (dash.cloudflare.com/sign-up ↗) for steps 4 to 6. Static pages on Cloudflare Pages are free and unlimited on every plan (Pages pricing ↗).
- No card details. Nothing in this mission needs a paid plan.
Get the starter site and preview it on your PC
Always look at a site on your own computer before it goes public. It's faster, and mistakes stay private.
Download the starter kit: my-first-site.zip (7KB). It's a one-page site for a sample bike mechanic, written in plain HTML and CSS so there's nothing to install or build. Swap the words for yours.

The starter site. It follows the visitor's light or dark setting and fits a phone screen without any extra work. Unzip it into a folder called
Sitesin your home folder:Windowsmkdir $HOME\Sites -Force Expand-Archive $HOME\Downloads\my-first-site.zip -DestinationPath $HOME\Sites cd $HOME\Sites\my-first-siteMacmkdir -p ~/Sites && unzip ~/Downloads/my-first-site.zip -d ~/Sites cd ~/Sites/my-first-siteHere's what's inside. The website itself is only the
docsfolder; everything else stays in your repository but never gets published:docs/index.html: the page. All the words are here.docs/styles.css: colours, spacing and layout. The colours are the--lines at the top.docs/404.html: shown when someone visits an address that doesn't exist.docs/favicon.svg: the icon in the browser tab.docs/.nojekyll: an empty file that tells GitHub Pages to publish the files exactly as they are (step 3 explains)..gitignore: keeps junk files and any.envsecrets file out of Git.extras/deploy-vite-to-pages.yml: a workflow for sites with a build step. Ignore it until step 7.
Now serve the folder like a real web server would.
--bind 127.0.0.1keeps it visible only to your own PC, not everyone on your Wi-Fi:Windowspython -m http.server 8000 --bind 127.0.0.1 --directory docsMacpython3 -m http.server 8000 --bind 127.0.0.1 --directory docsOutputServing HTTP on 127.0.0.1 port 8000 (http://127.0.0.1:8000/) ...Open localhost:8000 ↗. Each file the browser asks for shows up in the terminal as a line with
200(found) in it. Then try localhost:8000/old-page ↗: you get Python's plain error page and a404line. That's expected. Python's little server doesn't use custom 404 pages, but both hosts will.Make it yoursOpen
docs/index.htmlin any text editor (Notepad is fine, VS Code is nicer), change the name, headline, services and email, save, and refresh the browser. Change--accentinstyles.cssto change the main colour.Why every link has no slash at the startThe page loads
styles.css, not/styles.css. On GitHub Pages your site lives in a sub-folder (username.github.io/my-first-site/), so/styles.csswould point atusername.github.io/styles.css, which doesn't exist, and the page would load with no styling. Relative links work in both places. The 404 page does the opposite and keeps its styles inside the file, because it's shown at any broken address in any folder.CarefulEverything indocswill be public, and on GitHub Free the whole repository is public too. No passwords, API keys, private notes or your home address. An email address on a public page will attract spam, so use one you don't mind giving out.Press Ctrl + C in the terminal to stop the server when you're done.
200 lines for / and /styles.css.If it breaks'python' is not recognised, or the Microsoft Store opens + 2 more
'python' is not recognised, or the Microsoft Store opens
'Only one usage of each socket address' or 'Address already in use'
8001, in the command and the address.The page loads but looks like a plain 1990s document
styles.css. Check you ran the command from the my-first-site folder with --directory docs, and that the file is still called styles.css in lower case.