LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 3024 min read

Real-World Project

Plan and build a complete responsive landing page combining the grid system, navbar, cards, and a contact form.

Introduction

This final lesson pulls together everything from the course into one project: a responsive marketing landing page for a fictional product called "TaskFlow." You will plan the page section by section, then build it with a navbar, hero, feature grid, pricing cards, and a contact form — the same structure used by countless real product sites.

What You Will Build
  • A responsive, collapsible navbar with a call-to-action button.
  • A hero section with a headline, subtext, and buttons.
  • A three-column feature grid using cards.
  • A three-tier pricing section, again using cards.
  • A validated contact form using form controls and grid columns.
  • A simple multi-column footer.

Planning the Page

Before writing markup, sketch the page as a stack of full-width sections, then decide how each section's content breaks into columns at different widths. TaskFlow's landing page will use this structure, top to bottom: navbar, hero, features (3 columns → 1 on mobile), pricing (3 columns → 1 on mobile), contact form (2 columns → 1 on mobile), footer (4 columns → 1 on mobile).

SectionDesktop LayoutMobile Layout
NavbarHorizontal links + CTA buttonCollapsed hamburger menu
HeroCentered text, two buttons side by sideStacked, full-width buttons
Features3 cards per row (col-md-4)1 card per row (col-12)
Pricing3 cards per row (col-lg-4)1 card per row (col-12)
Contact Form2 fields per row (col-md-6)1 field per row (col-12)
Footer4 columns (col-md-3)Stacked columns

Project Setup

Start from a standard Bootstrap HTML skeleton with the CDN CSS in the head and the JS bundle before the closing body tag.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TaskFlow — Organize Your Team's Work</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<!-- sections go here -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

Building the Navbar

A responsive navbar with a collapsible menu on mobile and a highlighted call-to-action button on the right.

<nav class="navbar navbar-expand-lg navbar-dark bg-dark sticky-top">
<div class="container">
<a class="navbar-brand fw-bold" href="#">TaskFlow</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
data-bs-target="#navContent" aria-controls="navContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navContent">
<ul class="navbar-nav ms-auto mb-2 mb-lg-0 align-items-lg-center">
<li class="nav-item"><a class="nav-link" href="#features">Features</a></li>
<li class="nav-item"><a class="nav-link" href="#pricing">Pricing</a></li>
<li class="nav-item"><a class="nav-link" href="#contact">Contact</a></li>
<li class="nav-item ms-lg-3">
<a class="btn btn-primary" href="#contact">Get Started</a>
</li>
</ul>
</div>
</div>
</nav>

Building the Hero Section

A centered hero using utility classes for spacing, typography, and a two-button call-to-action row that stacks on mobile.

<header class="bg-primary bg-gradient text-white text-center py-5">
<div class="container py-5">
<h1 class="display-4 fw-bold">Organize Your Team's Work in One Place</h1>
<p class="lead col-lg-8 mx-auto">
TaskFlow brings tasks, docs, and conversations together so your team
always knows what's next.
</p>
<div class="d-grid gap-2 d-sm-flex justify-content-sm-center mt-4">
<a href="#pricing" class="btn btn-light btn-lg px-4">View Pricing</a>
<a href="#contact" class="btn btn-outline-light btn-lg px-4">Request a Demo</a>
</div>
</div>
</header>

Building the Features Grid

Three feature cards laid out with the grid system, one card per column on mobile and three across from the md breakpoint up.

