Build a Website with Claude Code

Build and deploy a responsive public speaking landing page.

Introduction

30 Second Summary

If you speak at events, lead workshops, or coach teams, people will Google you. What they find matters. A clean, professional landing page is the difference between getting booked and getting passed over.

In this project, you will build and deploy a responsive landing page for a public speaking business using only the terminal. You will write HTML and CSS from scratch, manage your code with Git, and publish the finished site to a live URL on GitHub Pages.

What You'll Build

When you share your URL with an event organizer, they will see a bold hero section with your name and tagline, scroll through your speaking topics, read testimonials from past events, and land on a clear call-to-action to book you.

By the end of this project, you'll have:

  • A live website at a real URL that you can text to anyone and they can view instantly on their phone, tablet, or desktop.
  • A responsive layout that adapts from a single-column design on mobile to a multi-column grid on desktop, solving the problem every web developer faces.
  • Hands-on experience with Claude Code as your terminal-based editor, writing real code and running Git commands without ever leaving the command line.
  • Secret Mission: Add smooth scroll behavior and a dark mode toggle that remembers the visitor's preference.

Are there any prerequisites?

None. This guide walks you through everything from folder setup to deployment. You just need a Mac with a terminal and a GitHub account.

Before We Start

Before we dive in, let's lock in what you're about to build and why it matters.

An event organizer is going to land on your page. Think about what you want them to feel and do when they arrive.

Set Up Your Project

Every website needs a home before you write a single line of code. You need a folder on your computer, a way to track changes to your files, and a place to host the final result online.

In this step, you'll verify that Git is ready on your machine, create a project folder, and connect it to a GitHub repository so you can deploy your page later.

In this step, get ready to:
  • Verify Git is available on your machine.
  • Create your project folder and connect it to a GitHub repository.
  • Add starter files for your landing page.
Verify Git and create your project folder

Git comes pre-installed on macOS. Let's confirm it's working before we rely on it for the rest of the project.

  • Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
  • Type Terminal and press Enter to open it.
  • Check that Git is installed by running this command:
git --version

✔️ I see a version number

