Introduction to Next.js
NextJS is a powerful React framework that enables developers to build performant and scalable web applications with ease. This documentation will guide you through creating a portfolio site using NextJS.
Key NextJS Features
App Router
NextJS 13+ introduces the App Router, a new routing system that provides:
- File-based routing
 - Nested layouts
 - Simplified data fetching
 - Automatic code splitting
 - Server and client components
 
Example of Routing Structure
app/
├── page.tsx          # Main landing page
├── about/
│   └── page.tsx      # About page
├── projects/
│   └── page.tsx      # Projects page
└── layout.tsx        # Global layout
Performance Optimizations
NextJS offers multiple optimization techniques:
- Automatic image optimization
 - Lazy loading of components
 - Static and server-side rendering
 - Incremental Static Regeneration (ISR)
 - Automatic code splitting
 
Package Management
package-lock.json
- Locks dependency versions precisely
 - Ensures consistent builds across different environments
 - Prevents unexpected package updates
 - Improves build reproducibility
 
Components in NextJS
Server Components
- Render on the server
 - Reduce client-side JavaScript
 - Improve initial page load performance
 - Default in App Router
 
Client Components
- Interactive components
 - Use client-side rendering
 - Enable state and event handling
 - Marked with 'use client' directive
 
Project Setup
Clone the repo
git clone https://github.com/Headstarter-AI-KNUST-Chapter/Personal-Portfolio.git
Initial Configuration
npm install
This command:
- Read the package.json file
 - Download and install all listed dependencies
 - Create a node_modules folder
 - Generate or update the package-lock.json file to ensure consistent installations across different environments
 
Diving into the codes
Overview
The Portfolio is a React functional component that composes multiple section components into a single page layout.
Page file contents
Component Imports
import React from "react";
import HeroSection from "./components/hero-section/HeroSection";
import ServiceSection from "./components/service-section/ServiceSection";
import Navbar from "./components/navbar/Navbar";
import ContactSection from "./components/contact-section/ContactSection";
import BrandSection from "./components/brand-section/BrandSection";
import Footer from "./components/footer/Footer";
Component Layout
const Portfolio = () => {
  return (
    <>
      <Navbar />
      <HeroSection />
      <div className="min-h-screen p-8 pt-0">        
        <BrandSection />
        <ServiceSection />
        <ContactSection />
        <Footer />
      </div>
    </>
  );
};
Key Observations
- Uses React Fragment (
<>...</>) for wrapping components - Utilizes a container 
divwith utility classes for spacing - Follows a top-to-bottom page composition strategy
 - Separates Navbar and HeroSection from other content sections
 
Component Sections
- Navbar: Site navigation
 - HeroSection: Landing/introduction area
 - BrandSection: Brand or client showcase
 - ServiceSection: Services or capabilities overview
 - ContactSection: Contact information or form
 - Footer: Page footer/additional links
 
Navbar Component:
- 
Scroll-Aware Design:
- The navbar dynamically changes its appearance (e.g., shadow and backdrop blur) based on the user’s scroll position. This ensures visibility while maintaining aesthetic appeal.
 - Accomplished using the 
useEffecthook and thescrollYproperty from thewindowobject. 
 
   useEffect(() => {
     const handleScroll = () => {
       setIsScrolled(window.scrollY > 0);
     };
     window.addEventListener("scroll", handleScroll);
     return () => window.removeEventListener("scroll", handleScroll);
   }, []);
- 
Copy-to-Clipboard Functionality:
- Includes a button that lets users copy an email address directly to their clipboard using the 
navigator.clipboardAPI. 
 - Includes a button that lets users copy an email address directly to their clipboard using the 
 
   const copyEmail = () => {
     navigator.clipboard.writeText("isaacoboenimil@gmail.com");
   };
