Sakshi

I've built portfolio sites for clients, for developers I've mentored, and for myself multiple times as my work evolved. The pattern that works consistently is simpler than most tutorials make it — six sections, Bootstrap 5.3, one SCSS variables file, and a contact form that actually sends. Here's the complete guide.

Project Setup

# Create project structure
mkdir portfolio && cd portfolio
mkdir -p assets/{css,scss,js,images,fonts}
touch index.html assets/scss/style.scss

Enter fullscreen mode Exit fullscreen mode

Install Bootstrap 5.3 via npm or CDN. For a portfolio — CDN is fine unless you want SCSS variable customization. If you want to customize colors and fonts — npm and SCSS.

npm install [email protected]

Enter fullscreen mode Exit fullscreen mode

// assets/scss/style.scss — correct import order

// 1. Google Fonts
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');

// 2. Your Bootstrap variable overrides — BEFORE Bootstrap import
$primary: #fd4766;
$font-family-base: 'Inter', sans-serif;
$border-radius: 8px;
$border-radius-lg: 12px;
$box-shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.06);
$box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);

// 3. Bootstrap
@import 'bootstrap/scss/bootstrap';

// 4. Your custom styles after Bootstrap
// Custom styles below

Enter fullscreen mode Exit fullscreen mode

HTML Structure — Six Sections

html
<!DOCTYPE html>
<html lang="en" data-bs-theme="light">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="description" content="Your name — Frontend Developer specializing in Angular, Bootstrap, and React">
  <title>Your Name — Frontend Developer</title>
  <link rel="stylesheet" href="assets/css/style.css">
</head>
<body>

  <!-- 1. Navigation -->
  <nav class="navbar navbar-expand-lg sticky-top bg-white border-bottom">...</nav>

  <!-- 2. Hero -->
  <section id="hero" class="hero-section py-100">...</section>

  <!-- 3. Projects -->
  <section id="projects" class="projects-section py-80 bg-light">...</section>

  <!-- 4. Skills -->
  <section id="skills" class="skills-section py-80">...</section>

  <!-- 5. About -->
  <section id="about" class="about-section py-80 bg-light">...</section>

  <!-- 6. Contact -->
  <section id="contact" class="contact-section py-80">...</section>

  <!-- Footer -->
  <footer class="footer py-4 bg-dark text-white">...</footer>

  <script src="assets/js/bootstrap.bundle.min.js"></script>
  <script src="assets/js/main.js"></script>
</body>
</html>

Enter fullscreen mode Exit fullscreen mode

Six sections. That's all a portfolio needs. Resist the urge to add more.

Section 1 — Navigation

<nav class="navbar navbar-expand-lg sticky-top bg-white border-bottom shadow-sm">
  <div class="container">
    <a class="navbar-brand fw-bold text-primary" href="#">
      YourName
    </a>
    <button class="navbar-toggler border-0" type="button"
            data-bs-toggle="collapse" data-bs-target="#navMenu">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navMenu">
      <ul class="navbar-nav ms-auto gap-1">
        <li class="nav-item">
          <a class="nav-link px-3" href="#projects">Projects</a>
        </li>
        <li class="nav-item">
          <a class="nav-link px-3" href="#skills">Skills</a>
        </li>
        <li class="nav-item">
          <a class="nav-link px-3" href="#about">About</a>
        </li>
        <li class="nav-item">
          <a class="btn btn-primary px-4 ms-2" href="#contact">
            Hire Me
          </a>
        </li>
      </ul>
    </div>
  </div>
</nav>

Enter fullscreen mode Exit fullscreen mode

sticky-top keeps the navbar visible while scrolling. border-bottom shadow-sm gives it subtle depth. The "Hire Me" button as a CTA in the navbar gets clicks — more than a plain nav link.

Section 2 — Hero

