In today’s digital landscape, a personal portfolio website is more than just a nice-to-have; it’s a necessity. It’s your online resume, a showcase of your skills and projects, and a crucial tool for networking and landing new opportunities. But building a portfolio can seem daunting, especially if you’re new to web development. This guide will walk you through creating a simple, yet effective, interactive portfolio website using Next.js, a powerful React framework.
Why Next.js for Your Portfolio?
Next.js offers several advantages that make it an excellent choice for building a portfolio:
- Server-Side Rendering (SSR) and Static Site Generation (SSG): Next.js can pre-render your pages, improving SEO and initial load times. This is crucial for getting your portfolio seen by potential clients or employers.
- React-Based: If you’re familiar with React, you’ll feel right at home with Next.js. It leverages React’s component-based architecture, making your code modular and reusable.
- Easy Routing: Next.js simplifies routing with its file-based system. Each file in your `pages` directory automatically becomes a route.
- Built-in Features: Next.js provides built-in features like image optimization, API routes, and more, streamlining the development process.
- Performance: Next.js optimizes performance out of the box, ensuring a smooth user experience.
This tutorial will focus on creating a basic portfolio website. We will cover how to display your projects, skills, and contact information. You can then expand on this foundation with more advanced features as your skills and needs evolve.
Setting Up Your Next.js Project
Let’s get started by setting up a new Next.js project. Open your terminal and run the following command:
npx create-next-app portfolio-app
This command creates a new directory called `portfolio-app` and sets up a basic Next.js project. Navigate into the project directory:
cd portfolio-app
Now, start the development server:
npm run dev
Open your browser and go to `http://localhost:3000`. You should see the default Next.js welcome page. This confirms that your project is set up correctly.
Project Structure Overview
Before we dive into the code, let’s take a quick look at the project structure. This will help you understand where to place your files and how Next.js organizes your application.
- `pages/`: This is the heart of your Next.js application. Each file in this directory becomes a route. For example, `pages/index.js` becomes the homepage (`/`), and `pages/about.js` becomes the about page (`/about`).
- `components/`: This directory is where you’ll store your reusable React components, such as navigation bars, project cards, and skill sections.
- `styles/`: This directory is for your CSS or other styling files. Next.js supports CSS Modules, styled-components, and other styling solutions.
- `public/`: This directory holds static assets like images, fonts, and other files.
- `package.json`: This file lists your project’s dependencies and scripts.
Creating the Homepage (index.js)
The `index.js` file in the `pages` directory will be your homepage. Let’s replace the default content with our portfolio content. Open `pages/index.js` and replace the code with the following:
import Head from 'next/head';
import styles from '../styles/Home.module.css';
export default function Home() {
return (
<div className={styles.container}>
<Head>
<title>Your Name - Portfolio</title>
<meta name="description" content="Your name's portfolio website" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className={styles.main}>
<h1 className={styles.title}>
Welcome to My Portfolio!
</h1>
<p className={styles.description}>
I'm [Your Name], a [Your Profession].
</p>
<div className={styles.grid}>
<a href="#projects" className={styles.card}>
<h2>Projects →</h2>
<p>View my featured projects.</p>
</a>
<a href="#skills" className={styles.card}>
<h2>Skills →</h2>
<p>Explore my skill set.</p>
</a>
<a href="#contact" className={styles.card}>
<h2>Contact →</h2>
<p>Get in touch with me.</p>
</a>
</div>
</main>
<footer className={styles.footer}>
<a
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Powered by{' '}
<img src="/vercel.svg" alt="Vercel Logo" className={styles.logo} /
>
</a>
</footer>
</div>
)
}
This code does the following:
- Imports `Head` from `next/head`: This component allows you to manage the `<head>` section of your HTML, including the title, meta descriptions, and other metadata.
- Imports styles from `../styles/Home.module.css`: This imports the CSS styles for your homepage. We’ll create this file shortly.
- Defines a `Home` component: This is the main component for your homepage.
- Sets the page title and meta description: This is crucial for SEO.
- Displays a welcome message and a brief description: This introduces you to visitors.
- Includes three links to different sections of your portfolio: Projects, Skills, and Contact. These will link to sections within the same page in this basic example, using anchor links.
- Includes a footer: This is a standard element for most websites.
Styling the Homepage (Home.module.css)
Now, let’s create the CSS file to style your homepage. Create a file named `Home.module.css` in the `styles` directory and add the following CSS:
.container {
min-height: 100vh;
padding: 0 0.5rem;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.main {
padding: 5rem 0;
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.footer {
width: 100%;
height: 100px;
border-top: 1px solid #eaeaea;
display: flex;
justify-content: center;
align-items: center;
}
.footer a {
display: flex;
justify-content: center;
align-items: center;
flex-grow: 1;
}
.title {
margin: 0;
line-height: 1.15;
font-size: 4rem;
text-align: center;
}
.description {
text-align: center;
font-size: 1.5rem;
line-height: 1.5;
margin: 2rem 0;
}
.grid {
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
max-width: 800px;
}
.card {
margin: 1rem;
padding: 1.5rem;
text-align: left;
color: inherit;
text-decoration: none;
border: 1px solid #eaeaea;
border-radius: 10px;
transition: color 0.15s ease, border-color 0.15s ease;
width: 100%;
max-width: 300px;
}
.card:hover,
.card:focus,
.card:active {
color: #0070f3;
border-color: #0070f3;
}
.card h2 {
margin: 0 0 1rem 0;
font-size: 1.5rem;
}
.card p {
margin: 0;
font-size: 1.25rem;
line-height: 1.5;
}
.logo {
height: 1em;
}
This CSS provides basic styling for the homepage, including the container, main content, footer, title, description, and the card-style links. Feel free to customize this CSS to match your desired aesthetic.
Creating the About, Projects, and Contact Sections
Now, let’s create the sections that the links on the homepage point to. For this basic portfolio, these sections will be on the same page, and we will use anchor links to navigate to them. We can also create separate pages for each section for more complex layouts.
Inside the `pages/index.js` file, add the following sections after the `<div className={styles.grid}>` element, before the closing `</main>` tag:
<section id="projects" className={styles.section}>
<h2>Projects</h2>
<p>Here you'll find a showcase of my projects. (This section is under construction)</p>
{/* Add your project cards here */}
</section>
<section id="skills" className={styles.section}>
<h2>Skills</h2>
<p>I have experience with the following technologies: (This section is under construction)</p>
<ul>
<li>JavaScript</li>
<li>React</li>
<li>Next.js</li>
<li>HTML</li>
<li>CSS</li>
</ul>
</section>
<section id="contact" className={styles.section}>
<h2>Contact</h2>
<p>Feel free to reach out to me! (This section is under construction)</p>
<p>Email: [Your Email Address]</p>
<p>LinkedIn: [Your LinkedIn Profile URL]</p>
</section>
Also, add the following CSS to `styles/Home.module.css` to style the sections:
.section {
margin-top: 3rem;
padding: 2rem;
border: 1px solid #ccc;
border-radius: 8px;
}
This creates the basic structure for the Projects, Skills, and Contact sections. Replace the placeholder content in each section with your actual information and projects. Remember to update the anchor links on the homepage to point to the correct sections.
Adding Project Cards (Project Showcase)
Let’s create a reusable `ProjectCard` component to display your projects. Create a new file named `ProjectCard.js` in the `components` directory. Add the following code:
import styles from '../styles/Home.module.css';
function ProjectCard({ title, description, imageUrl, projectUrl }) {
return (
<div className={styles.projectCard}>
<img src={imageUrl} alt={title} className={styles.projectImage} />
<h3>{title}</h3>
<p>{description}</p>
<a href={projectUrl} target="_blank" rel="noopener noreferrer" className={styles.projectLink}>
View Project
</a>
</div>
);
}
export default ProjectCard;
Add the following CSS to `styles/Home.module.css`:
.projectCard {
border: 1px solid #ddd;
border-radius: 8px;
padding: 1rem;
margin-bottom: 1rem;
width: 100%;
max-width: 600px;
}
.projectImage {
width: 100%;
height: auto;
margin-bottom: 0.5rem;
border-radius: 4px;
}
.projectLink {
display: inline-block;
padding: 0.5rem 1rem;
background-color: #0070f3;
color: white;
text-decoration: none;
border-radius: 4px;
margin-top: 0.5rem;
}
Now, in your `pages/index.js` file, import the `ProjectCard` component and add some project data to the `projects` section:
import Head from 'next/head';
import styles from '../styles/Home.module.css';
import ProjectCard from '../components/ProjectCard';
export default function Home() {
const projects = [
{
title: 'Project 1',
description: 'A brief description of project 1.',
imageUrl: '/project1.jpg', // Replace with your image path
projectUrl: 'https://example.com/project1', // Replace with your project URL
},
{
title: 'Project 2',
description: 'A brief description of project 2.',
imageUrl: '/project2.jpg', // Replace with your image path
projectUrl: 'https://example.com/project2', // Replace with your project URL
},
// Add more projects as needed
];
return (
<div className={styles.container}>
<Head>
<title>Your Name - Portfolio</title>
<meta name="description" content="Your name's portfolio website" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className={styles.main}>
<h1 className={styles.title}>
Welcome to My Portfolio!
</h1>
<p className={styles.description}>
I'm [Your Name], a [Your Profession].
</p>
<div className={styles.grid}>
<a href="#projects" className={styles.card}>
<h2>Projects →</h2>
<p>View my featured projects.</p>
</a>
<a href="#skills" className={styles.card}>
<h2>Skills →</h2>
<p>Explore my skill set.</p>
</a>
<a href="#contact" className={styles.card}>
<h2>Contact →</h2>
<p>Get in touch with me.</p>
</a>
</div>
<section id="projects" className={styles.section}>
<h2>Projects</h2>
{projects.map((project, index) => (
<ProjectCard
key={index}
title={project.title}
description={project.description}
imageUrl={project.imageUrl}
projectUrl={project.projectUrl}
/>
))}
</section>
<section id="skills" className={styles.section}>
<h2>Skills</h2>
<p>I have experience with the following technologies: (This section is under construction)</p>
<ul>
<li>JavaScript</li>
<li>React</li>
<li>Next.js</li>
<li>HTML</li>
<li>CSS</li>
</ul>
</section>
<section id="contact" className={styles.section}>
<h2>Contact</h2>
<p>Feel free to reach out to me! (This section is under construction)</p>
<p>Email: [Your Email Address]</p>
<p>LinkedIn: [Your LinkedIn Profile URL]</p>
</section>
</main>
<footer className={styles.footer}>
<a
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Powered by{' '}
<img src="/vercel.svg" alt="Vercel Logo" className={styles.logo} /
>
</a>
</footer>
</div>
)
}
Important: Make sure to replace `/project1.jpg` and `/project2.jpg` with the actual paths to your project images. Also, replace the `projectUrl` values with the URLs of your projects. Place your images in the `public` directory.
Adding Images (Image Optimization)
Next.js has built-in image optimization capabilities. To use them, you’ll need to import the `Image` component from `next/image`. Modify the `ProjectCard.js` file to use this component:
import styles from '../styles/Home.module.css';
import Image from 'next/image';
function ProjectCard({ title, description, imageUrl, projectUrl }) {
return (
<div className={styles.projectCard}>
<Image src={imageUrl} alt={title} width={600} height={400} className={styles.projectImage} />
<h3>{title}</h3>
<p>{description}</p>
<a href={projectUrl} target="_blank" rel="noopener noreferrer" className={styles.projectLink}>
View Project
</a>
</div>
);
}
export default ProjectCard;
Key changes:
- Imported `Image` from `next/image`.
- Replaced the `<img>` tag with the `<Image>` component.
- Added `width` and `height` attributes. These are required for the image optimization to work correctly. You can adjust these values based on your image dimensions.
Next.js will automatically optimize your images, reducing their file size and improving loading times.
Deployment
Once you’ve built your portfolio, you’ll want to deploy it so that it’s accessible to the world. Next.js makes deployment incredibly easy. Here’s how to deploy to Vercel, a platform specifically designed for Next.js applications:
- Create a Vercel Account: If you don’t already have one, sign up for a free Vercel account at https://vercel.com/.
- Connect Your GitHub Repository: Vercel integrates seamlessly with GitHub. Log in to Vercel and connect your GitHub account. Then, import your `portfolio-app` repository.
- Configure Deployment (If Necessary): Vercel will usually detect that it’s a Next.js project and automatically configure the deployment settings. You might need to specify the build command (`npm run build`) and the output directory (usually `.next`). However, Vercel often handles this automatically.
- Deploy: Click the “Deploy” button. Vercel will build and deploy your application.
- Access Your Portfolio: Once the deployment is complete, Vercel will provide you with a unique URL for your portfolio website. You can then share this link with potential employers or clients.
Vercel offers a generous free tier, making it an excellent choice for hosting your portfolio.
Common Mistakes and How to Fix Them
Here are some common mistakes beginners make when building a Next.js portfolio and how to fix them:
- Incorrect File Paths: Make sure your file paths are accurate, especially when importing components, images, and CSS files. Double-check your import statements and image paths.
- CSS Conflicts: If you’re using CSS Modules (as we did), make sure your class names are unique and that you’re importing the correct CSS file. Avoid using generic class names that might conflict with other libraries.
- Missing Image Dimensions: When using the `next/image` component, always provide the `width` and `height` attributes. These are essential for image optimization and prevent layout shifts. If you don’t know the exact dimensions, you can often use the `fill` prop along with a parent element with defined dimensions.
- Forgetting to Build: Before deploying, make sure you build your application using `npm run build`. This creates the optimized production-ready files.
- Ignoring SEO: Pay attention to your page titles, meta descriptions, and alt text for images. These elements are crucial for SEO and help people find your portfolio on search engines.
- Not Using Version Control: Always use version control (like Git) to track your changes. This allows you to revert to previous versions if you make a mistake and collaborate with others.
- Overcomplicating the Design: Start simple. Focus on showcasing your projects and skills effectively. You can always add more features and design elements later.
Key Takeaways
- Next.js is a great choice for portfolio websites: It offers excellent performance, SEO benefits, and a developer-friendly experience.
- Structure your project carefully: Understand the `pages`, `components`, and `styles` directories to organize your code effectively.
- Use reusable components: Create components like `ProjectCard` to keep your code modular and maintainable.
- Optimize your images: Leverage the built-in image optimization features in Next.js.
- Pay attention to SEO: Optimize your page titles, meta descriptions, and image alt text.
- Deploy your portfolio: Platforms like Vercel make deployment easy.
FAQ
Q: Can I use different styling methods besides CSS Modules?
A: Yes, Next.js supports various styling methods, including styled-components, Tailwind CSS, and global CSS. Choose the method you’re most comfortable with.
Q: How do I handle different screen sizes (responsive design)?
A: Use CSS media queries in your CSS files. You can also use libraries like styled-components or Tailwind CSS, which provide built-in responsive design features.
Q: How can I add a contact form?
A: You can use a third-party service like Formspree or Netlify Forms, or you can create an API route in Next.js to handle form submissions. For a simple setup, third-party services are often the easiest option.
Q: How do I update my portfolio after deployment?
A: After making changes to your code, commit them to your Git repository and push them to your connected platform (e.g., GitHub). Vercel will automatically detect the changes and redeploy your website.
Q: Where can I find more Next.js resources?
A: The official Next.js documentation is an excellent resource: https://nextjs.org/docs. You can also find numerous tutorials and examples on websites like freeCodeCamp, MDN Web Docs, and YouTube.
Building a portfolio website with Next.js is a fantastic way to showcase your skills and projects. By following these steps and customizing the code to fit your needs, you can create a professional-looking website that effectively represents your abilities to potential employers or clients. Remember to iterate and improve your portfolio over time. As you learn new skills and complete new projects, update your portfolio to reflect your growth and expertise. Your portfolio is a living document, a testament to your ongoing journey in the world of web development.