<section id="features" class="py-5">
<div class="container">
<h2 class="text-center mb-5">Why Teams Choose TaskFlow</h2>
<div class="row g-4">
<div class="col-12 col-md-4">
<div class="card h-100 border-0 shadow-sm">
<div class="card-body text-center">
<i class="bi bi-kanban fs-1 text-primary mb-3"></i>
<h5 class="card-title">Visual Boards</h5>
<p class="card-text">Track work at a glance with drag-and-drop kanban boards.</p>
</div>
</div>
</div>
<div class="col-12 col-md-4">
<div class="card h-100 border-0 shadow-sm">
<div class="card-body text-center">
<i class="bi bi-people fs-1 text-primary mb-3"></i>
<h5 class="card-title">Team Collaboration</h5>
<p class="card-text">Comment, assign, and share files without leaving the task.</p>
</div>
</div>
</div>
<div class="col-12 col-md-4">
<div class="card h-100 border-0 shadow-sm">
<div class="card-body text-center">
<i class="bi bi-graph-up fs-1 text-primary mb-3"></i>
<h5 class="card-title">Progress Reports</h5>
<p class="card-text">Automatic dashboards show exactly where every project stands.</p>
</div>
</div>
</div>
</div>
</div>
</section>

Building the Pricing Cards

Three pricing tiers, with the middle "recommended" plan visually emphasized using a border and badge — a common real-world pattern combining cards, badges, and list groups.

<section id="pricing" class="py-5 bg-body-tertiary">
<div class="container">
<h2 class="text-center mb-5">Simple, Transparent Pricing</h2>
<div class="row g-4 justify-content-center">
<div class="col-12 col-lg-4">
<div class="card h-100">
<div class="card-body text-center">
<h5 class="card-title">Starter</h5>
<p class="display-6">$9<small class="fs-6 text-body-secondary">/mo</small></p>
<ul class="list-group list-group-flush text-start mb-3">
<li class="list-group-item">Up to 5 team members</li>
<li class="list-group-item">3 active projects</li>
</ul>
<a href="#contact" class="btn btn-outline-primary w-100">Choose Starter</a>
</div>
</div>
</div>
<div class="col-12 col-lg-4">
<div class="card h-100 border-primary border-2 shadow">
<div class="card-body text-center">
<span class="badge text-bg-primary mb-2">Most Popular</span>
<h5 class="card-title">Team</h5>
<p class="display-6">$29<small class="fs-6 text-body-secondary">/mo</small></p>
<ul class="list-group list-group-flush text-start mb-3">
<li class="list-group-item">Up to 25 team members</li>
<li class="list-group-item">Unlimited projects</li>
</ul>
<a href="#contact" class="btn btn-primary w-100">Choose Team</a>
</div>
</div>
</div>
<div class="col-12 col-lg-4">
<div class="card h-100">
<div class="card-body text-center">
<h5 class="card-title">Enterprise</h5>
<p class="display-6">Custom</p>
<ul class="list-group list-group-flush text-start mb-3">
<li class="list-group-item">Unlimited members</li>
<li class="list-group-item">Dedicated support</li>
</ul>
<a href="#contact" class="btn btn-outline-primary w-100">Contact Sales</a>
</div>
</div>
</div>
</div>
</div>
</section>

Building the Contact Form

A contact form using paired grid columns for name/email, full-width fields for the message, and Bootstrap's validation classes.

