🚀 The Grand Finale

Congratulations — you've made it to the capstone! Over the past 11 modules, you've built a complete toolkit: semantic HTML, CSS styling & layout, Flexbox & Grid, responsive design, animations, accessibility, and SEO. Now it's time to put it ALL together in one real project.

In this module, you'll build a multi-page responsive portfolio website from scratch — no templates, no frameworks, just pure HTML & CSS — and deploy it live on the internet using GitHub Pages. By the end, you'll have a real URL you can share with anyone.

🎯
What You'll Build: A 4-page portfolio with Home, About, Projects, and Contact pages. Fully responsive, accessible, SEO-optimized, with smooth animations — deployed live on GitHub Pages.
Prerequisites: This module assumes you've completed Modules 0–11. Every concept from the course will be applied here. If you're unsure about something, refer back to the relevant module.

Skills You'll Apply

Module Skill Applied
0–1HTML fundamentals, page structure, semantic tags
2–3Advanced HTML, forms, tables
4Images, multimedia, embedding
5–6CSS styling, box model, typography
7–8Flexbox & Grid layouts
9Responsive design & media queries
10Transitions, animations, transforms
11Accessibility (ARIA, keyboard nav) & SEO

📋 Project Planning

Every professional project starts with a plan. Before writing a single line of code, let's define what we're building and how it will be structured.

Page Structure

Our portfolio will have 4 pages, each with a shared header/footer and its own unique content:

🏠
Home (index.html)

Hero section with your name & tagline, featured projects grid, call-to-action.

👤
About (about.html)

Bio, skills list, education/experience timeline.

💼
Projects (projects.html)

Project cards grid with images, descriptions, and links.

✉️
Contact (contact.html)

Contact form (styled, accessible), social links, location info.

File Structure

Organize your project with a clean, standard folder structure:

File Tree
my-portfolio/
├── index.html          # Home page
├── about.html          # About page
├── projects.html       # Projects page
├── contact.html        # Contact page
├── css/
│   ├── style.css       # Main stylesheet
│   └── responsive.css  # Media queries
├── images/
│   ├── profile.jpg     # Your photo
│   ├── project-1.jpg   # Project screenshots
│   ├── project-2.jpg
│   └── favicon.ico     # Browser tab icon
└── README.md           # Project description

Wireframe Your Pages

Before coding, sketch a rough layout for each page. You don't need fancy tools — pen and paper works perfectly. Focus on:

📐
Layout Structure

Where does the header, main content, and footer go? How many columns?

📱
Responsive Breakpoints

How will the layout change on mobile vs. tablet vs. desktop?

🎨
Color Palette

Pick 2–3 primary colors and a neutral. Use CSS custom properties for consistency.

💡
Pro Tip: Start mobile-first! Sketch the mobile layout first, then figure out how it expands for larger screens. This is exactly the approach we learned in Module 9.

⚙️ Setting Up the Project

Let's create the project folder and set up the initial files. Open your terminal (or VS Code's built-in terminal) and run:

Terminal
# Create project folder and navigate into it
mkdir my-portfolio
cd my-portfolio

# Create subfolders
mkdir css images

# Create initial files
touch index.html about.html projects.html contact.html
touch css/style.css css/responsive.css
touch README.md

HTML Boilerplate

Start each HTML file with this boilerplate. Customize the <title> and <meta> tags for each page:

HTML
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Your Name — Portfolio</title>
    <meta name="description" content="Portfolio of [Your Name] — web developer">
    <link rel="icon" href="images/favicon.ico">
    <link rel="stylesheet" href="css/style.css">
    <link rel="stylesheet" href="css/responsive.css">
</head>
<body>

    <!-- Shared header (same on all pages) -->
    <header class="site-header">
        <!-- Navigation goes here -->
    </header>

    <!-- Page-specific content -->
    <main>
        <!-- Unique content per page -->
    </main>

    <!-- Shared footer (same on all pages) -->
    <footer class="site-footer">
        <!-- Footer content -->
    </footer>