You should see something like git version 2.39.5 (the exact number doesn't matter). Git is ready to go.

ⓧ I see a dialog or command not found

On macOS, you may see a pop-up asking to install Command Line Developer Tools. Click Install in the dialog and wait for the download to finish (this can take a few minutes).

Once the installation completes, run git --version again to confirm you see a version number.

Now create your project folder on the Desktop so you can find it easily.

  • Move to your Desktop by running this command:
cd ~/Desktop
  • Create your project folder and move into it by running these commands:
mkdir speaking
cd speaking
  • Initialize a new Git repository by running this command:
git init -b main

You should see output that says Initialized empty Git repository in /Users/.../Desktop/speaking/.git/.

What does git init do?

This command turns your speaking folder into a Git repository. Git will now track every change you make to files inside this folder.

The -b main flag sets the default branch name to main, which is what GitHub expects.

Seeing permission denied?

Make sure you ran cd ~/Desktop first. If your Desktop has restricted permissions, try cd ~ instead and create the folder there.

Help me fix this permission error

Connect your project to GitHub

Your project folder lives only on your computer right now. You need a matching repository on GitHub so you can push your code there and deploy it later with GitHub Pages.

  • Open your browser and go to github.com.
  • Sign in to your GitHub account (jamal-nextwork).
  • In the upper-right corner, click the + icon, then select New repository.
  • In the Repository name field, type speaking.
  • Set the visibility to Public.
  • Do not check any boxes under the initialization options (no README, no .gitignore, no license).
  • Click Create repository.

Why leave the repository empty?

You already initialized Git locally with git init. If GitHub also creates files (like a README), you'll get a merge conflict when you try to push. An empty remote avoids that problem entirely.

After creating the repository, GitHub shows a Quick Setup page. Switch back to your terminal to connect the two.

  • Add your GitHub repository as the remote origin by running this command:
git remote add origin https://github.com/jamal-nextwork/speaking.git

Before you verify the connection, what do you think git remote -v will print?

  • Confirm the remote is connected by running this command:
git remote -v

You should see your GitHub repository URL printed twice (once for fetch, once for push):

origin  https://github.com/jamal-nextwork/speaking.git (fetch)
origin  https://github.com/jamal-nextwork/speaking.git (push)

Not seeing the remote URL?

Double check that you typed the repository URL exactly as shown. The format is https://github.com/jamal-nextwork/speaking.git.

If you made a typo, remove the remote and try again:

git remote remove origin
git remote add origin https://github.com/jamal-nextwork/speaking.git

Help me troubleshoot the remote connection

Create your starter files

GitHub Pages needs an index.html file as the entry point for your site. You also need a special file called .nojekyll to tell GitHub Pages to serve your files directly.

  • Create both files by running this command:
touch .nojekyll index.html

What is .nojekyll?

GitHub Pages runs a tool called Jekyll by default, which processes your files before serving them. An empty .nojekyll file in your project root disables this behavior and tells GitHub to serve your HTML directly without any extra processing.

  • Confirm the files exist by running:
ls -a

You should see .nojekyll and index.html listed in the output (along with .git).

Don't see .nojekyll in the listing?

Files that start with a dot are hidden by default. Make sure you used ls -a (with the -a flag) instead of plain ls. The -a flag shows all files including hidden ones.

Help me view hidden files in the terminal

Your project skeleton is ready. You have a Git repository on your machine connected to GitHub, with starter files waiting for content. Next up, you'll fill index.html with your speaking business content and see it in the browser.

Build the Raw HTML

In the previous step, you set up your project folder, initialized Git, and connected to GitHub. Now it's time to fill that empty index.html with real content.

Before any styling, you need content on screen. This step gets your actual speaking business content into a browser window so you can see it, even though it looks plain and unstyled.

In this step, get ready to:
  • Write the full HTML structure with all four page sections.
  • Preview the page in your browser to confirm all content renders.
  • Commit your progress to Git.
Write the HTML structure in Claude Code

Your landing page needs four distinct sections that guide a visitor from learning who you are, to seeing what you speak about, to reading social proof, to taking action and booking you.

  • In your Claude Code session, ask it to replace the empty index.html with a full HTML landing page by typing this prompt:
Replace the contents of index.html with a complete HTML landing page for a public speaker named Jamal. In the head, include charset UTF-8, a viewport meta tag, the title "Jamal | Public Speaker", a link to styles.css, and Google Fonts preconnect links for the Inter font (weights 400, 600, 700). In the body, create four sections: 1) A hero section with the heading "Jamal", tagline "Inspiring teams to lead with clarity and confidence", and a "Book Me to Speak" call-to-action button linking to #contact. 2) A topics section titled "What I Speak About" with three cards: Leadership in Tech, Career Transitions, and The Power of Storytelling, each with a short description. 3) A testimonials section titled "What People Say" with two blockquotes from Sarah Chen (TechConf 2025) and Marcus Rivera (VP Engineering at Acme). 4) A contact section titled "Let's Work Together" with a "Get in Touch" mailto link to hello@jamal.com. End with a footer that says "Built by Jamal with Claude Code".
  • Claude Code shows you a diff of the changes. Accept the edit to write the file.

What did Claude Code just do?

Claude Code created a complete HTML document with two major parts. The <head> contains metadata that browsers and search engines read (character encoding, viewport sizing for mobile, a page title, and font links). The <body> contains everything a visitor actually sees on the page.