<section id="contact" class="py-5">
<div class="container">
<h2 class="text-center mb-5">Request a Demo</h2>
<form class="row g-3 col-lg-8 mx-auto needs-validation" novalidate>
<div class="col-12 col-md-6">
<label for="fullName" class="form-label">Full Name</label>
<input type="text" class="form-control" id="fullName" required>
<div class="invalid-feedback">Please enter your name.</div>
</div>
<div class="col-12 col-md-6">
<label for="workEmail" class="form-label">Work Email</label>
<input type="email" class="form-control" id="workEmail" required>
<div class="invalid-feedback">Please enter a valid email.</div>
</div>
<div class="col-12">
<label for="message" class="form-label">What are you hoping to solve?</label>
<textarea class="form-control" id="message" rows="4" required></textarea>
<div class="invalid-feedback">Please add a short message.</div>
</div>
<div class="col-12 text-center">
<button class="btn btn-primary btn-lg px-5" type="submit">Request Demo</button>
</div>
</form>
</div>
</section>
// Bootstrap's standard client-side validation trigger
(() => {
document.querySelectorAll('.needs-validation').forEach(form => {
form.addEventListener('submit', event => {
if (!form.checkValidity()) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false);
});
})();

A dark, four-column footer that stacks to a single column on mobile, wrapping up the page.

<footer class="bg-dark text-white py-5">
<div class="container">
<div class="row g-4">
<div class="col-12 col-md-3">
<h5>TaskFlow</h5>
<p class="text-body-secondary">Work management for growing teams.</p>
</div>
<div class="col-6 col-md-3">
<h6>Product</h6>
<ul class="list-unstyled">
<li><a class="link-light link-underline-opacity-0" href="#features">Features</a></li>
<li><a class="link-light link-underline-opacity-0" href="#pricing">Pricing</a></li>
</ul>
</div>
<div class="col-6 col-md-3">
<h6>Company</h6>
<ul class="list-unstyled">
<li><a class="link-light link-underline-opacity-0" href="#">About</a></li>
<li><a class="link-light link-underline-opacity-0" href="#">Careers</a></li>
</ul>
</div>
<div class="col-12 col-md-3">
<h6>Stay Updated</h6>
<form class="d-flex" role="search">
<input class="form-control me-2" type="email" placeholder="Email address" aria-label="Email address">
<button class="btn btn-outline-light" type="submit">Join</button>
</form>
</div>
</div>
<hr class="my-4">
<p class="text-center text-body-secondary mb-0">© 2026 TaskFlow. All rights reserved.</p>
</div>
</footer>

Testing Responsiveness

Before calling the page done, walk through it at each breakpoint using your browser's device toolbar: confirm the navbar collapses correctly below lg, the feature and pricing cards stack to one column below md/lg, the contact form fields stack below md, and the footer columns stack below md. Also confirm the sticky-top navbar does not overlap the hero heading on short mobile viewports.

Common Mistakes

Avoid These Mistakes
  • Building the whole page at desktop width first and only checking mobile at the very end, when fixes are more expensive.
  • Forgetting novalidate plus the was-validated JS trigger, so the browser's default validation bubbles fight Bootstrap's styled feedback.
  • Nesting a full <div class="container"> inside a section that is already inside another container, doubling up padding.
  • Leaving placeholder link href="#" on primary navigation without real destinations before shipping.
  • Missing aria-label on icon-only or icon-first controls, like the newsletter form's email input.

Best Practices

  • Plan each section's column breakdown before writing markup, as done in the planning table above.
  • Reuse the same card pattern (h-100, shadow-sm, card-body) across features and pricing for visual consistency.
  • Keep one <container> per section rather than nesting containers.
  • Use semantic landmarks — <header>, <nav>, <section id="...">, <footer> — so the page has a real document outline.
  • Test keyboard navigation end to end: tab through the navbar, form fields, and buttons to confirm focus order and visibility.

Frequently Asked Questions

Yes — use one .container (or .container-fluid for edge-to-edge sections) per <section>, directly inside it, rather than nesting multiple containers, which would compound padding unexpectedly.

You can add a slight scale transform via a small custom CSS rule, or increase the shadow/border utilities, as done above with border-primary border-2 shadow — both are legitimate uses of custom CSS since Bootstrap has no built-in "featured card" utility.

No — this entire landing page is built with plain HTML, Bootstrap's CSS classes, and the small validation script shown above; a framework like React only becomes useful once the page needs real interactivity beyond forms and toggles.

Key Takeaways

  • A real landing page is just a stack of sections, each using the grid system to break its content into responsive columns.
  • The navbar, cards, list groups, badges, forms, and icons from earlier lessons combine naturally in a single page.
  • Client-side form validation needs both the novalidate attribute and the was-validated JavaScript trigger.
  • Always verify the finished page across every breakpoint, not just the width you built it at.

Bootstrap Course Completed!

You have successfully completed all 30 lessons — from the grid system and core components through Sass customization and JavaScript components. You now have a genuinely practical Bootstrap skill set for building responsive interfaces quickly.

Browse All Courses →