Why this session exists
Your page has semantic regions, a nav, a photo, a skills table, a contact form, and its own styles.css. It works on your machine. Today it stops being a file and becomes a website: we check it the way professionals check (machines are better at finding your typos than you are), then put it on GitHub Pages - free, no credit card, no command line - and load it on a phone that is not yours.
The pre-flight checks 8 min live
Browsers forgive broken HTML silently, which means your page can look fine while being quietly wrong. Before shipping, professionals run three checks: an x-ray, a merciless proofreader, and a phone test.
LiveDevtools inspector - the x-ray2 min▶
Right-click any element on any page and choose Inspect. Devtools shows you the DOM - the structure the browser actually built, not the source you wrote. When those two disagree (an unclosed tag the browser repaired, a paragraph that swallowed its neighbor), the inspector is where the disagreement becomes visible.
- Hover a line in the inspector and the matching element highlights on the page - that is how you find "which tag is this box".
- Look for elements nested somewhere strange. If your footer appears inside your form in the inspector, the browser repaired a mistake and guessed wrong.
LiveThe W3C validator - zero-mercy proofreading3 min▶
Go to validator.w3.org, pick "Validate by File Upload" (or paste your source under "Direct Input"), and submit. It reads your file with zero forgiveness and lists every technical sin with a line number.
- Read errors top-down and fix the FIRST one first. One unclosed tag early in the file confuses the parser about everything after it - the first error often causes half the list. Fix it, re-validate, watch ten errors become two.
- Warnings are advice, errors are bugs. Ship with zero errors; read the warnings and decide.
<h2>My skills</h2> <p>Things I use <strong>every week.</p> <ul> <li>Spreadsheets</li> <li>Python <li>SQL</li> </ul> <p>Always learning more.
</strong> never closes, so bold leaks to the end of the paragraph. Bug 2: the Python <li> never closes. Bug 3: the last <p> never closes. All three render "fine" - which is exactly why the validator exists.
LiveThe viewport meta - why phones lie without it3 min▶
Phone browsers assume old pages were designed for desktop, so by default they render your page on a fake 980px-wide canvas and shrink the whole thing down - tiny unreadable text, pinch-zoom everywhere. One line in the head tells the phone to stop pretending:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport"
content="width=device-width, initial-scale=1">
<title>Phoebe Fu</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Ready to ship</h1>
</body>
</html>
width=device-width- "use the phone's real width, not the fake 980px".initial-scale=1- "start at 100% zoom, no shrinking".- Test before shipping: open devtools, click the little phone icon (device mode), pick a phone size. If your page needs sideways scrolling at phone width, fix that before it meets a real phone.
Self-studyA debugging order that works2 min read▶
When a page looks wrong, check in this order - cheapest first: 1) Did you save and reload? 2) Validator - unclosed tags and typos surface instantly. 3) Inspector - is the DOM shaped the way you think it is? 4) Only then suspect your CSS. In practice, steps 1 and 2 catch most of it; MDN's Debugging HTML lesson walks the same route with a deliberately broken demo file worth playing with.
Accessibility - the 6-point audit 7 min live
Accessibility is not an advanced topic bolted on at the end - it is mostly the honest HTML you have written all course, checked deliberately once before shipping. Six checks, two minutes each, and your page works for screen readers, keyboard users, and everyone squinting at a phone in the sun.
LiveChecks 1-4: honest alt, ladder, links, labels3 min▶
Four checks you can run by reading your own source. Each one is a promise your markup makes to someone who is not looking at the screen:
- 1 · Every img has honest alt. Describe what the image shows and why it is there:
alt="Phoebe presenting at a data meetup", notalt="photo". Purely decorative image?alt=""tells screen readers to skip it - honestly. - 2 · Headings form a ladder. One h1, then h2, then h3 - no skipping down. Screen-reader users navigate by the headings list; a skipped level is a missing stair.
- 3 · Links say where they go. Read only the link text aloud: would you know the destination?
- 4 · Every input has a label wired with
formatching the input'sid- Session 4's rule, now audited.
<img src="https://placehold.co/80x80" alt="image"> <p>My talk slides are online - <a href="https://example.com/slides">click here</a>.</p> <form> Your email <input type="email"> </form>
LiveChecks 5-6: contrast and lang2 min▶
- 5 · Color contrast. Body text needs at least a 4.5:1 contrast ratio against its background. Do not trust your eyes on your own monitor - paste your two hex colors into the WebAIM contrast checker and let it judge.
- 6 · The lang attribute.
<html lang="en">has been on your page since Session 1 - confirm it survived your edits. It picks the screen-reader voice and the translation source language.
<p style="color: #b3b3b3;"> Faint text feels elegant on your monitor and disappears on a phone in sunlight. </p>
One effort, three payoffs. The same six checks that help a screen-reader user are what search engines rank with (alt text, headings, link text, lang) and what makes the page usable for everyone (labels, contrast). Accessibility, SEO, and usability are not three jobs - they are one honest-markup job wearing three name tags.
GitHub Pages from absolute zero 7 min live
GitHub is a home for code folders - each folder is called a repository ("repo"), and millions of people store projects there for free. It has a bonus feature made for you: put HTML files in a repo, flip one switch, and GitHub serves them to the whole internet as a real website. No server to rent, no company to pay.
LiveThe recipe: account, repo, upload, switch4 min▶
- Account: sign up free at github.com. Your username becomes part of your URL - pick one you are happy saying out loud.
- Repo: click New repository and name it exactly
USERNAME.github.io(your real username) - that magic name publishes at the root URL. Any other repo name works too via Settings, it just lives atusername.github.io/repo-name/. - Upload: in the repo, "uploading an existing file" - then drag
index.html,styles.css, and yourimages/folder straight from your file manager into the browser. Commit (that is GitHub's word for "save"). - Switch: Settings → Pages → under "Build and deployment" choose Deploy from a branch, pick
main, save. Your URL appears at the top of that page. - Wait: first publish can take a few minutes. Refresh the URL, not your patience.
Self-studyWhat that name means, and updating later2 min read▶
Why index.html mattered all course: when someone visits username.github.io, the server looks for a file named exactly index.html and shows it. That default was set in Session 1 and pays off today.
- Updating: edit the file locally, then upload it again with the same name - GitHub replaces the old one. Give it a minute, hard-refresh, done.
- Adding pages: upload
about.htmland it is live atusername.github.io/about.html- your Session 2 links between pages now work on the real internet.
Validate to zero ★ 6 min · follow along
We feed the project page to the validator and fix every error live - top-down, first error first - until the green "no errors" banner appears.
Open validator.w3.org → "Validate by File Upload" → choose your index.html → Check.
Read the first error only. Note its line number, open your file at that line, fix it, save.
Re-upload and re-check. Watch errors caused by the first one vanish without being touched.
Repeat until zero errors. Skim the warnings; fix any that are cheap.
Validate styles.css too if you like - the CSS validator lives at jigsaw.w3.org/css-validator, same ritual.
The 6-point audit, live on your page ★ 5 min · build your own
Run the strip from Part 2 against your own file. Most of you pass 4 or 5 already - fix the stragglers now, before the internet sees them.
Alt text: find every <img>, read the alt out loud, rewrite any that say "photo" or "image".
Headings: open devtools, search the DOM for h1, h2, h3 - confirm one h1 and no skipped levels.
Links: read only the link texts. Rewrite any "click here" or bare "here".
Labels: every form input gets a <label for> matched to its id - Session 4's form is the place to look.
Contrast: paste your text and background colors from styles.css into the WebAIM checker. 4.5:1 or darken.
Lang: confirm <html lang="en"> is intact. Six for six? You are cleared to ship.
SHIP IT ★ 9 min · everyone ships
Six sessions ago this was an empty text file. Now we put it where every website lives: on a URL. Do these steps with us, right now, and leave this session with your page on the internet.
Create your GitHub account (or sign in), click New repository, name it exactly USERNAME.github.io, keep it Public, create.
Click "uploading an existing file" and drag in index.html, styles.css, and your images/ folder. Commit changes.
Settings → Pages → Deploy from a branch → main → Save. Copy the URL it shows you.
Wait for the first build (grab water, it earns the drama), then open the URL. There it is.
Now the real test: open the URL on your phone. Not the file - the URL. Your viewport meta from Part 1 is why it reads beautifully.
Last step, non-optional: send the link to someone you like. A friend, a parent, a group chat. The moment someone else's device shows your page, you are a person who ships websites. Welcome to the club - it has no fees and excellent members.
This exact pipeline is professional practice, not a toy: docs sites, data project portfolios, and startup landing pages ship on GitHub Pages every day. The page you just published is built with the same skeleton, the same semantic regions, and the same checks a professional would run. The difference between you and "someone who can make websites" is now zero.
Try it yourself - this week ◐ 30-45 min total
- Share the URL somewhere that mildly scares you - a group chat, a bio, LinkedIn. Pages that no one visits quietly stop being maintained.
- Add one more content section entirely solo - a "Now" section, a reading list, a project write-up. Draft to live URL without looking anything up, if you can.
- Re-run the validator after your edits. New content means new chances for unclosed tags - the check is two minutes, make it a reflex.
- Load your page on the slowest connection you can find (phone, one bar). Notice what loads first - that is Session 3's image sizing paying rent.
- You have graduated - the remaining three deep dives are self-paced dessert: interactive HTML without JavaScript (6.1), embeds and vectors (6.2), and the professional head (6.3). Start with 6.1; it will surprise you.
Official sources covered
This session teaches the working content of MDN's Debugging HTML, the W3C validator, and the GitHub Pages getting-started docs, with accessibility essentials distilled from MDN and web.dev.
Three questions before you go 🎯 ◐ 90 seconds
1 · Your page looks perfect on desktop but is microscopic on a phone. The most likely missing piece is...
Without the viewport meta, phone browsers render on a fake 980px canvas and shrink everything. width=device-width, initial-scale=1 tells them to use the real screen.
2 · The validator reports 27 errors. The professional first move is...
Early errors confuse the parser about everything after them, so the first error often causes half the list. Fix it, re-check, and watch the count collapse.
3 · To publish at the root URL https://phoebe.github.io, the repo must be named...
The magic user-site repo is named exactly USERNAME.github.io. Any other repo name still works, but publishes under a subpath like phoebe.github.io/my-site/.