Each section uses semantic HTML elements with id and class attributes. The id lets you link directly to a section (like the CTA button linking to #contact). The class gives CSS a hook to style it later.

Verify your file matches the expected structure

Claude Code can sometimes generate slightly different code than expected. Check your file against these reference blocks to make sure the structure is correct.

  • View the contents of your file by running:
cat index.html

The top of your file should contain the document head and hero section:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Jamal | Public Speaker</title>
    <link rel="stylesheet" href="styles.css">
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
</head>
<body>
    <section id="hero" class="hero">
        <h1>Jamal</h1>
        <p class="tagline">Inspiring teams to lead with clarity and confidence</p>
        <a href="#contact" class="cta-button">Book Me to Speak</a>
    </section>

What does the head section do?

  • The viewport meta tag tells mobile browsers to match the screen width instead of zooming out to desktop size.
  • The preconnect links tell the browser to start connecting to Google Fonts early, so the font loads faster.
  • The styles.css link points to a file that doesn't exist yet. That's fine. You'll create it in the next step.

The middle of your file should contain the topics section with three cards:

    <section id="topics" class="topics">
        <h2>What I Speak About</h2>
        <div class="topics-grid">
            <div class="topic-card">
                <h3>Leadership in Tech</h3>
                <p>How to build and lead high-performing engineering teams while staying human.</p>
            </div>
            <div class="topic-card">
                <h3>Career Transitions</h3>
                <p>Navigating pivots, overcoming imposter syndrome, and betting on yourself.</p>
            </div>
            <div class="topic-card">
                <h3>The Power of Storytelling</h3>
                <p>Using narrative to influence, persuade, and connect with any audience.</p>
            </div>
        </div>
    </section>

The rest of your file should contain the testimonials, contact section, and footer:

    <section id="testimonials" class="testimonials">
        <h2>What People Say</h2>
        <div class="testimonials-grid">
            <blockquote class="testimonial-card">
                <p>"Jamal's talk was the highlight of our conference. Authentic, actionable, and unforgettable."</p>
                <cite>- Sarah Chen, TechConf 2025</cite>
            </blockquote>
            <blockquote class="testimonial-card">
                <p>"Our team still references lessons from Jamal's keynote six months later."</p>
                <cite>- Marcus Rivera, VP Engineering at Acme</cite>
            </blockquote>
        </div>
    </section>

    <section id="contact" class="contact">
        <h2>Let's Work Together</h2>
        <p>Available for keynotes, workshops, and panel discussions.</p>
        <a href="mailto:hello@jamal.com" class="cta-button">Get in Touch</a>
    </section>

    <footer>
        <p>Built by Jamal with Claude Code</p>
    </footer>
</body>
</html>

What do these sections do?

  • The topics-grid and testimonials-grid wrapper divs give CSS something to target when arranging cards into columns later.
  • The <blockquote> element is semantically correct for quoting someone else's words.
  • The mailto: link opens the visitor's email client with your address pre-filled.

Claude Code generated different code?

Claude Code may produce slightly different HTML than shown above. The important things to check are:

  • All four section IDs exist: hero, topics, testimonials, and contact.
  • The class names match exactly (cta-button, topic-card, testimonial-card, topics-grid, testimonials-grid).
  • If any are different, ask Claude Code to fix specific sections: "Change the class on the testimonial quotes to testimonial-card."

help me fix my HTML structure to match the expected class names

✔️ Awesome, I've got everything!

Great. Make sure you've saved your file.

ⓧ I'd like to double check the full code

Your index.html should contain all of the sections shown in the three reference blocks above, in this order:

  • Document head with viewport meta, title, styles.css link, and Google Fonts links.
  • Hero section with your name, tagline, and CTA button.
  • Topics section with three cards inside a grid wrapper.
  • Testimonials section with two blockquotes inside a grid wrapper.
  • Contact section with heading, description, and mailto link.
  • Footer with credit line.

Scroll up and compare each reference block against your cat index.html output to confirm they match.

Preview in your browser and commit

Your HTML is written. Before you think about styling, take a look at what the browser does with raw HTML and no CSS.

  • Open your page in the browser by running:
open index.html

Before you look at the browser, predict what you'll see. Will it look like a finished website, or something different?

You should see your name, tagline, speaking topics, testimonials, and a contact button all rendered as plain, unstyled text with default browser formatting. Everything is there, but it looks like a basic document. No colors, no layout, no spacing.

Why does it look so plain?

Without CSS, browsers apply default styles: black text on a white background, Times New Roman font, and elements stacked top to bottom. Every heading, paragraph, and link is functional but visually raw.

This is actually a good sign. It means your HTML structure is solid and all your content is accessible. The next step transforms this into something that looks professional.

  • Commit your progress by running:
git add . && git commit -m "Add HTML structure"
  • Confirm the commit succeeded. You should see a message showing the commit hash and Add HTML structure as the commit message.

Browser shows a blank page?

  • Check that index.html is not still empty. Run cat index.html in the terminal. If it's blank, Claude Code may not have saved the edit. Ask Claude Code again to write the file.
  • Make sure you accepted the diff when Claude Code proposed the changes. If you rejected it, the file stays empty.

help me figure out why my index.html is blank in the browser

Your content is on screen and committed to Git. Next up, you'll add CSS to transform this plain document into a polished, professional-looking landing page.

Style with CSS

Your landing page content is on screen, but it looks like a plain text document with default browser formatting. Times New Roman, no spacing, no visual hierarchy.

CSS transforms that raw content into something professional. In this step, you'll add colors, typography, spacing, and layout that builds credibility with event organizers who visit your page.

In this step, get ready to:
  • Create a styles.css file with color variables and base typography.
  • Style each section with backgrounds, cards, and a prominent call-to-action button.
  • Commit your styled page to Git.
Create the stylesheet with base styles

Your index.html already links to a file called styles.css (you set this up in the previous step). The browser is looking for that file but can't find it yet. You need to create it.

  • Create the styles.css file by running this command:
touch styles.css
  • Confirm the file exists by running:
ls

You should see index.html, styles.css, and .nojekyll in the output.

Now you'll add the foundation styles that every other rule builds on. CSS custom properties let you define your color palette once and reuse it everywhere.

  • Open styles.css in Claude Code and add the following base styles:
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

:root {
    --color-bg: #ffffff;
    --color-text: #1a1a1a;
    --color-accent: #2563eb;
    --color-accent-hover: #1d4ed8;
    --color-muted: #6b7280;
    --color-surface: #f3f4f6;
    --color-border: #e5e7eb;
}

body {
    font-family: 'Inter', sans-serif;
    color: var(--color-text);
    background-color: var(--color-bg);
    line-height: 1.6;
}

What does this code do?

  • The * selector resets all default margins and padding. This gives you a blank canvas instead of fighting browser defaults.
  • The :root block defines your color palette as reusable variables. When you write var(--color-accent) later, it pulls in #2563eb (a professional blue).
  • The body rule applies the Inter font from Google Fonts (already linked in your HTML) and sets comfortable reading line height.
  • Save styles.css and refresh your browser.

Your page text now appears in the Inter font with tighter spacing. The Times New Roman default is gone.

Still seeing Times New Roman?

  • Check that styles.css is in the same folder as index.html. The <link> tag in your HTML expects them side by side.
  • Make sure you saved both files before refreshing.
  • Try a hard refresh with Cmd+Shift+R to clear cached styles.

Still stuck? Why isn't my CSS file being loaded by the browser?

Style the hero section

The hero is the first thing visitors see. It needs to command attention with a bold heading, a clear tagline, and a bright call-to-action button.

  • Add the hero styles below your body rule in styles.css:
.hero {
    text-align: center;
    padding: 4rem 1.5rem;
    background-color: var(--color-surface);
}

.hero h1 {
    font-size: 2.5rem;
    font-weight: 700;
    margin-bottom: 0.5rem;
}

.tagline {
    font-size: 1.125rem;
    color: var(--color-muted);
    margin-bottom: 2rem;
    max-width: 500px;
    margin-left: auto;
    margin-right: auto;
}

.cta-button {
    display: inline-block;
    background-color: var(--color-accent);
    color: #ffffff;
    padding: 0.875rem 2rem;
    border-radius: 8px;
    text-decoration: none;
    font-weight: 600;
    transition: background-color 0.2s;
}

.cta-button:hover {
    background-color: var(--color-accent-hover);
}

What does this code do?

  • The .hero section gets a light gray background (var(--color-surface)) and centered text to create a distinct landing zone.
  • The tagline uses margin-left: auto and margin-right: auto with a max-width to keep it readable and centered.
  • The .cta-button uses transition: background-color 0.2s so the hover color change feels smooth instead of jarring.
  • Save styles.css and refresh your browser.

The hero section now has a light gray background, a large bold heading, a muted tagline, and a bright blue "Book Me to Speak" button.

Button not showing the blue background?

  • Confirm the class name in your HTML is class="cta-button" (with a hyphen, not underscore).
  • Check that .cta-button in your CSS starts with a dot. Without it, the browser looks for an HTML element called <cta-button> which doesn't exist.

Need help? Why isn't my CTA button styled?

Style topics, testimonials, and footer

The remaining sections need a card-based layout for topics, styled quote blocks for testimonials, and a contrasting background for the contact CTA.

  • Add the topics and grid styles below your .cta-button:hover rule in styles.css:
.topics,
.testimonials,
.contact {
    padding: 3rem 1.5rem;
    max-width: 900px;
    margin: 0 auto;
}

.topics h2,
.testimonials h2,
.contact h2 {
    font-size: 1.75rem;
    margin-bottom: 1.5rem;
    text-align: center;
}

.topics-grid,
.testimonials-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.5rem;
}