</body>
</html>

CSS Custom Properties

Set up a design system with CSS variables at the top of your style.css. This makes your entire site easy to re-theme:

CSS
/* ===== Design Tokens ===== */
:root {
    /* Colors */
    --color-primary: #2563eb;
    --color-primary-dark: #1d4ed8;
    --color-accent: #f59e0b;
    --color-text: #1f2937;
    --color-text-light: #6b7280;
    --color-bg: #ffffff;
    --color-bg-alt: #f9fafb;
    --color-border: #e5e7eb;

    /* Typography */
    --font-heading: 'Playfair Display', serif;
    --font-body: 'Inter', sans-serif;
    --font-mono: 'JetBrains Mono', monospace;

    /* Spacing */
    --space-xs: 0.25rem;
    --space-sm: 0.5rem;
    --space-md: 1rem;
    --space-lg: 2rem;
    --space-xl: 4rem;

    /* Transitions */
    --transition-fast: 150ms ease;
    --transition-base: 300ms ease;

    /* Shadows */
    --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
    --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
    --shadow-lg: 0 10px 25px rgba(0, 0, 0, 0.15);

    /* Border Radius */
    --radius-sm: 4px;
    --radius-md: 8px;
    --radius-lg: 16px;
    --radius-full: 9999px;
}

/* ===== Reset ===== */
*,
*::before,
*::after {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: var(--font-body);
    color: var(--color-text);
    background: var(--color-bg);
    line-height: 1.6;
}

🏗️ Building the HTML Structure

Let's build the HTML for each page. Remember: semantic HTML first, styling later. Use proper elements like <header>, <nav>, <main>, <section>, <article>, and <footer>.

Shared Navigation

The navigation will be identical on all 4 pages. Include a logo/name, nav links, and a mobile hamburger button:

HTML
<header class="site-header">
    <nav class="navbar" aria-label="Main navigation">
        <a href="index.html" class="logo">Your Name</a>

        <ul class="nav-links">
            <li><a href="index.html" class="nav-link active">Home</a></li>
            <li><a href="about.html" class="nav-link">About</a></li>
            <li><a href="projects.html" class="nav-link">Projects</a></li>
            <li><a href="contact.html" class="nav-link">Contact</a></li>
        </ul>

        <button class="menu-toggle" aria-label="Toggle menu" aria-expanded="false">
            <span class="hamburger"></span>
        </button>
    </nav>
</header>

Home Page — Hero Section

The hero is the first thing visitors see. Make it bold and clear:

HTML
<section class="hero">
    <div class="hero-content">
        <h1 class="hero-title">
            Hi, I'm <span class="highlight">Your Name</span>
        </h1>
        <p class="hero-subtitle">Web Developer & Designer</p>
        <div class="hero-cta">
            <a href="projects.html" class="btn btn-primary">View My Work</a>
            <a href="contact.html" class="btn btn-outline">Get in Touch</a>
        </div>
    </div>
</section>

Projects Page — Card Grid

Each project gets a card with an image, title, description, tech tags, and a link. This is where you use <article> semantics:

HTML
<section class="projects-grid">
    <h2>My Projects</h2>

    <div class="grid">
        <article class="project-card">
            <img src="images/project-1.jpg"
                 alt="Screenshot of weather app"
                 class="project-image"
                 loading="lazy">
            <div class="project-info">
                <h3>Weather App</h3>
                <p>A responsive weather dashboard with location search.</p>
                <div class="project-tags">
                    <span class="tag">HTML</span>
                    <span class="tag">CSS</span>
                    <span class="tag">Responsive</span>
                </div>
                <a href="#" class="btn btn-small">View Project →</a>
            </div>
        </article>

        <!-- Repeat for more projects -->
    </div>
</section>

Contact Page — Accessible Form

Apply everything from Module 3 (forms) and Module 11 (accessibility). Every input needs a <label>, and the form needs proper aria attributes:

