Building my portfolio website with Next.js and Tailwind CSS

A Step-by-Step Journey of Creating a Personal Portfolio with Modern Tools and Techniques

Building my portfolio website with Next.js and Tailwind CSS

I already had a portfolio website built using the Bento layout. But now, I needed to add a blogs section to my portfolio, so I decided to build a new portfolio website with a fresh design.

This time, I chose to use Next.js (because previously, I always built my sites using React.js, so I thought, why not try Next.js this time? ) and Tailwind CSS (my go-to CSS framework that I absolutely love).

My Project Folder Structure

Starting a Next.js Project

To create a fresh Next.js project, run the following command:

npx create-next-app@latest

You can also add any additional packages you need, and you'll be ready to go!

Starting with This Code

<div className="w-full px-8 md:w-11/12 lg:px-0 lg:w-3/4 mx-auto py-20 flex flex-col gap-10">  
  <Header />  
  <div className="flex flex-col gap-7 py-5 lg:py-10">  
    <About />  
    <Separator />  
    <Experience />  
    <Separator />  
    <Blogs />  
    <Separator />  
    <Projects />  
    <Separator />  
    <Skills />  
    <Separator />  
    <Contact />  
  </div>  
  <Footer />  
</div>

I styled all my sections within this structure.

Light and Dark Theme in Next.js

To add light and dark mode to my site, I installed the next-themes package.

Adding Theme Styles

In my globals.css file, I used the following code to apply background colors based on the theme:

@layer base {  
  body {  
    @apply dark:bg-[#1D1F20] bg-gray-200;  
  }  
}

Creating a Theme Toggle Hook

Since I needed to manage the theme across different parts of the site, I created a custom hook, useThemeToggle, to handle this functionality:

import { useTheme } from "next-themes";  

const useThemeToggle = () => {  
  const { systemTheme, theme, setTheme } = useTheme();  
  const currentTheme = theme === "system" ? systemTheme : theme;  

  const toggleTheme = () => {  
    setTheme(currentTheme === "dark" ? "light" : "dark");  
  };  

  return {  
    currentTheme,  
    toggleTheme,  
  };  
};  

export default useThemeToggle;

Implementing the Theme Toggle Button

export const ThemeToggleButton = () => {  
  const { currentTheme, toggleTheme } = useThemeToggle();  

  return (  
    <button onClick={toggleTheme}>  
      {currentTheme === "dark" ? (  
        <Image  
          src={NightLight}  
          alt="night"  
          width={30}  
          height={30}  
          className="object-contain"  
        />  
      ) : (  
        <Image  
          src={nightDark}  
          alt="light"  
          width={30}  
          height={30}  
          className="object-contain"  
        />  
      )}  
    </button>  
  );  
};

Adding a Blogs Section

I chose to use static data for the blogs instead of fetching them dynamically (e.g., from Hashnode) to avoid any issues with failed requests, which could result in poor UX. I'll manually update the static data whenever I upload a new blog—it’s not too time-consuming.

Here’s the Blogs component:

export const Blogs = () => {  
  return (  
    <div className="flex flex-col gap-5">  
      <Heading title="Blogs" />  
      <article className="flex flex-col gap-5 lg:gap-3 justify-between">  
        {blogs.map((blog) => (  
          <Link href={blog.link} target="blank" key={blog.id}>  
            <div className="flex flex-col gap-3 lg:flex-row lg:justify-between">  
              <div className="w-full">  
                <div className="flex items-center gap-3">  
                  <Image  
                    src={Calendar}  
                    alt="calendar"  
                    height={23}  
                    width={23}  
                    className="object-contain"  
                  />  
                  <h1 className="text-themeText text-sm font-medium">  
                    {blog.date}  
                  </h1>  
                </div>  
              </div>  
              <div className="w-full text-lg flex flex-col gap-3">  
                <p className="font-bold dark:text-darkHeading text-lightHeading underline">  
                  {blog.title}  
                </p>  
                <p className="font-medium dark:text-darkBody text-lightBody">  
                  {blog.subTitle}  
                </p>  
              </div>  
            </div>  
          </Link>  
        ))}  
      </article>  
    </div>  
  );  
};

Deploying My Site on Netlify

I deployed my website on Netlify. You can check it out here:
rumaisa.netlify.app

GitHub Repo Link

You can also check out my GitHub repository here:

https://github.com/rumaisanaveed/new-portfolio

And that’s it for today! I’ll be sharing more such articles soon. Don’t forget to follow me, like, and comment on my articles.

Stay connected with me - Rumaisa Naveed