.topic-card {
    background-color: var(--color-surface);
    padding: 1.5rem;
    border-radius: 8px;
    border: 1px solid var(--color-border);
}

.topic-card h3 {
    font-size: 1.125rem;
    margin-bottom: 0.5rem;
}

.topic-card p {
    color: var(--color-muted);
}

What does this code do?

  • The shared .topics, .testimonials, .contact rule centers content with margin: 0 auto and caps width at 900px so text lines stay readable.
  • The display: grid with grid-template-columns: 1fr creates a single-column layout. You'll expand this to multiple columns for larger screens in the next step.
  • Each .topic-card gets a subtle border and rounded corners to look like a tidy, distinct card.
  • Save styles.css and refresh your browser.

You should see three topic cards stacked vertically, each with a light background and a thin border.

  • Now add the testimonial, contact, and footer styles below your .topic-card p rule:
.testimonial-card {
    background-color: var(--color-surface);
    padding: 1.5rem;
    border-radius: 8px;
    border-left: 4px solid var(--color-accent);
}

.testimonial-card p {
    font-style: italic;
    margin-bottom: 0.75rem;
}

.testimonial-card cite {
    color: var(--color-muted);
    font-size: 0.875rem;
}

.contact {
    text-align: center;
    background-color: var(--color-surface);
    border-radius: 8px;
    margin-top: 2rem;
    margin-bottom: 2rem;
}