<section id="hero" class="hero-section py-100">
  <div class="container">
    <div class="row align-items-center g-5">
      <div class="col-lg-6 order-2 order-lg-1">
        <div class="hero-badge d-inline-flex align-items-center
                    gap-2 bg-primary-subtle text-primary
                    rounded-pill px-3 py-2 mb-4 small fw-semibold">
          <span class="dot bg-primary rounded-circle"
                style="width:8px;height:8px;"></span>
          Available for new projects
        </div>
        <h1 class="display-5 fw-bold lh-sm mb-3">
          Frontend Developer<br>
          <span class="text-primary">Building Angular</span><br>
          & Bootstrap Apps
        </h1>
        <p class="lead text-muted mb-4">
          I build production-ready admin dashboards, SaaS applications,
          and landing pages with Angular 22, Bootstrap 5.3, and React 19.
          12+ years of experience shipping clean code.
        </p>
        <div class="d-flex flex-wrap gap-3">
          <a href="#projects" class="btn btn-primary btn-lg px-4">
            View My Work
          </a>
          <a href="#contact" class="btn btn-outline-secondary btn-lg px-4">
            Get In Touch
          </a>
        </div>
        <div class="hero-stats d-flex gap-4 mt-5">
          <div>
            <div class="h4 fw-bold mb-0">12+</div>
            <div class="text-muted small">Years Experience</div>
          </div>
          <div>
            <div class="h4 fw-bold mb-0">50+</div>
            <div class="text-muted small">Projects Shipped</div>
          </div>
          <div>
            <div class="h4 fw-bold mb-0">20+</div>
            <div class="text-muted small">Happy Clients</div>
          </div>
        </div>
      </div>
      <div class="col-lg-6 order-1 order-lg-2 text-center">
        <div class="hero-image-wrapper position-relative d-inline-block">
          <img src="assets/images/your-photo.jpg"
               alt="Your Name — Frontend Developer"
               class="img-fluid rounded-4 shadow-lg"
               style="max-width: 420px;">
          <div class="hero-badge-card card border-0 shadow position-absolute
                      bottom-0 start-0 translate-middle-y ms-n3 p-3">
            <div class="d-flex align-items-center gap-2">
              <div class="badge-icon bg-success rounded-2 p-2">
                <i class="bx bx-check text-white fs-5"></i>
              </div>
              <div>
                <div class="fw-semibold small">Available Now</div>
                <div class="text-muted" style="font-size:11px;">
                  Open to opportunities
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>

Enter fullscreen mode Exit fullscreen mode

Photo on right on desktop, above content on mobile via order-2 order-lg-1. Stats below the CTA buttons. Availability badge card floating on the photo — a small detail that makes it feel designed rather than assembled.

Section 3 — Projects

<section id="projects" class="projects-section py-80 bg-light">
  <div class="container">
    <div class="row mb-50">
      <div class="col-lg-6">
        <h2 class="h1 fw-bold mb-3">Selected Work</h2>
        <p class="text-muted lead">
          Projects I've built — what the problem was,
          what I did, what shipped.
        </p>
      </div>
    </div>
    <div class="row g-4">

      <!-- Project Card -->
      <div class="col-lg-6">
        <div class="project-card card border-0 shadow-sm h-100
                    overflow-hidden hover-lift">
          <div class="project-image position-relative overflow-hidden">
            <img src="assets/images/project-1.jpg"
                 alt="Project Name"
                 class="img-fluid w-100"
                 style="height: 240px; object-fit: cover;">
            <div class="project-overlay position-absolute inset-0
                        bg-dark bg-opacity-75 d-flex align-items-center
                        justify-content-center gap-3 opacity-0
                        transition-opacity">
              <a href="#" class="btn btn-light btn-sm">
                Live Demo
              </a>
              <a href="#" class="btn btn-outline-light btn-sm">
                Case Study
              </a>
            </div>
          </div>
          <div class="card-body p-4">
            <div class="d-flex flex-wrap gap-2 mb-3">
              <span class="badge bg-primary-subtle text-primary fw-normal">
                Angular 22
              </span>
              <span class="badge bg-primary-subtle text-primary fw-normal">
                Bootstrap 5.3
              </span>
              <span class="badge bg-primary-subtle text-primary fw-normal">
                TypeScript
              </span>
            </div>
            <h3 class="h5 fw-semibold mb-2">SaaS Admin Dashboard</h3>
            <p class="text-muted small mb-3">
              Built a complete admin dashboard for a SaaS product
              with user management, analytics, and billing.
              Angular 22 with Signals throughout, Bootstrap 5.3 for UI.
            </p>
            <div class="d-flex gap-4">
              <div>
                <div class="fw-bold small">40%</div>
                <div class="text-muted" style="font-size:11px;">
                  Load time improvement
                </div>
              </div>
              <div>
                <div class="fw-bold small">12K</div>
                <div class="text-muted" style="font-size:11px;">
                  Monthly active users
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- Repeat for 3-4 projects -->

    </div>
  </div>