HTML
<section class="contact-section">
    <h2>Get in Touch</h2>

    <form class="contact-form" action="#" method="POST">
        <div class="form-group">
            <label for="name">Name</label>
            <input type="text" id="name" name="name"
                   required autocomplete="name">
        </div>

        <div class="form-group">
            <label for="email">Email</label>
            <input type="email" id="email" name="email"
                   required autocomplete="email">
        </div>

        <div class="form-group">
            <label for="message">Message</label>
            <textarea id="message" name="message"
                      rows="5" required></textarea>
        </div>

        <button type="submit" class="btn btn-primary">
            Send Message
        </button>
    </form>
</section>

Shared Footer

HTML
<footer class="site-footer">
    <div class="footer-content">
        <p>&copy; 2026 Your Name. All rights reserved.</p>
        <div class="social-links">
            <a href="#" aria-label="GitHub">GitHub</a>
            <a href="#" aria-label="LinkedIn">LinkedIn</a>
            <a href="mailto:you@email.com" aria-label="Email">Email</a>
        </div>
    </div>
</footer>

🎨 Base Styles & Typography

With the HTML structure in place, let's add the base styles. We already defined custom properties — now let's build the component styles on top of them.

Navigation Styles

CSS
/* ===== Navigation ===== */
.site-header {
    position: sticky;
    top: 0;
    z-index: 100;
    background: var(--color-bg);
    border-bottom: 1px solid var(--color-border);
}

.navbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    max-width: 1200px;
    margin: 0 auto;
    padding: var(--space-md) var(--space-lg);
}

.logo {
    font-family: var(--font-heading);
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--color-primary);
    text-decoration: none;
}

.nav-links {
    display: flex;
    gap: var(--space-lg);
    list-style: none;
}

.nav-link {
    text-decoration: none;
    color: var(--color-text-light);
    font-weight: 500;
    transition: color var(--transition-fast);
}

.nav-link:hover,
.nav-link.active {
    color: var(--color-primary);
}

Hero Section

CSS
/* ===== Hero ===== */
.hero {
    min-height: 80vh;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: var(--space-xl);
}

.hero-title {
    font-family: var(--font-heading);
    font-size: clamp(2rem, 5vw, 4rem);
    margin-bottom: var(--space-md);
}

.hero-title .highlight {
    color: var(--color-primary);
}

.hero-subtitle {
    font-size: clamp(1rem, 2.5vw, 1.5rem);
    color: var(--color-text-light);
    margin-bottom: var(--space-lg);
}

/* ===== Buttons ===== */
.btn {
    display: inline-block;
    padding: var(--space-sm) var(--space-lg);
    border-radius: var(--radius-md);
    font-weight: 600;
    text-decoration: none;
    transition: all var(--transition-base);
    cursor: pointer;
    border: 2px solid transparent;
}

.btn-primary {
    background: var(--color-primary);
    color: white;
}

.btn-primary:hover {
    background: var(--color-primary-dark);
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
}

.btn-outline {
    border-color: var(--color-primary);
    color: var(--color-primary);
}

.btn-outline:hover {
    background: var(--color-primary);
    color: white;
}

Project Cards

CSS
/* ===== Project Cards ===== */
.project-card {
    background: var(--color-bg);
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow: var(--shadow-sm);
    transition: transform var(--transition-base), box-shadow var(--transition-base);
}

.project-card:hover {
    transform: translateY(-4px);
    box-shadow: var(--shadow-lg);
}

.project-image {
    width: 100%;
    height: 200px;
    object-fit: cover;
}

.project-info {
    padding: var(--space-lg);
}

.project-tags {
    display: flex;
    gap: var(--space-xs);
    flex-wrap: wrap;
    margin: var(--space-sm) 0;
}

.tag {
    background: var(--color-bg-alt);
    padding: var(--space-xs) var(--space-sm);
    border-radius: var(--radius-full);
    font-size: 0.8rem;
    color: var(--color-text-light);
}

📱 Responsive Layout

Now let's make everything responsive using CSS Grid and Flexbox. Remember: mobile-first — start with the single-column layout and add complexity at larger breakpoints.