.contact p {
    color: var(--color-muted);
    margin-bottom: 1.5rem;
}

footer {
    text-align: center;
    padding: 2rem 1.5rem;
    color: var(--color-muted);
    font-size: 0.875rem;
}

What does this code do?

  • The .testimonial-card uses border-left: 4px solid var(--color-accent) to create a bold blue accent stripe. This is a common pattern for pull quotes.
  • The .contact section gets its own surface background and rounded corners so it visually stands out as a final call-to-action area.
  • The footer uses muted color and smaller font size to stay visually quiet.

Before you refresh, what do you expect the testimonials section to look like now?

  • Save styles.css and refresh your browser.

The full page is now styled. Testimonials show italic text with a blue left border. The contact section has a gray background with a centered blue button. The footer sits quietly at the bottom.

Testimonials not showing the blue left border?

  • Check that your HTML uses class="testimonial-card" on the <blockquote> elements (with a hyphen between "testimonial" and "card").
  • Make sure the .testimonial-card rule uses border-left (not border). A plain border would add the accent to all four sides.

Need help? Why aren't my testimonial card styles applying?

  • Commit your styled page by running:
git add . && git commit -m "Add CSS styling"

You should see a commit message confirming two files changed (styles.css created and any minor updates).

✔️ Awesome, I've got everything!

Great. Double check you've saved styles.css and that your commit went through.

ⓧ I'd like to double check the full code

Your styles.css is longer than 30 lines, so scroll up and confirm these sections are present in order:

  • CSS reset (* selector with margin, padding, box-sizing).
  • :root block with seven color variables.
  • body rule with Inter font and line-height.
  • .hero, .hero h1, .tagline, .cta-button, and .cta-button:hover rules.
  • Shared section padding (.topics, .testimonials, .contact) and shared h2 styles.
  • Grid rules for .topics-grid and .testimonials-grid.
  • .topic-card styles (background, border, border-radius).
  • .testimonial-card styles (border-left accent).
  • .contact and footer styles.

