Creating a Professional Developer Portfolio Website with Next.js and Modern CSS

OdynDevOdynDev
7 min read

A well-crafted portfolio website is essential for any developer looking to showcase their skills and projects to potential employers or clients. In this comprehensive guide, I'll walk you through building an impressive, responsive portfolio site using Next.js and modern CSS techniques that will help you stand out in the competitive tech industry.


Why Next.js for Your Portfolio?

Next.js offers several advantages for portfolio websites:

  • Server-side rendering for better SEO

  • Fast page loads with automatic code splitting

  • Image optimization with the built-in Image component

  • Easy routing without complex configuration

  • React-based development for component reusability

Project Structure and Setup

Let's break down how to build a professional portfolio website based on the code examples.


Setting Up the Project

First, create a new Next.js project:

npx create-next-app portfolio-website
cd portfolio-website

Essential Components

Your portfolio will need several key components:

  1. Hero section with introduction

  2. About section with skills

  3. Portfolio/projects showcase

  4. Services offered

  5. Testimonials from clients

  6. Contact information and form

  7. Blog section (optional)


Styling Your Portfolio

The CSS structure in our example uses CSS variables for consistent theming and easy updates. This approach makes it simple to change the entire color scheme by modifying just a few variables.

:root {
  --primary-color: #6366f1;
  --primary-hover: #4f46e5;
  --secondary-color: #22d3ee;
  --dark-color: #1e293b;
  --light-color: #f8fafc;
  --gray-color: #94a3b8;
  --border-color: #e2e8f0;
  --box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
  --transition: all 0.3s ease;
  --border-radius: 8px;
}

Responsive Design Principles

The example CSS includes media queries to ensure your site looks good on all devices:

@media (max-width: 1024px) {
  h1 { font-size: 3rem; }
  h2 { font-size: 2.2rem; }
}

@media (max-width: 768px) {
  /* Tablet styles */
  .about-grid, .contact-grid {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 576px) {
  /* Mobile styles */
  .hero-btns {
    flex-direction: column;
  }
}

Building the Main Sections

Let's look at implementing each crucial section:

1. The Navigation Bar

A fixed navbar that changes appearance on scroll enhances user experience:

export const Navbar = ({ scrollY }) => {
  const [isScrolled, setIsScrolled] = useState(false);

  useEffect(() => {
    setIsScrolled(scrollY > 50);
  }, [scrollY]);

  return (
    <nav className={isScrolled ? 'scrolled' : ''}>
      <div className="nav-container container">
        <div className="logo">YourName</div>
        <ul className="nav-links">
          <li><a href="#home" className="nav-link active">Home</a></li>
          <li><a href="#about" className="nav-link">About</a></li>
          <li><a href="#portfolio" className="nav-link">Portfolio</a></li>
          <li><a href="#services" className="nav-link">Services</a></li>
          <li><a href="#contact" className="nav-link">Contact</a></li>
        </ul>
      </div>
    </nav>
  );
};

2. Hero Section

The hero section creates your first impression. It should be visually striking and clearly communicate who you are:

<section className="hero" id="home">
  <div className="hero-shapes">
    <div className="shape shape-1"></div>
    <div className="shape shape-2"></div>
    <div className="shape shape-3"></div>
  </div>
  <div className="container">
    <div className="hero-content">
      <h1>Hello, I'm <span className="highlight">Your Name</span></h1>
      <p>Front-end Developer specializing in creating modern and responsive web applications using React and Next.js</p>
      <div className="hero-btns">
        <Link href="#portfolio">
          <span className="btn btn-primary">View Projects</span>
        </Link>
        <Link href="#contact">
          <span className="btn btn-outline">Contact</span>
        </Link>
      </div>
    </div>
  </div>
  <div className="scroll-indicator">
    <span></span>
  </div>
</section>


3. About Section with Skill Bars

The about section gives visitors insight into your background and skills:

<section className="about section" id="about">
  <div className="container">
    <div className="about-grid">
      <div className="about-image">
        <div className="image-wrapper">
          <Image 
            src="/profile.jpg" 
            alt="Profile picture" 
            width={500} 
            height={600} 
            className="profile-img"
          />
        </div>
        <div className="experience-box">
          <p>Experience: 5+ Years</p>
        </div>
      </div>
      <div className="about-text">
        <h2>About Me</h2>
        <p>I am passionate about creating modern web applications with intuitive user interfaces...</p>

        <div className="skill-bars" ref={skillsRef}>
          {skills.map((skill, index) => (
            <SkillBar
              key={index}
              name={skill.name}
              percentage={skill.percentage}
            />
          ))}
        </div>

        <div className="about-btns">
          <a href="/cv.pdf" className="btn btn-secondary" download>
            Download CV
          </a>
        </div>
      </div>
    </div>
  </div>
</section>

The SkillBar component visualizes your expertise:

export const SkillBar = ({ name, percentage }) => {
  return (
    <div className="skill-bar">
      <span>{name}</span>
      <div 
        className="skill-progress-bar" 
        data-width={`${percentage}%`} 
        style={{ width: `${percentage}%` }}
      ></div>
    </div>
  );
};

4. Portfolio Section with Filtering

The portfolio section showcases your work with filtering options:

<section className="portfolio section" id="portfolio">
  <div className="container">
    <div className="section-header">
      <h2>My Projects</h2>
      <p>Check out selected projects I had the pleasure to work on</p>
    </div>

    <div className="portfolio-filters">
      <button 
        className={`filter-btn ${activeFilter === 'all' ? 'active' : ''}`}
        onClick={() => setActiveFilter('all')}
      >
        All
      </button>
      <button 
        className={`filter-btn ${activeFilter === 'web' ? 'active' : ''}`}
        onClick={() => setActiveFilter('web')}
      >
        Web Applications
      </button>
      {/* Additional filter buttons */}
    </div>

    <div className="portfolio-grid">
      {filteredProjects.map((item) => (
        <PortfolioItem key={item.id} item={item} />
      ))}
    </div>
  </div>
</section>


5. Implementing Scroll Animations

Add scroll animations to enhance the visual experience:

export const RevealAnimation = ({ children }) => {
  const [isVisible, setIsVisible] = useState(false);
  const ref = useRef(null);

  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => {
        if (entry.isIntersecting) {
          setIsVisible(true);
          observer.unobserve(entry.target);
        }
      },
      { threshold: 0.1 }
    );

    if (ref.current) {
      observer.observe(ref.current);
    }

    return () => {
      if (ref.current) {
        observer.unobserve(ref.current);
      }
    };
  }, []);

  return (
    <div 
      ref={ref} 
      className={`reveal-animation ${isVisible ? 'animate' : ''}`}
    >
      {children}
    </div>
  );
};