- 
Responsive Mobile Menu:
- The navbar adapts to smaller screen sizes by including a mobile menu button (
MenuandXicons from Lucide). - When toggled, the menu displays navigation links and actions in a user-friendly way for mobile devices.
 
 - The navbar adapts to smaller screen sizes by including a mobile menu button (
 
   <Button
     variant="ghost"
     onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
     className="inline-flex items-center justify-center p-2"
   >
     {isMobileMenuOpen ? <X className="h-6 w-6" /> : <Menu className="h-6 w-6" />}
   </Button>
- 
Desktop and Mobile Navigation Links:
- Provides social links (e.g., LinkedIn, Dribbble, Instagram) as well as buttons for copying an email or accessing a CV.
 - These are conditionally rendered based on screen size using Tailwind CSS’s utility classes (e.g., 
hidden md:flex). 
 
HeroSection Component
Imports
import { Button } from "@/components/ui/button";
import Image from "next/image";
import React from "react";
- 
Button Component: The button is imported from a custom UI library (
@/components/ui/button). This approach indicates a modular design for reusability across the app. - 
Image Component: The 
Imagecomponent is part of Next.js. It’s a powerful tool for optimizing images in web applications, providing features like lazy loading, responsive sizing, and automatic format selection (e.g., WebP). - React: A foundational import for all React components.
 
HeroSection Function
function HeroSection() {
  return (
    <section className="grid min-h-[70vh] place-content-center rounded-b-[100px] bg-stone-400/50 p-10 text-center">
      ...
    </section>
  );
}
Details on Styling the Section
<section className="grid min-h-[70vh] place-content-center rounded-b-[100px] bg-stone-400/50 p-10 text-center">
- 
grid: Establishes a grid layout. Combined withplace-content-center, it centers the content both horizontally and vertically. - 
min-h-[70vh]: Ensures the hero section takes up at least 70% of the viewport height. - 
rounded-b-[100px]: Applies a custom, large rounded border radius to the bottom, adding a soft curve for a modern aesthetic. - 
bg-stone-400/50: Sets a semi-transparent light gray background with Tailwind's opacity feature (/50). - 
p-10: Adds padding around the section. - 
text-center: Centers all text content inside this section. 
Image Component
<Image
  width={300}
  height={300}
  src="/assets/images/images.jpeg"
  alt="Profile"
  className="mx-auto mb-4 h-40 w-40 rounded-full object-cover"
/>
- 
Optimization: The 
Imagecomponent ensures better performance through optimized loading and resizing. - 
Props:
- 
src: Path to the image. Here, it’s served from/assets/images/images.jpeg. - 
alt: Alt text for accessibility and SEO purposes. - 
widthandheight: Fixed dimensions for better performance. 
 - 
 - 
Styling:
- 
mx-auto: Horizontally centers the image. - 
h-40 w-40: Defines fixed height and width (10rem each). - 
rounded-full: Creates a circular image. - 
object-cover: Ensures the image scales without distortion. 
 - 
 
Heading
<h1 className="mb-4 text-4xl font-bold">
  Building digital
  <br />
  products, brands, and
  <br />
  experience.
</h1>
- 
mb-4: Adds margin-bottom for spacing. - 
text-4xl: Sets a large font size. - 
font-bold: Applies bold styling for emphasis. - 
Text Layout: The use of 
<br />tags breaks the text into multiple lines, creating a structured and visually appealing layout. 
Button Component
<Button className="mt-6 p-8 text-2xl">Latest Work</Button>
- Custom Button: The button component, likely styled and built within your custom library, is reusable.
 - 
Props and Styling:
- 
mt-6: Adds top margin for spacing. - 
p-8: Applies generous padding for a clickable and prominent button. - 
text-2xl: Enlarges the text for better readability. 
 - 
 - Text: The button directs users to view the "Latest Work," potentially linking to a portfolio or case studies.
 
BrandSection Component
Imports
import Image from "next/image";
import React from "react";
- 
Image: Next.js's 
Imagecomponent ensures efficient image rendering with features like lazy loading and responsive sizing. - React: Essential for defining React components.
 
BrandSection Function
function BrandSection() {
  ...
  return (
    <section className="relative z-10 my-20 rounded-b-[100px] bg-white px-10 py-20">
      ...
    </section>
  );
}
Brands Array
const brands = [
  { name: "National Bank of Canada", link: "/assets/images/national-bank-of-canada-logo.png" },
  { name: "Matter", link: "/assets/images/matter.png" },
  { name: "Coca-Cola", link: "/assets/images/Coca-Cola.png" },
  { name: "Adobe", link: "/assets/images/Adobe-logo.png" },
  { name: "Subway", link: "/assets/images/subway-logo.png" },
  { name: "Code Academy", link: "/assets/images/code-academy.png" },
];
- 
Structure: Each brand has a 
nameand alinkto the corresponding image file. - Scalability: Adding or removing brands is easy—just update the array.
 
Styling the Section
<section className="relative z-10 my-20 rounded-b-[100px] bg-white px-10 py-20">
- 
relative z-10: Positions the section above other elements for proper layering. - 
my-20: Adds vertical margin for spacing. - 
rounded-b-[100px]: Applies a curved bottom border for a smooth, modern look. - 
bg-white: Sets a clean white background. - 
px-10 py-20: Adds padding for a well-spaced layout. 
Grid Layout
<div className="grid grid-cols-6 items-center justify-items-center gap-8 opacity-50">
- 
grid: Establishes a grid layout for displaying the logos. - 
grid-cols-6: Divides the grid into six equal columns, ensuring each brand gets its own space. - 
items-center: Vertically centers the grid items. - 
justify-items-center: Horizontally centers the grid items. - 
gap-8: Adds consistent spacing between the items. - 
opacity-50: Reduces the opacity, giving the logos a subdued, professional look. 
Dynamic Rendering of Brands
{brands.map((brand, index) => (
  <div key={index} className="text-sm font-medium">
    <Image
      width={100}
      height={100}
      src={brand.link}
      alt={brand.name}
      className="mx-auto mb-4"
    />
  </div>
))}
- 
Mapping: The 
brandsarray is iterated withmap()to render each brand dynamically. - 
Key Prop: The 
keyprop (index) ensures React efficiently updates the DOM. - 
Image Component:
- 
src: Specifies the image path for each logo. - 
alt: Improves accessibility and SEO with descriptive alt text. - 
widthandheight: Ensures consistent logo sizing (100x100 px). - 
className: Centers the image and adds a small margin at the bottom (mx-auto mb-4). 
 - 
 - 
Wrapper Div: Includes 
text-smfor small text size andfont-mediumfor medium-weight font (if text is needed later). 
ServiceSection Component
Imports
import { Card } from "@/components/ui/card";
import React from "react";
- 
Card: A reusable UI component likely styled for consistent card-based layouts. This simplifies the process of rendering each service as a visually cohesive block. - 
React: Required to define and use React components. 
ServiceSection Function
function ServiceSection() {
  ...
  return (
    <section className="mb-20 py-52 px-20 w-full bg-stone-400/20 -my-52">
      ...
    </section>
  );
}
Services Array
const services = [
  {
    title: "UX & UI",
    description: "Designing interfaces that are intuitive, efficient, and enjoyable to use",
    icon: "🎨",
  },
  {
    title: "Web & Mobile App",
    description: "Transforming ideas into exceptional web and mobile app experiences",
    icon: "📱",
  },
  {
    title: "Design & Creative",
    description: "Crafting visually stunning designs that connect with your audience",
    icon: "✨",
  },
  {
    title: "Development",
    description: "Bringing your vision to life with the latest technology and design trends",
    icon: "💻",
  },
];
- 
Structure: Each service has a 
title,description, and aniconto visually represent the service. - Purpose: Makes the component dynamic and scalable—adding or updating services only requires modifying this array.
 
Styling the Section
<section className="mb-20 py-52 px-20 w-full bg-stone-400/20 -my-52">
- 
mb-20: Adds vertical margin at the bottom for spacing between sections. - 
py-52 px-20: Provides generous padding for a spacious layout. - 
w-full: Ensures the section spans the full width of the viewport. - 
bg-stone-400/20: Applies a semi-transparent background with a soft stone-gray tone. - 
-my-52: Adds a negative margin to overlap the previous or next sections slightly for a layered effect. 
Heading and Subheading
<div className="mb-16 text-center">
  <h2 className="mb-2 text-3xl font-bold">
    Collaborate with brands and agencies
  </h2>
  <p className="text-xl text-gray-600">to create impactful results.</p>
</div>
- 
Heading (
h2): Styled withtext-3xlfor a prominent font size andfont-boldfor emphasis. - 
Subheading (
p): Smaller (text-xl) and styled withtext-gray-600for a subtle, secondary emphasis. 
Grid Layout for Services
<div className="grid sm:grid-cols-4 gap-8">
- 
grid: Enables a grid layout for the cards. - 
sm:grid-cols-4: Defines a 4-column grid on small screens and larger. - 
gap-8: Adds consistent spacing between grid items. 
Dynamic Rendering of Services
{services.map((service, index) => (
  <Card key={index} className="p-6 bg-stone-400/20">
    <div className="mb-4 text-2xl">{service.icon}</div>
    <h3 className="mb-2 text-lg font-semibold">{service.title}</h3>
    <p className="text-sm text-gray-600">{service.description}</p>
  </Card>
))}
- 
Mapping: Each service is rendered dynamically using the 
.map()function. - 
Card Component: 
- 
Wrapper (
Card): Styled withp-6for padding andbg-stone-400/20for a consistent background. - 
Icon: Displayed in 
text-2xlfor a visually striking representation. - 
Title: Styled with 
text-lgandfont-semiboldfor emphasis. - 
Description: Styled with 
text-smandtext-gray-600for readability and a softer tone. 
 - 
Wrapper (
 - 
Key Prop: Ensures each card has a unique identifier (
index) for efficient rendering. 
ContactSection Component
Imports
import { Button } from "@/components/ui/button";
import { HandshakeIcon } from "lucide-react";
import React from "react";
- 
Button: A customizable button component for creating consistent, styled buttons. - 
HandshakeIcon: An icon imported from thelucide-reactlibrary to visually enhance the section. - 
React: Enables the use of JSX to build the component. 
ContactSection Function
function ContactSection() {
  ...
  return (
    <section className="-my-40 rounded-t-[100px] bg-white p-28 text-center">
      ...
    </section>
  );
}
- The function defines the ContactSection component.
 - The 
sectionelement serves as the container for the entire component, styled with Tailwind CSS classes. 
Styling the Section
<section className="-my-40 rounded-t-[100px] bg-white p-28 text-center">
- 
-my-40: Adds negative vertical margins to overlap the previous section for a seamless flow. - 
rounded-t-[100px]: Gives the section a unique curved top with a large border radius. - 
bg-white: Sets a clean, white background. - 
p-28: Adds ample padding to create a spacious layout. - 
text-center: Centers all text and content horizontally. 
Icon Wrapper
<div className="mb-8 grid place-content-center">
  <div className="rounded-full bg-muted p-8">
    <HandshakeIcon size={50} />
  </div>
</div>
- 
Outer Wrapper:
- 
mb-8: Adds a margin at the bottom to separate the icon from the heading. - 
grid place-content-center: Centers the icon wrapper both vertically and horizontally. 
 - 
 - 
Inner Wrapper:
- 
rounded-full: Ensures the icon container is perfectly circular. - 
bg-muted: Applies a muted background color, likely defined in the theme. - 
p-8: Adds padding inside the circular wrapper for a spacious look. 
 - 
 - 
HandshakeIcon: The icon is rendered with a size of 50px, making it bold and noticeable. 
Heading
<h2 className="mb-8 text-3xl font-bold">
  Tell me about your next
  <br />
  project
</h2>
- 
mb-8: Creates separation from the buttons below. - 
text-3xl: Sets a large, attention-grabbing font size. - 
font-bold: Enhances readability by making the text bold 
Footer Component
Imports
import React from "react";
- 
React: This import enables JSX and is essential for creating React components. 
Footer Function
function Footer() {
  ...
  return (
    <footer className="mt-20 flex items-center justify-between text-sm text-gray-600">
      ...
    </footer>
  );
}
- The function defines the Footer component.
 - The 
footerelement serves as the container for the footer content and is styled with Tailwind CSS classes. 
Styling the Footer
<footer className="mt-20 flex items-center justify-between text-sm text-gray-600">
- 
mt-20: Adds a margin-top of20units, creating space between the footer and the content above it. - 
flex: Utilizes Flexbox for layout, allowing easy alignment of child elements. - 
items-center: Vertically centers the content inside the footer. - 
justify-between: Distributes space between the child elements, placing one at the left and the other at the right. - 
text-sm: Sets a smaller text size for the footer content. - 
text-gray-600: Applies a medium gray color to the text for a subtle and soft appearance. 
Content in the Footer
- Copyright Text
 
   <div>© 2024 All rights reserved.</div>
- Displays the copyright text with the year 
2024. - 
div: A simple container for the copyright notice. 
- Navigation Links
 
   <nav className="space-x-4">
     <Link href="#">HeadStarter</Link>
   </nav>
- 
nav: A semantic HTML element for navigation links. In this case, it contains only one link. - 
space-x-4: Adds horizontal spacing between elements within thenavcontainer (though there's only one link here, it can accommodate additional links with equal spacing). - 
<Link>: A React component used for client-side navigation, though thehref="#"here doesn't direct to any specific page. 
Default Export
export default Footer;
Key Features
- 
Simple Layout:
- The footer is divided into two main sections: the copyright notice on the left and a navigation link on the right, using Flexbox for alignment.
 
 - 
Small Text for Footer:
- The text is styled in a smaller, subtle gray, ensuring that the footer does not distract from the main content but remains legible.
 
 - 
Extensibility:
- The navigation section (
<nav>) has space for additional links if needed, making it easy to expand in the future. 
 - The navigation section (
 
Best Practices
- Use server components by default
 - Implement lazy loading for heavy components
 - Optimize images with Next/Image
 - Leverage built-in TypeScript support
 - Modularize your code
 
Performance Optimization Techniques
- Use 
next/imagefor automatic image optimization - Implement code splitting
 - Utilize static generation for non-dynamic content
 - Enable incremental static regeneration
 
Recommended Packages
- Tailwind CSS for styling
 - Lucide React Icons for icons
 - Shadcn UI for component library
 
Deployment
- Vercel (recommended)
 - Netlify
 - GitHub Pages
 
Learning Resources
- NextJS Official Documentation
 - React Documentation
 - Vercel Deployment Guides
 
              
    
Top comments (0)