Your plain HTML document now looks like a professional landing page. Next up, you'll tackle the responsive design problem that appears when someone views this page on their phone.

Fix the Mobile Layout

Your landing page is styled and looks great at full desktop width. But here is the question every web developer has to face: what happens when someone opens your page on their phone?

Right now your page uses the same layout regardless of screen size. It does not adapt. This is the responsive design problem, and solving it is a core skill for every web developer.

In this step, get ready to:
  • Observe how your page fails to adapt at different screen widths.
  • Add CSS media queries that enhance the layout for tablet and desktop screens.
  • Test your responsive layout in Chrome DevTools and commit your changes.
Observe the responsive design problem

Your page is currently a one-size-fits-all design. Let's see that problem in action.

  • Switch back to your browser where your page is open.
  • Grab the right edge of your browser window and slowly drag it narrower, all the way down to about 375px wide (roughly the width of a phone screen).
  • Now drag it wider again, past 768px, past 1024px, all the way to full width.

Notice what happens as you resize. The answer is: nothing. The layout stays exactly the same at every width.

What's the problem here?

At desktop width, your topics grid shows a single column with huge empty space on either side. The hero heading stays small. The page wastes all that horizontal room.

A responsive page adapts its layout to match the available space. On phones, single columns work great. On tablets, two columns. On desktops, three columns and larger text. Your page needs to know the difference.

Add media queries for tablet and desktop

CSS media queries let you apply different styles depending on the viewer's screen width. You write your base styles for the smallest screen first, then add enhancements for larger screens.

  • Return to your Claude Code session in the terminal.
  • Add the following tablet media query to the bottom of styles.css, after the footer rule:
@media (min-width: 768px) {
    .hero {
        padding: 6rem 2rem;
    }

    .hero h1 {
        font-size: 3.5rem;
    }

    .tagline {
        font-size: 1.25rem;
    }

    .topics-grid {
        grid-template-columns: repeat(2, 1fr);
    }

    .testimonials-grid {
        grid-template-columns: repeat(2, 1fr);
    }

    .topics,
    .testimonials,
    .contact {
        padding: 4rem 2rem;
    }
}

What does this code do?

  • @media (min-width: 768px) means these styles only apply when the screen is 768px or wider (tablet size and up).
  • The hero gets more breathing room with larger padding and a bigger heading.
  • repeat(2, 1fr) switches the topics and testimonials grids from one column to two columns side by side.
  • Save styles.css and refresh your browser.
  • Drag your browser window to about 768px wide or wider. You should see your topic cards snap into a two-column grid and the hero text grow larger.

Still seeing a single column?

  • Confirm the @media block is placed AFTER the base styles, not inside another rule.
  • Make sure your browser window is actually 768px or wider. Drag it as wide as it goes to be sure.
  • Check that you saved the file. Unsaved changes will not appear in the browser.

Why isn't my media query changing the layout?

Now add the desktop media query directly below the tablet one you just added:

  • Add this second media query block at the very end of styles.css, after the closing } of the 768px block:
@media (min-width: 1024px) {
    .hero h1 {
        font-size: 4rem;
    }

    .topics-grid {
        grid-template-columns: repeat(3, 1fr);
    }

    .topics,
    .testimonials,
    .contact {
        max-width: 1100px;
    }
}

What does this code do?

  • @media (min-width: 1024px) kicks in on laptops and desktops, adding even more space.
  • The topics grid upgrades to three columns so all three cards sit side by side.
  • The hero heading grows to 4rem and sections expand to a 1100px max width to use the extra space.
  • Save styles.css and make your browser window full width.
  • You should see all three topic cards in a single row and the hero heading at its largest size.

Topics still showing two columns at full width?

  • Make sure the 1024px media query is separate from the 768px one. They should be two distinct @media blocks, not nested.
  • Check that you typed repeat(3, 1fr) (three columns) not repeat(2, 1fr) (two columns).