Projects Grid with CSS Grid

CSS
/* Mobile-first: single column */
.grid {
    display: grid;
    gap: var(--space-lg);
    grid-template-columns: 1fr;
}

/* Tablet: 2 columns */
@media (min-width: 768px) {
    .grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

/* Desktop: 3 columns */
@media (min-width: 1024px) {
    .grid {
        grid-template-columns: repeat(3, 1fr);
    }
}

Mobile Navigation

On mobile, the nav links collapse into a hamburger menu. This is a CSS-only approach using a checkbox hack (no JavaScript needed!):

CSS
/* === responsive.css === */

/* Hide hamburger on desktop */
.menu-toggle {
    display: none;
}

@media (max-width: 768px) {
    /* Show hamburger */
    .menu-toggle {
        display: block;
        background: none;
        border: none;
        cursor: pointer;
        padding: var(--space-sm);
    }

    .hamburger,
    .hamburger::before,
    .hamburger::after {
        display: block;
        width: 24px;
        height: 2px;
        background: var(--color-text);
        transition: transform var(--transition-base);
        position: relative;
    }

    .hamburger::before,
    .hamburger::after {
        content: '';
        position: absolute;
    }

    .hamburger::before { top: -7px; }
    .hamburger::after { top: 7px; }

    /* Mobile nav layout */
    .nav-links {
        position: fixed;
        top: 60px;
        right: 0;
        width: 100%;
        background: var(--color-bg);
        flex-direction: column;
        padding: var(--space-lg);
        box-shadow: var(--shadow-lg);
        transform: translateY(-100%);
        opacity: 0;
        transition: transform var(--transition-base), opacity var(--transition-base);
    }

    .nav-links.open {
        transform: translateY(0);
        opacity: 1;
    }
}
💡
Testing Tip: Use Chrome DevTools device toolbar (Ctrl/Cmd + Shift + M) to test your responsive design at different screen sizes. Test on at least mobile (375px), tablet (768px), and desktop (1024px+).

🧩 Reusable Components

A well-structured site uses reusable components — patterns that appear across multiple pages. Here are the key components for your portfolio:

Form Styles

Style your contact form inputs to be clean, accessible, and consistent:

CSS
/* ===== Forms ===== */
.form-group {
    margin-bottom: var(--space-lg);
}

.form-group label {
    display: block;
    margin-bottom: var(--space-xs);
    font-weight: 600;
    color: var(--color-text);
}

.form-group input,
.form-group textarea {
    width: 100%;
    padding: var(--space-sm) var(--space-md);
    border: 2px solid var(--color-border);
    border-radius: var(--radius-md);
    font-family: var(--font-body);
    font-size: 1rem;
    transition: border-color var(--transition-fast);
}

.form-group input:focus,
.form-group textarea:focus {
    outline: none;
    border-color: var(--color-primary);
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
}

Footer Styles

CSS
/* ===== Footer ===== */
.site-footer {
    background: var(--color-text);
    color: var(--color-bg);
    padding: var(--space-xl) var(--space-lg);
    text-align: center;
}

.footer-content {
    max-width: 1200px;
    margin: 0 auto;
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space-md);
}

.social-links {
    display: flex;
    gap: var(--space-lg);
}

.social-links a {
    color: var(--color-bg);
    text-decoration: none;
    opacity: 0.8;
    transition: opacity var(--transition-fast);
}

.social-links a:hover {
    opacity: 1;
}

About Page — Skills & Timeline

Use Flexbox for the skills list and a pseudo-element timeline for experience/education:

CSS
/* ===== Skills Grid ===== */
.skills-list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space-sm);
    list-style: none;
}

.skills-list li {
    background: var(--color-primary);
    color: white;
    padding: var(--space-xs) var(--space-md);
    border-radius: var(--radius-full);
    font-size: 0.9rem;
}

/* ===== Timeline ===== */
.timeline {
    position: relative;
    padding-left: var(--space-xl);
}