</section>

Enter fullscreen mode Exit fullscreen mode

Project overlay appears on hover — CSS handles this. Tech stack badges. Brief description with specific contribution. Outcome metrics where you have them. This structure works for 3-4 featured projects.

Section 4 — Skills

<section id="skills" class="skills-section py-80">
  <div class="container">
    <div class="row mb-50">
      <div class="col-lg-6">
        <h2 class="h1 fw-bold mb-3">Skills & Technologies</h2>
        <p class="text-muted">
          What I work with daily. Grouped by area.
        </p>
      </div>
    </div>
    <div class="row g-4">
      <div class="col-md-6 col-lg-4">
        <div class="skill-group card border-0 bg-light h-100 p-4">
          <div class="skill-icon mb-3">
            <div class="bg-primary-subtle rounded-3 p-3 d-inline-block">
              <i class="bx bxl-angular text-primary fs-3"></i>
            </div>
          </div>
          <h3 class="h6 fw-semibold mb-3">Frontend Frameworks</h3>
          <div class="d-flex flex-wrap gap-2">
            <span class="badge bg-white text-dark border fw-normal py-2 px-3">
              Angular 22
            </span>
            <span class="badge bg-white text-dark border fw-normal py-2 px-3">
              React 19
            </span>
            <span class="badge bg-white text-dark border fw-normal py-2 px-3">
              Next.js 16
            </span>
            <span class="badge bg-white text-dark border fw-normal py-2 px-3">
              TypeScript
            </span>
          </div>
        </div>
      </div>
      <div class="col-md-6 col-lg-4">
        <div class="skill-group card border-0 bg-light h-100 p-4">
          <div class="skill-icon mb-3">
            <div class="bg-primary-subtle rounded-3 p-3 d-inline-block">
              <i class="bx bxl-bootstrap text-primary fs-3"></i>
            </div>
          </div>
          <h3 class="h6 fw-semibold mb-3">CSS & Styling</h3>
          <div class="d-flex flex-wrap gap-2">
            <span class="badge bg-white text-dark border fw-normal py-2 px-3">
              Bootstrap 5.3
            </span>
            <span class="badge bg-white text-dark border fw-normal py-2 px-3">
              SCSS/Sass
            </span>
            <span class="badge bg-white text-dark border fw-normal py-2 px-3">
              Tailwind CSS
            </span>
            <span class="badge bg-white text-dark border fw-normal py-2 px-3">
              CSS Custom Properties
            </span>
          </div>
        </div>
      </div>
      <div class="col-md-6 col-lg-4">
        <div class="skill-group card border-0 bg-light h-100 p-4">
          <div class="skill-icon mb-3">
            <div class="bg-primary-subtle rounded-3 p-3 d-inline-block">
              <i class="bx bx-code-alt text-primary fs-3"></i>
            </div>
          </div>
          <h3 class="h6 fw-semibold mb-3">Tools & Backend</h3>
          <div class="d-flex flex-wrap gap-2">
            <span class="badge bg-white text-dark border fw-normal py-2 px-3">
              Node.js
            </span>
            <span class="badge bg-white text-dark border fw-normal py-2 px-3">
              Git
            </span>
            <span class="badge bg-white text-dark border fw-normal py-2 px-3">
              AWS
            </span>
            <span class="badge bg-white text-dark border fw-normal py-2 px-3">
              PostgreSQL
            </span>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>

Enter fullscreen mode Exit fullscreen mode

Grouped by category. Badge tags instead of progress bars. Clean cards with icon per category. Honest — only list what you actually use.

Section 5 — About