Help me debug my 1024px media query for the topics grid.

✔️ Awesome, I've got everything!

Great. Double check you have saved your file before moving on.

ⓧ I'd like to double check the full code

Your styles.css is over 30 lines, so confirm you have these sections in order by scrolling through the file:

  • The CSS reset (* { margin: 0; ... }).
  • The :root custom properties block.
  • Base body, hero, tagline, cta-button, section, grid, card, testimonial, contact, and footer styles.
  • The @media (min-width: 768px) block with hero padding, font sizes, 2-column grids, and section padding.
  • The @media (min-width: 1024px) block with 4rem hero heading, 3-column topics grid, and 1100px max-width.
Test in DevTools and commit your changes

Dragging the browser edge works, but Chrome DevTools gives you precise device previews that match real phones and tablets.

  • Open Chrome DevTools by pressing Cmd+Option+I (macOS) or Ctrl+Shift+I (Windows).
  • Toggle the device toolbar by pressing Cmd+Shift+M (macOS) or Ctrl+Shift+M (Windows).
  • Select iPhone SE from the device dropdown at the top of the viewport.

Before you look at the result, predict: will you see a multi-column grid or a single-column stack on this phone-sized screen?

You should see a clean single-column layout. Topic cards stack vertically, the hero text fits comfortably, and the CTA button is easy to tap. This is your base mobile design working as intended.

  • Switch the device dropdown to iPad Air and confirm you see a two-column grid.
  • Switch to Responsive and drag the width past 1024px to confirm the three-column topics grid appears.

Why mobile-first?

Your base CSS handles the smallest screens. Media queries then progressively ADD complexity for larger viewports. This approach means the page always works on the most constrained device first, and larger screens get enhancements on top.

  • Commit your responsive design changes by running this in your terminal:
git add . && git commit -m "Add responsive design"

Seeing 'nothing to commit'?

  • This means you have not saved styles.css since your last commit. Save the file and run the commit command again.

Why is Git saying nothing to commit?

Your page now responds to every screen size. Next up, you will put this site live on the internet so anyone can visit it.

Deploy to GitHub Pages

Your page now adapts beautifully from phone to desktop. There is one problem though. It only lives on your computer.

GitHub Pages is a free hosting service built into every GitHub repository. In this step, you'll push your code to GitHub and turn on Pages so anyone in the world can visit your landing page at a real URL.

In this step, get ready to:
  • Push your local code to GitHub.
  • Enable GitHub Pages on your repository.
  • Verify your site is live at a public URL.
Push your code to GitHub

All your commits so far exist only on your machine. Pushing sends them to the remote repository on GitHub, where Pages can serve them as a website.

  • Push your code to GitHub by running this command:
git push -u origin main

What does this command do?

The -u flag sets origin main as the default upstream branch. From now on, you can just run git push without specifying the remote and branch every time.

You should see output confirming the push, including a line like Branch 'main' set up to track remote branch 'main' from 'origin'.

Seeing an authentication error?

If Git asks for credentials or shows a 403 error, you may need to authenticate. macOS often prompts a browser-based sign-in window. Accept the prompt and sign in with your GitHub account.

If you see remote: Repository not found, double-check that the remote URL matches your repository name by running git remote -v.

Why is my git push failing?

Enable GitHub Pages

Your code is on GitHub now. The next step is to tell GitHub to serve it as a website.

  • Open your repository page at github.com/jamal-nextwork/speaking in your browser.
  • Confirm you can see your files (index.html, styles.css, .nojekyll) listed on the repository page.
  • Click the Settings tab near the top of the page.
  • In the left sidebar, find the Code and automation section and click Pages.
  • Under Build and deployment, find the Source dropdown and select Deploy from a branch.
  • In the Branch section that appears, select main from the first dropdown.
  • Leave the folder set to / (root).
  • Click Save.

A confirmation message appears at the top of the page confirming your GitHub Pages source has been saved.

What did you just configure?

You told GitHub to take the files on your main branch, in the root folder, and serve them as a static website. Every time you push new commits to main, GitHub rebuilds and updates your live site automatically.