.timeline::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 2px;
    background: var(--color-border);
}

.timeline-item {
    position: relative;
    margin-bottom: var(--space-lg);
}

.timeline-item::before {
    content: '';
    position: absolute;
    left: calc(-1 * var(--space-xl) - 5px);
    top: 4px;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: var(--color-primary);
}

✨ Animations & Polish

Time to add the finishing touches from Module 10. Subtle animations make your portfolio feel professional and polished.

Card Hover Effects

We already added basic hover to project cards. Let's enhance with image zoom and overlay:

CSS
/* Image zoom on hover */
.project-card .project-image {
    transition: transform var(--transition-base);
}

.project-card:hover .project-image {
    transform: scale(1.05);
}

/* Button lift effect */
.btn:active {
    transform: translateY(0);
}

Scroll Reveal Animation

Add a fade-in-up effect for elements as they enter the viewport. Define the animation in CSS:

CSS
/* Scroll reveal animation */
@keyframes fadeInUp {
    from {
        opacity: 0;
        transform: translateY(30px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.reveal {
    opacity: 0;
    transform: translateY(30px);
}

.reveal.visible {
    animation: fadeInUp 0.6s ease forwards;
}

/* Respect reduced motion preference */
@media (prefers-reduced-motion: reduce) {
    .reveal {
        opacity: 1;
        transform: none;
        animation: none;
    }
}
⚠️
Always Respect User Preferences: Use the prefers-reduced-motion media query to disable animations for users who have motion sensitivity. This is essential for accessibility (Module 11).

♿ Accessibility Audit

Before deploying, run through this accessibility checklist. Every item comes from what you learned in Module 11:

Check What to Verify Module
All images have descriptive alt text 4, 11
Semantic HTML: <header>, <nav>, <main>, <footer> 2, 11
Heading hierarchy: one <h1> per page, logical order 2, 11
All form inputs have associated <label> elements 3, 11
Color contrast ratio meets WCAG AA (4.5:1 text, 3:1 large) 11
Full keyboard navigation: Tab, Enter, Escape all work 11
:focus-visible styles on all interactive elements 11
aria-label on icon-only buttons (hamburger, social links) 11
prefers-reduced-motion disables animations 10, 11
Skip navigation link as first focusable element 11

Add a Skip Link

Add this as the very first element inside <body> on every page:

HTML
<a href="#main-content" class="skip-link">Skip to main content</a>
CSS
.skip-link {
    position: absolute;
    top: -100%;
    left: 50%;
    transform: translateX(-50%);
    background: var(--color-primary);
    color: white;
    padding: var(--space-sm) var(--space-md);
    border-radius: var(--radius-md);
    z-index: 1000;
    transition: top var(--transition-fast);
}

.skip-link:focus {
    top: var(--space-md);
}
💡
Run Lighthouse: Open Chrome DevTools → Lighthouse tab → check "Accessibility". Aim for a score of 90+ before deploying.

🔍 SEO & Meta Tags

Apply everything from Module 11's SEO section to make your portfolio discoverable by search engines and social media.

Essential Meta Tags

Add these to every page's <head>:

HTML
<head>
    <!-- Basic Meta -->
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Your Name — Portfolio | Web Developer</title>
    <meta name="description" content="Portfolio of [Name], a web developer specializing in...">

    <!-- Open Graph (Facebook, LinkedIn) -->
    <meta property="og:title" content="Your Name — Portfolio">
    <meta property="og:description" content="Web developer portfolio showcasing...">
    <meta property="og:image" content="https://yourdomain.com/images/og-image.jpg">
    <meta property="og:url" content="https://yourdomain.com/">
    <meta property="og:type" content="website">

    <!-- Twitter Card -->
    <meta name="twitter:card" content="summary_large_image">
    <meta name="twitter:title" content="Your Name — Portfolio">
    <meta name="twitter:image" content="https://yourdomain.com/images/og-image.jpg">

    <!-- Favicon -->
    <link rel="icon" type="image/x-icon" href="images/favicon.ico">
</head>

JSON-LD Structured Data

Add structured data so search engines understand your portfolio is a personal website. Place this in the <head> of your home page:

JSON-LD
<script type="application/ld+json">
{
    "@context": "https://schema.org",
    "@type": "Person",
    "name": "Your Name",
    "url": "https://yourdomain.com",
    "jobTitle": "Web Developer",
    "sameAs": [
        "https://github.com/yourusername",
        "https://linkedin.com/in/yourusername"
    ]
}
</script>

SEO Checklist

Item Done?
Unique <title> on every page (50–60 characters)
Unique <meta description> per page (150–160 chars)
Open Graph tags for social sharing
All images have alt text
Proper heading hierarchy (h1 → h2 → h3)
JSON-LD structured data on home page
All links are descriptive (not "click here")

🌐 Deploy to GitHub Pages

The moment of truth! Let's put your portfolio live on the internet using GitHub Pages — a free hosting service for static websites.

Step 1: Initialize Git

If you haven't already, initialize a Git repository in your project folder:

Terminal
# Navigate to your project
cd my-portfolio

# Initialize git
git init

# Add all files
git add .

# Create first commit
git commit -m "Initial commit — portfolio website"

Step 2: Create a GitHub Repository

1️⃣
Go to GitHub

Sign in to github.com and click the + button → New repository.

2️⃣
Name Your Repo

Name it yourusername.github.io for a personal site, or any name for a project site. Keep it public.

3️⃣
Push Your Code

Follow the instructions GitHub shows to push your existing repository.

Terminal
# Add GitHub as remote origin
git remote add origin https://github.com/yourusername/yourusername.github.io.git

# Push to GitHub
git branch -M main
git push -u origin main

Step 3: Enable GitHub Pages

⚙️
Repository Settings

Go to your repo → SettingsPages (in left sidebar).

🌿
Select Branch

Under "Source", select main branch and / (root) folder. Click Save.

🎉
Your Site is Live!

After a few minutes, your site will be live at https://yourusername.github.io. Share it with the world!

💡
Custom Domain: You can also connect a custom domain (like yourname.com) in the GitHub Pages settings. GitHub provides free HTTPS for custom domains too!

Making Updates

Every time you want to update your live site, just commit and push:

Terminal
# After making changes:
git add .
git commit -m "Update projects section"
git push

🎓 Summary & Next Steps

Congratulations! You've completed the entire Web Foundations course. You've gone from understanding how the web works to building and deploying a complete, professional website. Here's everything you've accomplished:

🏗️
Semantic HTML

You built a multi-page site with proper structure: headers, navs, sections, articles, forms, and footers.

🎨
CSS Design System

You created a complete design system with custom properties, typography, colors, and reusable components.

📐
Modern Layout

You used Flexbox and CSS Grid to create responsive, flexible layouts that work on any screen size.

Animations & Polish

You added smooth transitions, hover effects, and scroll animations while respecting user preferences.

Accessibility

You built for everyone: keyboard navigation, screen reader support, skip links, and ARIA attributes.

🔍
SEO & Deployment

You optimized for search engines with meta tags, Open Graph, JSON-LD, and deployed to a live URL.

What's Next?

Now that you have solid HTML & CSS foundations, here are the natural next steps in your web development journey:

Learn JavaScript

Add interactivity: dynamic content, form validation, API calls, and single-page apps.

🛠️
Explore Build Tools

Learn Sass/SCSS for advanced CSS, and build tools like Vite for development workflows.

🎯
Keep Building!

The best way to solidify skills is through practice. Rebuild your portfolio, contribute to open source, or take on freelance projects.

🎉
You Did It! You're no longer just a beginner — you're a web developer with a live portfolio to prove it. Every professional developer started exactly where you are now. Keep building, keep learning, and most importantly — have fun!
🎓 Course Complete!

Web Foundations: HTML & CSS Mastery

You've completed all 13 modules. Share your portfolio with the world!

🏆