<section id="about" class="about-section py-80 bg-light">
  <div class="container">
    <div class="row align-items-center g-5">
      <div class="col-lg-5">
        <img src="assets/images/about-photo.jpg"
             alt="About Your Name"
             class="img-fluid rounded-4 shadow">
      </div>
      <div class="col-lg-7">
        <h2 class="h1 fw-bold mb-4">About Me</h2>
        <p class="text-muted mb-3">
          I've been building web applications since 2013.
          Started with Bootstrap 3, grew into Angular and React,
          now building production systems with Angular 22,
          Bootstrap 5.3, and Next.js 16.
        </p>
        <p class="text-muted mb-4">
          I care about code that's readable in six months,
          accessible to everyone, and fast on a real device
          on a real connection. Not just fast in a Lighthouse
          test on a MacBook Pro on fiber.
        </p>
        <div class="row g-3 mb-4">
          <div class="col-6">
            <div class="d-flex align-items-center gap-2">
              <i class="bx bx-map text-primary"></i>
              <span class="small">India</span>
            </div>
          </div>
          <div class="col-6">
            <div class="d-flex align-items-center gap-2">
              <i class="bx bx-briefcase text-primary"></i>
              <span class="small">Available for remote</span>
            </div>
          </div>
          <div class="col-6">
            <div class="d-flex align-items-center gap-2">
              <i class="bx bx-calendar text-primary"></i>
              <span class="small">12+ years experience</span>
            </div>
          </div>
          <div class="col-6">
            <div class="d-flex align-items-center gap-2">
              <i class="bx bx-code-block text-primary"></i>
              <span class="small">Full stack capable</span>
            </div>
          </div>
        </div>
        <div class="d-flex gap-3">
          <a href="assets/your-resume.pdf"
             class="btn btn-primary px-4"
             download>
            Download Resume
          </a>
          <a href="https://github.com/yourusername"
             class="btn btn-outline-secondary px-4"
             target="_blank">
            GitHub Profile
          </a>
        </div>
      </div>
    </div>
  </div>
</section>

Enter fullscreen mode Exit fullscreen mode

Short paragraphs. Specific details — not generic "passionate about clean code." Quick facts in a grid. Resume download and GitHub link as CTAs.

Section 6 — Contact

<section id="contact" class="contact-section py-80">
  <div class="container">
    <div class="row justify-content-center mb-50">
      <div class="col-lg-6 text-center">
        <h2 class="h1 fw-bold mb-3">Let's Work Together</h2>
        <p class="text-muted">
          Available for freelance projects and full-time opportunities.
          Response time: within 24 hours.
        </p>
      </div>
    </div>
    <div class="row g-4 justify-content-center">
      <div class="col-lg-7">
        <div class="card border-0 shadow-sm p-4 p-md-5">
          <form action="https://formspree.io/f/your-form-id"
                method="POST">
            <div class="row g-3">
              <div class="col-md-6">
                <label class="form-label fw-medium small">Name *</label>
                <input type="text"
                       name="name"
                       class="form-control"
                       placeholder="Your name"
                       required>
              </div>
              <div class="col-md-6">
                <label class="form-label fw-medium small">Email *</label>
                <input type="email"
                       name="email"
                       class="form-control"
                       placeholder="[email protected]"
                       required>
              </div>
              <div class="col-12">
                <label class="form-label fw-medium small">
                  Project Type
                </label>
                <select name="project_type" class="form-select">
                  <option value="">Select project type</option>
                  <option>Admin Dashboard</option>
                  <option>Landing Page</option>
                  <option>Full Stack Application</option>
                  <option>Consultation</option>
                  <option>Other</option>
                </select>
              </div>
              <div class="col-12">
                <label class="form-label fw-medium small">Message *</label>
                <textarea name="message"
                          class="form-control"
                          rows="5"
                          placeholder="Tell me about your project..."
                          required></textarea>
              </div>
              <div class="col-12">
                <button type="submit"
                        class="btn btn-primary btn-lg w-100">
                  Send Message
                </button>
              </div>
            </div>
          </form>
        </div>
      </div>
      <div class="col-lg-3">
        <div class="d-flex flex-column gap-3">
          <div class="card border-0 bg-light p-4">
            <div class="d-flex align-items-center gap-3">
              <div class="bg-primary-subtle rounded-3 p-3">
                <i class="bx bx-envelope text-primary fs-5"></i>
              </div>
              <div>
                <div class="fw-semibold small">Email</div>
                <a href="mailto:[email protected]"
                   class="text-muted small text-decoration-none">
                  [email protected]
                </a>
              </div>
            </div>
          </div>
          <div class="card border-0 bg-light p-4">
            <div class="d-flex align-items-center gap-3">
              <div class="bg-primary-subtle rounded-3 p-3">
                <i class="bx bxl-linkedin text-primary fs-5"></i>
              </div>
              <div>
                <div class="fw-semibold small">LinkedIn</div>
                <a href="https://linkedin.com/in/yourprofile"
                   class="text-muted small text-decoration-none"
                   target="_blank">
                  linkedin.com/in/yourprofile
                </a>
              </div>
            </div>
          </div>
          <div class="card border-0 bg-light p-4">
            <div class="d-flex align-items-center gap-3">
              <div class="bg-primary-subtle rounded-3 p-3">
                <i class="bx bxl-github text-primary fs-5"></i>
              </div>
              <div>
                <div class="fw-semibold small">GitHub</div>
                <a href="https://github.com/yourusername"
                   class="text-muted small text-decoration-none"
                   target="_blank">
                  github.com/yourusername
                </a>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>