Adding Interactive Elements

Skill Bar Animation

Add this effect to animate skill bars when they come into view:

useEffect(() => {
  const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        const skillBars = document.querySelectorAll('.skill-progress-bar')
        skillBars.forEach((bar, index) => {
          setTimeout(() => {
            bar.style.width = bar.getAttribute('data-width') || ''
          }, index * 200)
        })
      }
    })
  }, { threshold: 0.5 })

  if (skillsRef.current) {
    observer.observe(skillsRef.current)
  }

  return () => {
    if (skillsRef.current) {
      observer.unobserve(skillsRef.current)
    }
  }
}, [])

Portfolio Filtering

Implement filtering functionality for your portfolio projects:

const filteredProjects = activeFilter === 'all' 
  ? portfolioItems
  : portfolioItems.filter(item => item.category === activeFilter)

Contact Form Section:

<section className="contact section" id="contact">
  <div className="container">
    <div className="section-header">
      <h2>Contact</h2>
      <p>Feel free to contact me if you have any questions or would like to discuss potential collaboration.</p>
    </div>

    <div className="contact-grid">
      <div className="contact-info">
        {/* Contact cards with icons */}
        <div className="contact-card">
          <div className="contact-icon">
            {/* Email icon SVG */}
          </div>
          <div className="contact-text">
            <h3>E-mail</h3>
            <p>contact@yourdomain.com</p>
          </div>
        </div>
        {/* More contact cards */}
      </div>

      <div className="contact-form">
        <form>
          {/* Form fields */}
          <button type="submit" className="btn btn-primary">
            Send Message
          </button>
        </form>
      </div>
    </div>
  </div>
</section>

For a complete portfolio, consider adding serverless functions to handle form submissions.


Performance Optimizations

Ensure your portfolio loads quickly with these optimizations:

  1. Optimize images using Next.js Image component

  2. Lazy load components that are below the fold

  3. Minimize CSS and JavaScript with proper bundling

  4. Use next/font for web fonts to avoid layout shifts

  5. Implement progressive loading for large media files

SEO Considerations

Don't forget to optimize your portfolio for search engines:

<Head>
  <title>Your Name | Front-end Developer</title>
  <meta name="description" content="Portfolio of a front-end developer specializing in React and Next.js" />
  <meta name="keywords" content="front-end developer, React developer, Next.js, portfolio" />
  <meta name="author" content="Your Name" />
  <link rel="canonical" href="https://yourdomain.com" />
  <meta property="og:title" content="Your Name | Front-end Developer" />
  <meta property="og:description" content="Portfolio of a front-end developer specializing in React and Next.js" />
  <meta property="og:image" content="https://yourdomain.com/og-image.jpg" />
  <meta property="og:url" content="https://yourdomain.com" />
  <meta name="twitter:card" content="summary_large_image" />
</Head>

Conclusion

Building a professional portfolio with Next.js and modern CSS gives you a fast, responsive, and visually appealing website to showcase your skills and projects. The combination of server-side rendering for SEO benefits and client-side interactivity creates an optimal user experience.

Remember that your portfolio is a living document—update it regularly with new projects and skills to keep it relevant. Make sure it reflects your current abilities and career goals.

By following this guide, you'll create a portfolio that not only looks great but also demonstrates your technical expertise in modern web development frameworks and best practices.

Would you like me to expand on any specific aspect of building a portfolio website with Next.js, such as deployment options or more advanced animations?


Thanks for stopping by! 🙌

I really appreciate you taking the time to read this.
If you’re curious about more of my work, feel free to check out my portfolio:
👉 [Click here]

I'm always pushing myself to learn, improve, and build even better projects. 🚀
You can also browse more of my creations and articles right here on my Profile. Enjoy exploring!

0
Subscribe to my newsletter

Read articles from OdynDev directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

OdynDev
OdynDev

My name is Daniel. I code, design, and get things done. I'm not a fan of school, but I love learning - on my own terms. I build websites that make sense, look good, and never feel boring. If you're looking for someone who does things right, with clarity and a human touch - I’m your guy.