The .nojekyll file you created earlier tells GitHub to skip its default Jekyll build process and serve your HTML directly. This makes deploys faster and avoids unexpected build issues.

Verify your live site

GitHub needs a minute or two to build and publish your site after you enable Pages. Publication can take up to 10 minutes, but it usually finishes within 1-2 minutes.

  • Wait about 1-2 minutes for the initial deployment to complete.

Before you open the URL, think about what you expect to see. Will it be the unstyled HTML from your early commits, or the fully styled responsive page?

  • Visit your live site by opening this URL in your browser:
open https://jamal-nextwork.github.io/speaking

You see your fully styled, responsive landing page live on the internet. The hero section, topic cards, testimonials, and contact CTA all display with your color scheme and typography.

  • Text the URL to yourself or a friend to confirm it looks great on a real phone.

Why test on a real phone?

DevTools device simulation is useful for development, but nothing replaces testing on an actual phone. Real devices have different rendering engines, touch behaviors, and viewport quirks. If an event organizer opens your link on their phone and it looks broken, that is a missed opportunity.

Seeing a 404 page?

If your URL shows a 404 error, check these things:

  • Make sure you waited at least 2 minutes after saving the Pages configuration. Refresh the page and try again.
  • Confirm your repository has an index.html file in the root (not inside a subfolder). Visit your repository page on GitHub and check.
  • Verify the repository name in your URL matches exactly. It should be jamal-nextwork.github.io/speaking.

My GitHub Pages site shows a 404 error. How do I fix it?

Secret mission

Dark Mode Toggle with Smooth Scroll

Your landing page looks great, but what about visitors who browse at night? Add a dark mode toggle that remembers their preference across visits, plus smooth scroll navigation that makes your single-page site feel polished and professional.

Clean Up Your Resources

Clean Up Your Resources

This project runs entirely locally and deploys to GitHub Pages, which is permanently free. There are no ongoing costs to worry about.

Decide whether to keep your resources running, update them later, or delete them entirely.

Resources you used:

  • GitHub repository: jamal-nextwork/speaking (free, no cost).
  • GitHub Pages site: free hosting at https://jamal-nextwork.github.io/speaking.
  • Local project folder: ~/Desktop/speaking.

Keep everything running

No action needed. Choose this if you want your site to stay live and you plan to keep updating it.

  • GitHub Pages hosting is permanently free with no bandwidth limits for normal use.
  • Your site stays live indefinitely at https://jamal-nextwork.github.io/speaking.
  • Push new commits to main at any time and the site updates automatically within minutes.

Pause - I'll come back to this later

Your GitHub Pages site stays live for free, so there is nothing to pause on the hosting side. You can leave everything as-is until you are ready to return.

  • Your local files in ~/Desktop/speaking remain on your machine and take minimal disk space.
  • When you are ready to resume, open your terminal, navigate to ~/Desktop/speaking, and start editing.

Delete - I don't want to use this again

Remove all project resources from your computer and GitHub. This cannot be undone.

  • Delete your local project folder by running this command in your terminal:
  • Delete the GitHub repository (this also removes your live site):
rm -rf ~/Desktop/speaking

To delete the repository on GitHub:

  • Open your repository at github.com/jamal-nextwork/speaking.
  • Click Settings (under the repository name).
  • Scroll down to the Danger Zone section.
  • Click Delete this repository.
  • Click I want to delete this repository.
  • Click I have read and understand these effects.
  • Type the repository name jamal-nextwork/speaking to confirm.
  • Click Delete this repository.

That's a Wrap!

That's a Wrap!

Nice work. You just built a professional landing page from scratch and deployed it to a live URL that anyone in the world can visit.

You've learned how to:

  • Build a complete HTML page with semantic sections and style it using CSS custom properties, flexbox, and grid layouts.
  • Solve the responsive design problem with mobile-first media queries at 768px and 1024px breakpoints.
  • Deploy a live website to GitHub Pages using Git fundamentals: init, add, commit, remote, and push.
  • Secret Mission: Added JavaScript-powered dark mode with localStorage persistence and smooth scroll navigation.

Ready to quiz yourself?