Enter fullscreen mode Exit fullscreen mode

Formspree for the form — no backend needed. Project type dropdown helps qualify enquiries. Contact info cards beside the form for people who prefer email directly.

Dark Mode Toggle

// assets/js/main.js

// Theme toggle
const themeToggle = document.getElementById('themeToggle')
const savedTheme = localStorage.getItem('theme') ||
  (window.matchMedia('(prefers-color-scheme: dark)').matches
    ? 'dark' : 'light')

document.documentElement.setAttribute('data-bs-theme', savedTheme)

themeToggle?.addEventListener('click', () => {
  const current = document.documentElement
    .getAttribute('data-bs-theme')
  const next = current === 'dark' ? 'light' : 'dark'
  document.documentElement.setAttribute('data-bs-theme', next)
  localStorage.setItem('theme', next)
})

// Smooth scroll for nav links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
  anchor.addEventListener('click', (e) => {
    e.preventDefault()
    const target = document.querySelector(
      anchor.getAttribute('href')
    )
    target?.scrollIntoView({ behavior: 'smooth', block: 'start' })
  })
})

// Active nav link on scroll
const sections = document.querySelectorAll('section[id]')
const navLinks = document.querySelectorAll('.navbar-nav .nav-link')

window.addEventListener('scroll', () => {
  const scrollY = window.scrollY

  sections.forEach(section => {
    const sectionTop = section.offsetTop - 100
    const sectionHeight = section.offsetHeight
    const sectionId = section.getAttribute('id')

    if (scrollY >= sectionTop &&
        scrollY < sectionTop + sectionHeight) {
      navLinks.forEach(link => {
        link.classList.remove('active')
        if (link.getAttribute('href') === `#${sectionId}`) {
          link.classList.add('active')
        }
      })
    }
  })
})

Enter fullscreen mode Exit fullscreen mode

Three JavaScript behaviors — theme toggle, smooth scroll, active nav link on scroll. No jQuery. Pure vanilla JavaScript. Everything Bootstrap handles through data-bs-* attributes.

CSS for Custom Touches

// assets/scss/style.scss additions

// Spacing utilities
.py-80 { padding-top: 80px; padding-bottom: 80px; }
.py-100 { padding-top: 100px; padding-bottom: 100px; }
.mb-50 { margin-bottom: 50px; }

// Project card hover
.hover-lift {
  transition: transform 0.2s ease, box-shadow 0.2s ease;

  &:hover {
    transform: translateY(-4px);
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.12) !important;

    .project-overlay {
      opacity: 1 !important;
    }
  }
}

.project-overlay {
  transition: opacity 0.2s ease;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

// Dark mode custom properties
[data-bs-theme="dark"] {
  --bs-body-bg: #0f1117;
  --bs-secondary-bg: #1a1f2e;

  .bg-light {
    background-color: #1a1f2e !important;
  }

  .card {
    background-color: #1e2130;
    border-color: #2d3748;
  }

  .skill-group {
    background-color: #1e2130 !important;
  }
}

Enter fullscreen mode Exit fullscreen mode

Minimal custom CSS on top of Bootstrap. Hover lift effect for project cards. Dark mode overrides for custom sections. Everything else is Bootstrap utilities.

If you want a Bootstrap 5.3 portfolio template already built with this structure — browse LettStart Design. Zero jQuery, Bootstrap 5.3, Lighthouse above 85. Use FIRST30 for 30% off.