Skip to content

A cutting-edge, production-ready portfolio website built with Next.js 15, React 18, TypeScript, TailwindCSS, and Framer Motion. This project showcases modern web development practices, including server-side rendering, API routes, email functionality, analytics integration, internationalization (i18n), and stunning animations.

License

Notifications You must be signed in to change notification settings

arnobt78/MyPortfolio--NextJS-FullStack

Repository files navigation

Modern Portfolio Website - Next.js FullStack Project (My Personal Official Portfolio)

License: MIT Next.js React TypeScript TailwindCSS Framer Motion Shadcn UI i18next

A cutting-edge, production-ready portfolio website built with Next.js 15, React 18, TypeScript, TailwindCSS, and Framer Motion. This project showcases modern web development practices, including server-side rendering, API routes, email functionality, analytics integration, internationalization (i18n), and stunning animations.

Author: Arnob Mahmud | License: MIT

🌟 Open Source Project - This is an open-source project. Feel free to use, enhance, and extend this project to the next level! Contributions, improvements, forks, and stars are always welcome. Together, we can make this portfolio template even better!

Screenshot 2025-10-23 at 13 47 13 Screenshot 2025-10-23 at 13 47 33 Screenshot 2025-10-23 at 13 48 00 Screenshot 2025-10-23 at 13 49 36 Screenshot 2025-10-23 at 13 49 49


πŸ“‹ Table of Contents


🎯 Overview

This is a production-ready, modern portfolio website that demonstrates best practices in Next.js development. It features a complete full-stack implementation with server-side rendering, API routes, email functionality, multi-language support, and professional animations.

Key Highlights

  • Next.js 15 with App Router and Server Components
  • TypeScript for type safety throughout the codebase
  • Internationalization (i18n) - English and German support
  • Email Integration - Contact form with auto-reply functionality
  • Analytics - Google Analytics 4 and Vercel Analytics
  • SEO Optimized - Meta tags, Open Graph, structured data, sitemap
  • Responsive Design - Mobile-first approach with TailwindCSS
  • Smooth Animations - Framer Motion for page transitions and interactions
  • Modern UI Components - Radix UI and Shadcn UI components
  • Performance Optimized - Image optimization, lazy loading, code splitting

✨ Features

Core Features

  • ⚑ Next.js 15 with App Router and Server Components
  • 🎨 Modern UI/UX with TailwindCSS and Shadcn UI components
  • 🎭 Smooth Animations powered by Framer Motion
  • πŸ“± Fully Responsive design for all devices
  • 🌍 Internationalization - English and German language support
  • πŸ”’ Type-Safe with TypeScript
  • πŸ“§ Contact Form with email notifications and auto-reply
  • πŸ“Š Analytics with Google Analytics & Vercel Analytics
  • 🎯 SEO Optimized with meta tags, Open Graph, and structured data
  • β™Ώ Accessible components following WCAG guidelines
  • πŸš€ Fast Performance with optimized images and lazy loading
  • πŸ€– AI Chatbot Widget integration for interactive FAQ

Advanced Features

  • πŸŽͺ Typewriter Effect on homepage hero section
  • 🎠 Project Carousel with Swiper.js
  • πŸ“‹ Grid/List View Toggle for projects showcase
  • πŸ“ˆ Animated Counter for statistics
  • 🎬 Page Transitions with smooth animations
  • πŸͺœ Stair Transition Effect between pages
  • πŸ“œ Scroll-to-Top button functionality
  • 🎯 Custom Tooltips for enhanced UX
  • πŸ“± Mobile Navigation with hamburger menu
  • πŸ”„ Loading States for async operations
  • 🌐 Language Switcher with cookie persistence
  • πŸ“„ Dynamic Sitemap generation

πŸ›  Technology Stack

Frontend

  • Framework: Next.js 15.5.9 (React 18.3.1)
  • Language: TypeScript 5.7.2
  • Styling: TailwindCSS 3.4.17
  • Animations: Framer Motion 12.23.24
  • UI Components: Radix UI, Shadcn UI
  • Icons: React Icons 5.5.0, Lucide React 0.546.0
  • Carousel: Swiper 12.0.2
  • Internationalization: i18next 25.8.0, react-i18next 16.5.3

Backend & APIs

  • Runtime: Node.js
  • Email Service: Nodemailer 7.0.9
  • HTTP Client: Axios 1.12.2
  • Email Templates: @react-email/render 1.4.0
  • Alternative Email: Resend 6.2.0

Analytics & Monitoring

  • Web Analytics: Google Analytics 4
  • Performance: Vercel Analytics 1.5.0

Development Tools

  • Package Manager: npm/yarn/pnpm
  • Linting: ESLint 8.57.0
  • Build Tool: Turbopack (Next.js 15)
  • Deployment: Vercel

πŸ“ Project Structure

portfolio-arnob-new/
β”œβ”€β”€ app/                          # Next.js App Router
β”‚   β”œβ”€β”€ api/                      # API Routes
β”‚   β”‚   β”œβ”€β”€ send-email/          # Main contact form handler
β”‚   β”‚   β”‚   └── route.ts
β”‚   β”‚   └── send-auto-reply/     # Auto-reply email handler
β”‚   β”‚       └── route.ts
β”‚   β”œβ”€β”€ about/                    # About page
β”‚   β”‚   └── page.tsx
β”‚   β”œβ”€β”€ contact/                  # Contact page
β”‚   β”‚   └── page.tsx
β”‚   β”œβ”€β”€ faq/                      # FAQ page
β”‚   β”‚   └── page.tsx
β”‚   β”œβ”€β”€ privacy/                  # Privacy policy page
β”‚   β”‚   └── page.tsx
β”‚   β”œβ”€β”€ resume/                   # Resume/CV page
β”‚   β”‚   └── page.tsx
β”‚   β”œβ”€β”€ services/                 # Services offered page
β”‚   β”‚   └── page.tsx
β”‚   β”œβ”€β”€ terms/                    # Terms of service page
β”‚   β”‚   └── page.tsx
β”‚   β”œβ”€β”€ work/                     # Portfolio/Projects page
β”‚   β”‚   └── page.tsx
β”‚   β”œβ”€β”€ globals.css              # Global styles & animations
β”‚   β”œβ”€β”€ layout.tsx               # Root layout with metadata
β”‚   β”œβ”€β”€ page.tsx                 # Homepage
β”‚   └── sitemap.ts               # Dynamic sitemap generation
β”‚
β”œβ”€β”€ components/                   # React Components
β”‚   β”œβ”€β”€ pages/                   # Page-specific components
β”‚   β”‚   β”œβ”€β”€ AboutPage.tsx       # About page content
β”‚   β”‚   β”œβ”€β”€ ContactPage.tsx     # Contact form with validation
β”‚   β”‚   β”œβ”€β”€ FAQPage.tsx         # FAQ accordion
β”‚   β”‚   β”œβ”€β”€ HomePage.tsx        # Hero section with typewriter
β”‚   β”‚   β”œβ”€β”€ PrivacyPage.tsx     # Privacy policy content
β”‚   β”‚   β”œβ”€β”€ ResumePage.tsx      # Tabbed resume/skills section
β”‚   β”‚   β”œβ”€β”€ ServicesPage.tsx    # Service cards grid
β”‚   β”‚   β”œβ”€β”€ TermsPage.tsx       # Terms of service content
β”‚   β”‚   └── WorkPage.tsx        # Projects showcase with carousel
β”‚   β”‚
β”‚   β”œβ”€β”€ ui/                      # Reusable UI components (Shadcn)
β”‚   β”‚   β”œβ”€β”€ accordion.tsx       # FAQ accordion component
β”‚   β”‚   β”œβ”€β”€ alert.tsx          # Alert/notification component
β”‚   β”‚   β”œβ”€β”€ button.tsx          # Custom button variants
β”‚   β”‚   β”œβ”€β”€ card.tsx            # Card component
β”‚   β”‚   β”œβ”€β”€ dropdown-menu.tsx  # Dropdown menu
β”‚   β”‚   β”œβ”€β”€ input.tsx          # Form input field
β”‚   β”‚   β”œβ”€β”€ scroll-area.tsx    # Custom scrollbar
β”‚   β”‚   β”œβ”€β”€ select.tsx          # Dropdown select
β”‚   β”‚   β”œβ”€β”€ sheet.tsx          # Mobile navigation sheet
β”‚   β”‚   β”œβ”€β”€ tabs.tsx            # Tab navigation
β”‚   β”‚   β”œβ”€β”€ textarea.tsx        # Multi-line input
β”‚   β”‚   └── tooltip.tsx         # Tooltip component
β”‚   β”‚
β”‚   β”œβ”€β”€ LanguageSelector/        # Language switcher component
β”‚   β”‚   └── LanguageSelector.tsx
β”‚   β”‚
β”‚   β”œβ”€β”€ Footer.tsx               # Footer with links
β”‚   β”œβ”€β”€ GoogleAnalytics.tsx      # GA4 integration
β”‚   β”œβ”€β”€ Header.tsx                # Main navigation header
β”‚   β”œβ”€β”€ I18nProvider.tsx         # i18n provider wrapper
β”‚   β”œβ”€β”€ MobileNav.tsx             # Mobile hamburger menu
β”‚   β”œβ”€β”€ Nav.tsx                   # Desktop navigation links
β”‚   β”œβ”€β”€ PageTransition.tsx        # Page animation wrapper
β”‚   β”œβ”€β”€ Photo.tsx                 # Profile photo with effects
β”‚   β”œβ”€β”€ ScrollToTop.tsx           # Scroll-to-top button
β”‚   β”œβ”€β”€ Social.tsx                # Social media links
β”‚   β”œβ”€β”€ Stairs.tsx                # Stair animation component
β”‚   β”œβ”€β”€ StairTranstion.tsx       # Stair transition wrapper
β”‚   └── Stats.tsx                 # Animated statistics counter
β”‚
β”œβ”€β”€ context/                      # React Context Providers
β”‚   └── LanguageContext.tsx      # Language state management
β”‚
β”œβ”€β”€ hooks/                        # Custom React Hooks
β”‚   └── useTypewriter.ts         # Typewriter text effect hook
β”‚
β”œβ”€β”€ lib/                          # Utility functions & configurations
β”‚   β”œβ”€β”€ i18n.ts                  # i18next configuration
β”‚   β”œβ”€β”€ language-cookie.ts       # Cookie-based language persistence
β”‚   β”œβ”€β”€ language-detection.ts    # Browser language detection
β”‚   β”œβ”€β”€ translations.ts          # Translation strings (en/de)
β”‚   └── utils.ts                 # Helper functions (cn, etc.)
β”‚
β”œβ”€β”€ public/                       # Static assets
β”‚   β”œβ”€β”€ assets/                  # Images, icons, etc.
β”‚   β”‚   β”œβ”€β”€ resume/             # Resume-related assets
β”‚   β”‚   β”œβ”€β”€ skills/             # Skill icons
β”‚   β”‚   └── work/               # Project screenshots
β”‚   β”œβ”€β”€ favicon.ico             # Site favicon
β”‚   β”œβ”€β”€ photo.png               # Profile photo
β”‚   └── robots.txt              # SEO robots file
β”‚
β”œβ”€β”€ .env.local                    # Environment variables (not in repo)
β”œβ”€β”€ .eslintignore                # ESLint ignore rules
β”œβ”€β”€ .eslintrc.json               # ESLint configuration
β”œβ”€β”€ .gitignore                   # Git ignore rules
β”œβ”€β”€ global.d.ts                  # Global TypeScript declarations
β”œβ”€β”€ LICENSE                      # MIT License
β”œβ”€β”€ middleware.ts                # Next.js middleware (language detection)
β”œβ”€β”€ next.config.js               # Next.js configuration
β”œβ”€β”€ package.json                 # Project dependencies
β”œβ”€β”€ postcss.config.mjs           # PostCSS configuration
β”œβ”€β”€ tailwind.config.js           # TailwindCSS configuration
β”œβ”€β”€ tsconfig.json                # TypeScript configuration
└── README.md                    # This file

πŸš€ Installation & Setup

Prerequisites

Before you begin, ensure you have the following installed:

  • Node.js 18.17 or higher (Download)
  • npm (comes with Node.js) or yarn or pnpm
  • Git for version control
  • A Gmail account (for email functionality)
  • A Google Analytics 4 account (optional, for analytics)

Step 1: Clone the Repository

# Clone using HTTPS
git clone https://github.com/arnobt78/MyPortfolio--NextJS-FullStack-Website.git

# Or clone using SSH
git clone git@github.com:arnobt78/MyPortfolio--NextJS-FullStack-Website.git

# Navigate to project directory
cd MyPortfolio--NextJS-FullStack-Website

Step 2: Install Dependencies

# Using npm
npm install

# Or using yarn
yarn install

# Or using pnpm
pnpm install

This will install all the required dependencies listed in package.json.


πŸ” Environment Variables

Create a .env.local file in the root directory of your project. This file contains sensitive information and should never be committed to version control.

Required Environment Variables

# =================================
# EMAIL CONFIGURATION (Required)
# =================================

# Your Gmail address (used for sending/receiving contact form emails)
EMAIL_USER=your-email@gmail.com

# Gmail App Password (NOT your regular Gmail password)
# Generate this from: https://myaccount.google.com/apppasswords
EMAIL_PASS=your-16-character-app-password


# =================================
# GOOGLE ANALYTICS (Optional)
# =================================

# Google Analytics 4 Measurement ID
# Find this in GA4: Admin > Data Streams > Your Stream
NEXT_PUBLIC_GA_MEASUREMENT_ID=G-XXXXXXXXXX


# =================================
# CHATBOT WIDGET (Optional)
# =================================

# Chatbot widget URL (for embedded chatbot functionality)
# In production: Your chatbot deployment URL
# In development: http://localhost:3000 (if running locally)
NEXT_PUBLIC_CHATBOT_URL=https://your-chatbot-url.vercel.app


# =================================
# SEO & VERIFICATION (Optional)
# =================================

# Google Search Console verification code
# Get from: https://search.google.com/search-console
NEXT_PUBLIC_GOOGLE_SITE_VERIFICATION=your-verification-code

# Bing Webmaster Tools verification code
# Get from: https://www.bing.com/webmasters
NEXT_PUBLIC_BING_SITE_VERIFICATION=your-verification-code

How to Obtain Environment Variables

1. EMAIL_USER (Your Gmail Address)

  • Simply use your existing Gmail address
  • Example: your-email@gmail.com

2. EMAIL_PASS (Gmail App Password)

Important: This is NOT your regular Gmail password. It's a special 16-character password generated by Google.

Steps to generate:

  1. Go to Google Account Settings
  2. Click on Security in the left sidebar
  3. Enable 2-Step Verification (required for App Passwords)
  4. Once 2FA is enabled, return to Security settings
  5. Scroll down to App passwords (may appear after 2FA setup)
  6. Click App passwords
  7. Select Mail as the app
  8. Select Other (Custom name) as the device
  9. Enter a name like "Portfolio Website"
  10. Click Generate
  11. Copy the 16-character password (format: xxxx xxxx xxxx xxxx)
  12. Remove spaces and use it as EMAIL_PASS

Example: abcdwxyzpqrsjklm

Security Note: Never share your app password or commit it to version control!

3. NEXT_PUBLIC_GA_MEASUREMENT_ID (Google Analytics - Optional)

Steps to get your Measurement ID:

  1. Go to Google Analytics
  2. Create an account if you don't have one
  3. Create a new GA4 Property (not Universal Analytics)
  4. Navigate to Admin (gear icon at bottom left)
  5. Under Property, click Data Streams
  6. Click on your Web stream
  7. Find Measurement ID (format: G-XXXXXXXXXX)
  8. Copy and paste into .env.local

Example: G-7CTQNDTW0G

4. NEXT_PUBLIC_CHATBOT_URL (Chatbot Widget - Optional)

If you're using the embedded chatbot widget:

  • Production: Your chatbot deployment URL (e.g., https://portfolio-chatbot-widget.vercel.app)
  • Development: http://localhost:3000 (if running chatbot locally)

5. NEXT_PUBLIC_GOOGLE_SITE_VERIFICATION (Google Search Console - Optional)

Steps:

  1. Go to Google Search Console
  2. Add your property (website URL)
  3. Choose HTML tag verification method
  4. Copy the content value from the meta tag
  5. Add to .env.local

Example: abc123def456ghi789

6. NEXT_PUBLIC_BING_SITE_VERIFICATION (Bing Webmaster - Optional)

Steps:

  1. Go to Bing Webmaster Tools
  2. Add your site
  3. Choose Meta tag verification
  4. Copy the content value
  5. Add to .env.local

Security Best Practices

⚠️ Never commit .env.local to Git!

The .gitignore file is already configured to exclude:

  • .env.local
  • .env.development.local
  • .env.test.local
  • .env.production.local

If you accidentally commit sensitive data:

  1. Remove it from Git history immediately
  2. Regenerate all compromised credentials
  3. Update .env.local with new credentials
  4. Rotate any exposed API keys or passwords

πŸƒ How to Run

Development Mode

Start the development server with hot-reload:

# Using npm
npm run dev

# Or using yarn
yarn dev

# Or using pnpm
pnpm dev

The application will be available at:

Note: The project uses Turbopack for faster development builds.

Clean Development Mode

If you encounter cache issues, run:

npm run dev:clean

This removes the .next folder and starts a fresh development build.

Production Build

Build the application for production:

# Build the project
npm run build

# Start production server
npm run start

Linting

Check code quality and fix issues:

npm run lint

🌍 Internationalization (i18n)

This project includes full internationalization support with English and German languages.

How It Works

  1. Language Detection:

    • Checks browser language preference
    • Falls back to cookie-stored preference
    • Defaults to English if no preference found
  2. Language Persistence:

    • Stores selected language in cookies
    • Persists across page reloads
    • Uses selectedLanguage cookie key
  3. Translation System:

    • Uses i18next and react-i18next
    • Translation strings stored in lib/translations.ts
    • Supports nested keys (e.g., home.hello)

Adding a New Language

  1. Add translations to lib/translations.ts:
export const translations = {
  en: {
    "nav.home": "Home",
    // ... existing translations
  },
  de: {
    "nav.home": "Startseite",
    // ... existing translations
  },
  // Add new language
  fr: {
    "nav.home": "Accueil",
    // ... add all translation keys
  },
};
  1. Update language types:
// In context/LanguageContext.tsx
export type Language = "en" | "de" | "fr"; // Add new language

// In middleware.ts
const supportedLanguages = ["en", "de", "fr"]; // Add new language
  1. Update i18n configuration:
// In lib/i18n.ts
resources: {
  en: { translation: translations.en },
  de: { translation: translations.de },
  fr: { translation: translations.fr }, // Add new language
},

Using Translations in Components

import { useLanguage } from "@/context/LanguageContext";

function MyComponent() {
  const { t } = useLanguage();

  return (
    <div>
      <h1>{t("home.hello")}</h1>
      <p>{t("home.bio")}</p>
    </div>
  );
}

Language Switcher Component

The LanguageSelector component provides a dropdown to switch languages:

import { LanguageSelector } from "@/components/LanguageSelector/LanguageSelector";

<LanguageSelector />;

🧩 Components Overview

Page Components (components/pages/)

1. HomePage.tsx

Purpose: Landing page hero section with introduction and call-to-action.

Key Features:

  • Typewriter effect for name animation
  • Profile photo with circular border effect
  • Download resume button
  • Social media links
  • Animated statistics counter

Code Example:

import HomePage from "@/components/pages/HomePage";

export default function Home() {
  return <HomePage />;
}

Reusability:

// Extract typewriter effect
import { useTypewriter } from "@/hooks/useTypewriter";

const { displayText, isComplete } = useTypewriter({
  text: "Your Name",
  speed: 200,
  delay: 2000,
});

Customization:

  • Edit personal information in the component
  • Update resume link in the Button href
  • Modify typewriter text in useTypewriter hook
  • Change animation delays in style props

2. ServicesPage.tsx

Purpose: Display services offered in a grid layout with hover effects.

Key Features:

  • Responsive grid (1 column mobile, 2 columns desktop)
  • Hover effects with color transitions
  • Arrow icon that rotates on hover
  • Service cards with numbering
  • Technology stack display

Data Structure:

interface Service {
  num: string; // Service number (e.g., "01")
  titleKey: string; // Translation key for title
  descriptionKey: string; // Translation key for description
  stack: ServiceStack[]; // Technologies used
  href: string; // Link to contact page
}

How to Add/Edit Services:

const services: Service[] = [
  {
    num: "01",
    titleKey: "services.01.title",
    descriptionKey: "services.01.description",
    stack: [{ name: "React" }, { name: "Next.js" }],
    href: "/contact",
  },
  // Add more services here
];

Reusability in Other Projects:

  • Extract the service card into a separate component
  • Pass services array as props
  • Style using Tailwind utility classes
  • Perfect for service pages, product showcases, or feature lists

3. ResumePage.tsx

Purpose: Tabbed interface displaying resume, experience, education, and skills.

Key Features:

  • Tab navigation (About, Experience, Education, Skills)
  • Scrollable content areas
  • Icon-based skill display with tooltips
  • Timeline cards for experience/education
  • Multi-language support

Data Structures:

// About section
interface InfoItem {
  fieldName: string;
  fieldValue: string;
}

// Experience section
interface ExperienceItem {
  company: string;
  position: string;
  duration: string;
}

// Skills section
interface SkillItem {
  icon: JSX.Element;
  name: string;
}

How to Update Content:

  1. Add Experience:
const experience: ExperienceData = {
  items: [
    {
      company: "Your Company",
      position: "Your Position",
      duration: "Jan 2024 - Present",
    },
  ],
};
  1. Add Skills:
import { FaReact } from "react-icons/fa";

const skills: SkillsData = {
  skillList: [
    { icon: <FaReact />, name: "React.js" },
    // Add more skills
  ],
};

Reusability:

  • Convert to a generic tabbed component
  • Pass data as props
  • Use in team pages, product showcases, or documentation sites

4. WorkPage.tsx

Purpose: Showcase portfolio projects with grid/list view toggle.

Key Features:

  • Swiper carousel for image slideshow
  • Grid view (original) and list view modes
  • Project filtering by category
  • Live demo and GitHub repository links
  • Technology stack display
  • Multi-language project descriptions

Project Data Structure:

interface Project {
  num: string; // Project number
  category: string; // Frontend/Fullstack/Backend
  title: string; // Translation key for title
  description: string; // Translation key for description
  stack: ProjectStack[]; // Technologies used
  image: string; // Screenshot path
  live: string; // Live demo URL
  github: string; // GitHub repository URL
}

How to Add New Projects:

const projects: Project[] = [
  {
    num: "01",
    category: "Fullstack",
    title: "work.project.01.title", // Translation key
    description: "work.project.01.description", // Translation key
    stack: [{ name: "Next.js" }, { name: "TypeScript" }],
    image: "/assets/work/project-image.png",
    live: "https://your-live-demo.com",
    github: "https://github.com/yourusername/repo",
  },
];

View Mode Toggle:

  • Grid View: Carousel with single project focus
  • List View: All projects in scrollable list

Reusability:

  • Perfect for freelancer portfolios
  • Agency project showcases
  • Product galleries
  • Case study presentations
  • E-commerce product listings

5. ContactPage.tsx

Purpose: Contact form with email functionality and validation.

Key Features:

  • Form validation (required fields, email format)
  • Loading states during submission
  • Success/error alerts with icons
  • Auto-reply email to user
  • Smooth scroll to alert message
  • Contact information display
  • Copy-to-clipboard functionality
  • Multi-language support

Form Data Structure:

interface FormData {
  fullname: string;
  email: string;
  message: string;
}

API Integration:

// Send main email
const response = await axios.post("/api/send-email", formData);

// Send auto-reply
const autoReply = await axios.post("/api/send-auto-reply", formData);

Error Handling:

  • Network errors
  • Authentication errors
  • Validation errors
  • Timeout errors

Reusability:

  • Extract form into separate component
  • Add file upload capability
  • Integrate with other backend services (Firebase, Supabase)
  • Add CAPTCHA for spam protection
  • Use in newsletter signups, feedback forms, or support tickets

6. FAQPage.tsx

Purpose: Frequently Asked Questions page with accordion interface.

Key Features:

  • Accordion component for expandable Q&A
  • Multi-language support
  • Smooth expand/collapse animations
  • Accessible keyboard navigation

Data Structure:

interface FAQItem {
  question: string; // Translation key
  answer: string; // Translation key
}

How to Add FAQs:

const faqData: FAQItem[] = [
  {
    question: t("faq.01.question"),
    answer: t("faq.01.answer"),
  },
  // Add more FAQs
];

Reusability:

  • Use in help centers
  • Documentation sites
  • Product pages
  • Support pages

UI Components (components/ui/)

These are Shadcn UI components - fully customizable, accessible, and ready to use.

button.tsx

Versatile button component with multiple variants.

Variants:

  • default - Primary accent button
  • destructive - Red danger button
  • outline - Bordered button
  • secondary - Muted secondary button
  • ghost - Transparent button
  • link - Link-styled button

Sizes:

  • default - Standard size
  • sm - Small button
  • lg - Large button
  • icon - Square icon button

Usage:

import { Button } from "@/components/ui/button";

<Button variant="default" size="lg">
  Click Me
</Button>

<Button variant="outline" size="sm">
  Secondary Action
</Button>

input.tsx

Styled text input field with focus states.

Usage:

import { Input } from "@/components/ui/input";

<Input
  type="email"
  placeholder="Enter your email"
  value={email}
  onChange={(e) => setEmail(e.target.value)}
/>;

textarea.tsx

Multi-line text input for longer content.

Usage:

import { Textarea } from "@/components/ui/textarea";

<Textarea placeholder="Your message" className="h-[200px]" />;

alert.tsx

Notification component for success/error messages.

Variants:

  • default - Blue informational
  • destructive - Red error
  • success - Green success (custom)

Usage:

import { Alert, AlertTitle, AlertDescription } from "@/components/ui/alert";

<Alert variant="success">
  <AlertTitle>Success!</AlertTitle>
  <AlertDescription>Your message has been sent.</AlertDescription>
</Alert>;

tabs.tsx

Tabbed interface for organizing content.

Usage:

import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs";

<Tabs defaultValue="tab1">
  <TabsList>
    <TabsTrigger value="tab1">Tab 1</TabsTrigger>
    <TabsTrigger value="tab2">Tab 2</TabsTrigger>
  </TabsList>

  <TabsContent value="tab1">Content for Tab 1</TabsContent>
  <TabsContent value="tab2">Content for Tab 2</TabsContent>
</Tabs>;

accordion.tsx

Expandable accordion component for FAQs or collapsible content.

Usage:

import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from "@/components/ui/accordion";

<Accordion type="single" collapsible>
  <AccordionItem value="item-1">
    <AccordionTrigger>Question?</AccordionTrigger>
    <AccordionContent>Answer here.</AccordionContent>
  </AccordionItem>
</Accordion>;

tooltip.tsx

Hover tooltip for additional information.

Usage:

import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "@/components/ui/tooltip";

<TooltipProvider>
  <Tooltip>
    <TooltipTrigger>Hover me</TooltipTrigger>
    <TooltipContent>
      <p>Tooltip content here</p>
    </TooltipContent>
  </Tooltip>
</TooltipProvider>;

Layout Components

Header.tsx

Main navigation header with logo and links.

Features:

  • Logo with accent dot
  • Desktop navigation menu
  • Mobile hamburger menu
  • Language selector
  • "Hire me" CTA button

Customization:

// Change logo text
<h1 className="text-4xl font-semibold">
  YourBrand<span className="text-accent">.</span>
</h1>

Nav.tsx

Desktop navigation links with active state highlighting.

Navigation Links:

const links = [
  { name: "home", path: "/" },
  { name: "services", path: "/services" },
  { name: "resume", path: "/resume" },
  { name: "work", path: "/work" },
  { name: "contact", path: "/contact" },
];

How to Add Links:

Simply add to the links array with name and path. The component uses translation keys for display.


MobileNav.tsx

Mobile-friendly sheet navigation.

Features:

  • Hamburger icon trigger
  • Slide-in navigation sheet
  • Logo display
  • Close button
  • Mobile-optimized link styles

Footer.tsx

Footer component with copyright and links.

Features:

  • Dynamic year display
  • Links to About, Privacy, Terms pages
  • Multi-language support
  • Responsive layout

Social.tsx

Social media icon links.

Social Platforms:

const socials = [
  { icon: <FaGithub />, path: "https://github.com/username" },
  { icon: <FaLinkedinIn />, path: "https://linkedin.com/in/username" },
  { icon: <FaYoutube />, path: "https://youtube.com/@username" },
  { icon: <FaInstagram />, path: "https://instagram.com/username" },
];

Usage:

<Social
  containerStyles="flex gap-6"
  iconStyles="w-9 h-9 border border-accent rounded-full flex justify-center items-center text-accent hover:bg-accent hover:text-primary transition-all duration-500"
/>

Stats.tsx

Animated statistics counter.

Features:

  • Counts from start value to target value
  • Smooth easing animation
  • Responsive grid layout
  • Customizable duration
  • Multi-language support

Data Structure:

const stats = [
  {
    num: 5, // Target number
    textKey: "home.stats.years", // Translation key
    startFrom: 0, // Starting number
  },
];

How It Works:

Uses requestAnimationFrame for smooth 60fps animation with ease-out curve.

Reusability:

  • E-commerce dashboards
  • Analytics displays
  • Achievement counters
  • Progress indicators

Photo.tsx

Profile photo with circular border animation.

Features:

  • Circular shape with rotating border effect
  • Responsive sizing
  • Image optimization with Next.js Image
  • Fade-in animation

Customization:

// Change image source
<Image
  src="/your-photo.png"
  alt="Your Name"
  width={498}
  height={498}
  priority
/>

PageTransition.tsx

Wrapper component for page transition animations.

Usage:

import PageTransition from "@/components/PageTransition";

export default function RootLayout({ children }) {
  return <PageTransition>{children}</PageTransition>;
}

Animation:

Uses Framer Motion's AnimatePresence with fade and slide effects.


StairTransition.tsx

Creative stair-step page transition effect.

How It Works:

  • Creates multiple div elements
  • Animates them in sequence
  • Creates a "stair" effect during page transitions

ScrollToTop.tsx

Button that appears when scrolling down, returns to top when clicked.

Features:

  • Only visible after scrolling 300px
  • Smooth scroll to top
  • Fixed position in bottom-right corner
  • Fade in/out animation

GoogleAnalytics.tsx

Google Analytics 4 integration component.

Features:

  • Loads GA4 script
  • Initializes gtag function
  • Logs status in development mode
  • Silent fail for ad blockers

Usage:

Already included in layout.tsx root layout.


LanguageSelector.tsx

Language switcher dropdown component.

Features:

  • Dropdown menu for language selection
  • Visual flag/icons for languages
  • Persists selection in cookies
  • Updates UI immediately

Usage:

import { LanguageSelector } from "@/components/LanguageSelector/LanguageSelector";

<LanguageSelector />;

πŸ”Œ API Endpoints

1. /api/send-email (POST)

Purpose: Sends contact form submission to your email address.

Request Body:

{
  fullname: string; // User's name (1-100 characters)
  email: string; // User's email (valid format)
  message: string; // User's message (1-5000 characters)
}

Response (Success):

{
  message: "Email sent successfully";
}

Response (Error):

{
  error: "Validation failed" | "Authentication failed" | "Connection failed",
  details: string  // Specific error message
}

Validation Rules:

  • All fields required
  • Email must be valid format
  • Name: 1-100 characters
  • Message: 1-5000 characters
  • Input sanitization to prevent XSS

Email Configuration:

const transporter = nodemailer.createTransport({
  host: "smtp.gmail.com",
  port: 587,
  secure: false,
  auth: {
    user: process.env.EMAIL_USER,
    pass: process.env.EMAIL_PASS,
  },
});

Error Handling:

  • EAUTH - Authentication failed
  • ECONNECTION - Connection failed
  • Invalid email format
  • Missing fields

Usage Example:

const handleSubmit = async (e: React.FormEvent) => {
  e.preventDefault();

  try {
    const response = await axios.post("/api/send-email", formData);
    if (response.status === 200) {
      // Show success message
    }
  } catch (error) {
    // Handle error
  }
};

2. /api/send-auto-reply (POST)

Purpose: Sends automatic confirmation email to user after form submission.

Request Body:

{
  fullname: string;
  email: string;
  message: string;
}

Response (Success):

{
  message: "Auto-reply sent successfully",
  referenceNumber: string  // Format: ARN-{timestamp}-{random}
}

Email Template Features:

  • Professional HTML email design
  • Reference number for tracking
  • Message preview (truncated at 200 chars)
  • Submission date
  • Contact information
  • Brand colors and fonts
  • Responsive design

Sample Reference Number:

ARN-1729699200000-742

HTML Email Template:

  • Header with gradient background
  • Message preview box
  • Reference number display
  • Next steps section
  • Contact information footer
  • Disclaimer section

Usage Example:

// Send auto-reply after main email
const autoReply = await axios.post("/api/send-auto-reply", formData);
console.log("Reference:", autoReply.data.referenceNumber);

πŸ—‚οΈ Pages & Routes

App Router Structure

Next.js 15 uses the App Router with file-based routing.

Route File Component Description
/ app/page.tsx HomePage Landing page with hero
/about app/about/page.tsx AboutPage About information
/services app/services/page.tsx ServicesPage Services offered
/resume app/resume/page.tsx ResumePage Resume/Skills
/work app/work/page.tsx WorkPage Portfolio projects
/faq app/faq/page.tsx FAQPage Frequently asked questions
/contact app/contact/page.tsx ContactPage Contact form
/privacy app/privacy/page.tsx PrivacyPage Privacy policy
/terms app/terms/page.tsx TermsPage Terms of service

Creating New Pages

Example: Add /blog page

  1. Create folder and file:
mkdir app/blog
touch app/blog/page.tsx
  1. Create page component:
// app/blog/page.tsx
export default function BlogPage() {
  return (
    <div>
      <h1>Blog</h1>
      {/* Your blog content */}
    </div>
  );
}
  1. Add to navigation:
// components/Nav.tsx
const links = [
  // ... existing links
  { name: "blog", path: "/blog" },
];

Dynamic Routes

Example: Blog post with dynamic slug

mkdir -p app/blog/[slug]
touch app/blog/[slug]/page.tsx
// app/blog/[slug]/page.tsx
export default function BlogPost({ params }: { params: { slug: string } }) {
  return (
    <div>
      <h1>Blog Post: {params.slug}</h1>
    </div>
  );
}

Access at: /blog/my-first-post

Sitemap Generation

The project includes automatic sitemap generation via app/sitemap.ts:

export default function sitemap(): MetadataRoute.Sitemap {
  return [
    {
      url: "https://www.arnobmahmud.com",
      lastModified: new Date(),
      changeFrequency: "monthly",
      priority: 1,
    },
    // ... more routes
  ];
}

Access at: /sitemap.xml


πŸͺ Custom Hooks

useTypewriter Hook

File: hooks/useTypewriter.ts

Purpose: Creates a typewriter text effect with customizable speed and delay.

Interface:

interface UseTypewriterOptions {
  text: string; // Text to animate
  speed?: number; // Typing speed in ms (default: 100)
  delay?: number; // Initial delay before typing starts (default: 0)
}

interface UseTypewriterReturn {
  displayText: string; // Currently displayed text
  isComplete: boolean; // Whether animation is complete
}

Usage:

import { useTypewriter } from "@/hooks/useTypewriter";

function MyComponent() {
  const { displayText, isComplete } = useTypewriter({
    text: "Hello, World!",
    speed: 150,
    delay: 1000,
  });

  return (
    <h1>
      {displayText}
      {!isComplete && <span className="typewriter-cursor">|</span>}
    </h1>
  );
}

How It Works:

  1. Delays initial render by delay milliseconds
  2. Types one character every speed milliseconds
  3. Updates displayText state progressively
  4. Sets isComplete to true when finished

Reusability:

  • Hero headlines
  • Product descriptions
  • Loading messages
  • Interactive tutorials
  • Chat interfaces

Customization Ideas:

  • Add backspace/delete effect
  • Loop animation
  • Type multiple strings in sequence
  • Add realistic typing pauses

🎨 Styling & Animations

TailwindCSS Configuration

File: tailwind.config.js

Custom Theme:

theme: {
  extend: {
    colors: {
      primary: "#1c1c22",
      accent: {
        DEFAULT: "#00ff99",
        hover: "#00e187",
      },
    },
    fontFamily: {
      primary: "var(--font-jetbrainsMono)",
    },
  }
}

Custom Animations:

keyframes: {
  "fade-in": {
    from: { opacity: "0" },
    to: { opacity: "1" },
  },
  "ease-in-out": {
    "0%": { opacity: "0", transform: "translateY(10px)" },
    "100%": { opacity: "1", transform: "translateY(0)" },
  },
}

Global Styles

File: app/globals.css

Key Features:

  • Custom animations with delays
  • Scrollbar styling
  • Text outline effects
  • Typewriter cursor animation
  • Horizontal scroll prevention

Typewriter Cursor:

.typewriter-cursor {
  display: inline-block;
  width: 2px;
  height: 1em;
  background-color: #00ff99;
  margin-left: 2px;
  animation: blink 1s infinite;
}

@keyframes blink {
  0%,
  49% {
    opacity: 1;
  }
  50%,
  100% {
    opacity: 0;
  }
}

Custom Scrollbar:

.custom-scrollbar::-webkit-scrollbar {
  width: 8px;
}

.custom-scrollbar::-webkit-scrollbar-track {
  background: #1c1c22;
}

.custom-scrollbar::-webkit-scrollbar-thumb {
  background: #00ff99;
  border-radius: 4px;
}

Framer Motion Animations

Page Transitions:

<motion.div
  initial={{ opacity: 0, y: 20 }}
  animate={{ opacity: 1, y: 0 }}
  exit={{ opacity: 0, y: 20 }}
  transition={{ duration: 0.5 }}
>
  {children}
</motion.div>

Hover Effects:

<motion.div whileHover={{ scale: 1.05 }} whileTap={{ scale: 0.95 }}>
  Click me
</motion.div>

Staggered Children:

<motion.div
  variants={{
    hidden: { opacity: 0 },
    show: {
      opacity: 1,
      transition: {
        staggerChildren: 0.1,
      },
    },
  }}
>
  {items.map((item) => (
    <motion.div
      variants={{
        hidden: { opacity: 0, y: 20 },
        show: { opacity: 1, y: 0 },
      }}
    >
      {item}
    </motion.div>
  ))}
</motion.div>

πŸ“§ Email Configuration

Gmail SMTP Setup

Step 1: Enable 2-Step Verification

  1. Go to Google Account Security
  2. Click "2-Step Verification"
  3. Follow the setup wizard

Step 2: Generate App Password

  1. Return to Security settings
  2. Click "App passwords"
  3. Select "Mail" and "Other (Custom name)"
  4. Enter "Portfolio Website"
  5. Click "Generate"
  6. Copy the 16-character password
  7. Add to .env.local as EMAIL_PASS

Step 3: Verify Configuration

// Test email configuration
const transporter = nodemailer.createTransport({
  host: "smtp.gmail.com",
  port: 587,
  secure: false,
  auth: {
    user: process.env.EMAIL_USER,
    pass: process.env.EMAIL_PASS,
  },
});

// Verify connection
await transporter.verify();

Alternative Email Providers

Yahoo Mail

const transporter = nodemailer.createTransport({
  host: "smtp.mail.yahoo.com",
  port: 587,
  secure: false,
  auth: {
    user: "youremail@yahoo.com",
    pass: "your-app-password",
  },
});

Outlook/Hotmail

const transporter = nodemailer.createTransport({
  host: "smtp-mail.outlook.com",
  port: 587,
  secure: false,
  auth: {
    user: "youremail@outlook.com",
    pass: "your-password",
  },
});

Custom SMTP

const transporter = nodemailer.createTransport({
  host: "smtp.yourdomain.com",
  port: 465,
  secure: true,
  auth: {
    user: "youremail@yourdomain.com",
    pass: "your-password",
  },
});

Troubleshooting Email Issues

Error: "Invalid login"

  • Ensure 2FA is enabled
  • Regenerate app password
  • Check for typos in .env.local

Error: "Connection timeout"

  • Check firewall settings
  • Verify port 587 is open
  • Try port 465 with secure: true

Emails going to spam

  • Add SPF record to your domain
  • Set up DKIM authentication
  • Use authenticated sender in "from" field

πŸ“Š Analytics Integration

Google Analytics 4

Setup in Project:

  1. Component already created: components/GoogleAnalytics.tsx
  2. Imported in app/layout.tsx
  3. Uses NEXT_PUBLIC_GA_MEASUREMENT_ID from .env.local

Tracking Events:

// Custom event tracking
window.gtag("event", "button_click", {
  event_category: "engagement",
  event_label: "hire_me_button",
  value: 1,
});

Page Views:

Automatically tracked on route changes.

View Reports:

  1. Go to Google Analytics
  2. Select your property
  3. Navigate to "Reports" > "Realtime" for live data
  4. Navigate to "Reports" > "Engagement" for detailed analytics

Vercel Analytics

Setup:

Already integrated in app/layout.tsx:

import { Analytics } from "@vercel/analytics/react";

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <Analytics />
        {children}
      </body>
    </html>
  );
}

Features:

  • Automatic page view tracking
  • Web Vitals monitoring (CLS, FID, LCP, FCP, TTFB)
  • No configuration needed
  • Works automatically on Vercel deployments

View Analytics:

  1. Go to Vercel Dashboard
  2. Select your project
  3. Click "Analytics" tab
  4. View traffic, performance, and Web Vitals

πŸ” SEO & Metadata

Metadata Configuration

File: app/layout.tsx

The project includes comprehensive SEO metadata:

export const metadata: Metadata = {
  metadataBase: new URL("https://www.arnobmahmud.com"),
  title: "Arnob Mahmud | Full-Stack Engineer | Web & Cloud Solutions",
  description: "Full-Stack Software Engineer (5+ years)...",
  keywords: [
    "Full-Stack Software Engineer",
    "React",
    "Next.js",
    // ... more keywords
  ],
  openGraph: {
    title: "...",
    description: "...",
    url: "https://www.arnobmahmud.com",
    images: [{ url: "/assets/photo.png" }],
  },
  twitter: {
    card: "summary_large_image",
    // ... Twitter metadata
  },
};

Structured Data (JSON-LD)

The project includes two structured data schemas:

  1. Person Schema - For personal information
  2. LocalBusiness Schema - For business information

These help search engines understand your content better.

Sitemap

Automatic sitemap generation at /sitemap.xml via app/sitemap.ts.

Robots.txt

Located at public/robots.txt for search engine crawling instructions.


πŸš€ Deployment

Deploy to Vercel (Recommended)

Option 1: Deploy via GitHub (Automatic)

  1. Push to GitHub:
git add .
git commit -m "Initial commit"
git push origin main
  1. Connect to Vercel:

    • Go to Vercel
    • Click "Add New" > "Project"
    • Import your GitHub repository
    • Vercel auto-detects Next.js
  2. Configure Environment Variables:

    • Click "Environment Variables"
    • Add all variables from .env.local:
      • EMAIL_USER
      • EMAIL_PASS
      • NEXT_PUBLIC_GA_MEASUREMENT_ID
      • NEXT_PUBLIC_CHATBOT_URL (if using)
      • NEXT_PUBLIC_GOOGLE_SITE_VERIFICATION (optional)
      • NEXT_PUBLIC_BING_SITE_VERIFICATION (optional)
    • Click "Deploy"
  3. Auto-Deployment:

    • Every push to main branch triggers new deployment
    • Pull requests create preview deployments

Option 2: Deploy via Vercel CLI

# Install Vercel CLI
npm install -g vercel

# Login to Vercel
vercel login

# Deploy
vercel

# Deploy to production
vercel --prod

Deploy to Netlify

  1. Build Settings:

    • Build command: npm run build
    • Publish directory: .next
  2. Environment Variables:

    Add all variables from .env.local in Netlify dashboard

  3. Netlify Configuration:

    Create netlify.toml:

[build]
  command = "npm run build"
  publish = ".next"

[[plugins]]
  package = "@netlify/plugin-nextjs"

Deploy to AWS Amplify

  1. Connect GitHub repository
  2. Configure build settings:
    • Build command: npm run build
    • Output directory: .next
  3. Add environment variables
  4. Deploy

Self-Hosting (VPS/Cloud)

Requirements:

  • Node.js 18+ installed
  • PM2 for process management
  • Nginx for reverse proxy

Steps:

  1. Build the application:
npm run build
  1. Start with PM2:
# Install PM2
npm install -g pm2

# Start application
pm2 start npm --name "portfolio" -- start

# Save PM2 configuration
pm2 save

# Set up auto-start
pm2 startup
  1. Configure Nginx:
server {
  listen 80;
  server_name yourdomain.com;

  location / {
    proxy_pass http://localhost:3000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
  }
}
  1. Enable SSL with Certbot:
sudo certbot --nginx -d yourdomain.com

πŸ”„ Reusable Components Guide

How to Extract and Reuse Components

Example 1: Reusable Card Component

Extract from ServicesPage:

// components/ServiceCard.tsx
import Link from "next/link";
import { BsArrowDownRight } from "react-icons/bs";

interface ServiceCardProps {
  num: string;
  title: string;
  description: string;
  href: string;
}

export default function ServiceCard({
  num,
  title,
  description,
  href,
}: ServiceCardProps) {
  return (
    <div className="flex-1 flex flex-col justify-between gap-4 group">
      <div className="w-full flex justify-between items-center">
        <div className="text-5xl font-extrabold text-outline text-transparent group-hover:text-outline-hover transition-all duration-500">
          {num}
        </div>
        <Link
          href={href}
          className="w-[50px] h-[50px] rounded-full bg-white group-hover:bg-accent transition-all duration-500 flex justify-center items-center hover:-rotate-45"
        >
          <BsArrowDownRight className="text-primary text-3xl" />
        </Link>
      </div>

      <h2 className="text-[32px] font-bold leading-none text-white group-hover:text-accent transition-all duration-500">
        {title}
      </h2>

      <p className="text-white/60 text-justify">{description}</p>

      <div className="border-b border-white/20 w-full"></div>
    </div>
  );
}

Usage:

import ServiceCard from '@/components/ServiceCard';

const services = [...];

return (
  <div className="grid grid-cols-1 md:grid-cols-2 gap-16">
    {services.map((service, index) => (
      <ServiceCard key={index} {...service} />
    ))}
  </div>
);

Example 2: Reusable Form Component

Extract from ContactPage:

// components/ContactForm.tsx
import { useState } from "react";
import { Button } from "./ui/button";
import { Input } from "./ui/input";
import { Textarea } from "./ui/textarea";

interface ContactFormProps {
  onSubmit: (data: FormData) => Promise<void>;
  loading?: boolean;
}

interface FormData {
  fullname: string;
  email: string;
  message: string;
}

export default function ContactForm({
  onSubmit,
  loading = false,
}: ContactFormProps) {
  const [formData, setFormData] = useState<FormData>({
    fullname: "",
    email: "",
    message: "",
  });

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    await onSubmit(formData);
    setFormData({ fullname: "", email: "", message: "" });
  };

  return (
    <form onSubmit={handleSubmit} className="flex flex-col gap-4">
      <Input
        type="text"
        name="fullname"
        placeholder="Enter your name"
        value={formData.fullname}
        onChange={(e) =>
          setFormData((prev) => ({ ...prev, fullname: e.target.value }))
        }
        required
      />

      <Input
        type="email"
        name="email"
        placeholder="Enter your email"
        value={formData.email}
        onChange={(e) =>
          setFormData((prev) => ({ ...prev, email: e.target.value }))
        }
        required
      />

      <Textarea
        name="message"
        placeholder="Type your message here"
        value={formData.message}
        onChange={(e) =>
          setFormData((prev) => ({ ...prev, message: e.target.value }))
        }
        className="h-[200px]"
        required
      />

      <Button type="submit" disabled={loading}>
        {loading ? "Sending..." : "Send Message"}
      </Button>
    </form>
  );
}

Example 3: Reusable Stats Component

Make Stats.tsx more flexible:

// components/StatsCounter.tsx
interface Stat {
  num: number;
  text: string;
  startFrom?: number;
}

interface StatsCounterProps {
  stats: Stat[];
  columns?: number;
}

export default function StatsCounter({
  stats,
  columns = 4,
}: StatsCounterProps) {
  const gridClass = `grid-cols-${columns}`;

  return (
    <div className={`grid ${gridClass} gap-6`}>
      {stats.map((stat, index) => (
        <StatItem key={index} {...stat} />
      ))}
    </div>
  );
}

Usage in different projects:

// E-commerce dashboard
const ecommerceStats = [
  { num: 1250, text: "Total Orders" },
  { num: 45678, text: "Revenue ($)" },
  { num: 98, text: "Customer Satisfaction (%)" },
];

<StatsCounter stats={ecommerceStats} columns={3} />;

// Blog analytics
const blogStats = [
  { num: 50000, text: "Monthly Visitors" },
  { num: 234, text: "Published Articles" },
];

<StatsCounter stats={blogStats} columns={2} />;

Component Reusability Checklist

βœ… Make components prop-driven

  • Accept data via props instead of hardcoding
  • Use TypeScript interfaces for type safety

βœ… Keep components focused

  • Single responsibility principle
  • Separate logic from presentation

βœ… Use composition over inheritance

  • Build complex UIs from simple components
  • Use children prop for flexibility

βœ… Document component APIs

  • Add JSDoc comments
  • Provide usage examples
  • List all props and their types

βœ… Style with flexibility

  • Accept className prop for custom styling
  • Use Tailwind utility classes
  • Support theme variants

βœ… Handle edge cases

  • Empty states
  • Loading states
  • Error states

βœ… Best Practices

Code Organization

1. Component Structure:

Component/
β”œβ”€β”€ Component.tsx         # Main component
β”œβ”€β”€ Component.test.tsx    # Unit tests
β”œβ”€β”€ Component.stories.tsx # Storybook stories (optional)
└── index.ts             # Export file

2. Import Order:

// 1. React and Next.js imports
import { useState } from "react";
import Link from "next/link";

// 2. Third-party libraries
import axios from "axios";
import { motion } from "framer-motion";

// 3. Internal components
import { Button } from "@/components/ui/button";

// 4. Utilities and helpers
import { cn } from "@/lib/utils";

// 5. Types and interfaces
import type { FormData } from "@/types";

// 6. Styles and assets
import "./styles.css";

3. TypeScript Best Practices:

  • Always define interfaces for props
  • Use type for unions and intersections
  • Avoid any type
  • Enable strict mode

4. Performance Optimization:

  • Use React.memo for expensive components
  • Implement code splitting with dynamic imports
  • Optimize images with Next.js Image component
  • Lazy load components below the fold

5. Accessibility:

  • Use semantic HTML elements
  • Add ARIA labels where needed
  • Ensure keyboard navigation
  • Maintain color contrast ratios
  • Test with screen readers

6. SEO Best Practices:

  • Use Next.js metadata API
  • Include Open Graph tags
  • Add structured data (JSON-LD)
  • Create sitemap.xml
  • Implement canonical URLs

πŸ” Keywords & SEO

Meta Tags Configuration

File: app/layout.tsx

export const metadata: Metadata = {
  metadataBase: new URL("https://www.arnobmahmud.com"),
  title: "Arnob Mahmud | Full-Stack Developer | Portfolio",
  description: "Professional portfolio showcasing web development projects...",
  keywords: [
    "Arnob Mahmud",
    "Full-Stack Developer",
    "Web Developer",
    "React",
    "Next.js",
    "TypeScript",
    "Portfolio",
  ],
  authors: [{ name: "Arnob Mahmud" }],
  openGraph: {
    title: "Arnob Mahmud | Full-Stack Developer",
    description: "Portfolio of Arnob Mahmud...",
    url: "https://www.arnobmahmud.com",
    siteName: "Arnob Mahmud Portfolio",
    images: [{ url: "/assets/photo.png" }],
    locale: "en_US",
    type: "website",
  },
  twitter: {
    card: "summary_large_image",
    title: "Arnob Mahmud | Full-Stack Developer",
    description: "Portfolio of Arnob Mahmud...",
    images: ["/assets/photo.png"],
  },
};

Keywords for Portfolio Websites

General:

  • Full-Stack Developer
  • Web Developer
  • Software Engineer
  • Frontend Developer
  • Backend Developer
  • Portfolio Website

Technologies:

  • React.js
  • Next.js
  • TypeScript
  • JavaScript
  • Node.js
  • TailwindCSS
  • Framer Motion

Services:

  • Web Development
  • UI/UX Design
  • API Development
  • Database Design
  • Cloud Deployment
  • SEO Optimization

Location-based:

  • Frankfurt Developer
  • Germany Web Developer
  • Remote Developer

πŸ› Troubleshooting

Common Issues and Solutions

1. Email Not Sending

Symptoms:

  • "Authentication failed" error
  • "Connection timeout" error
  • Emails not arriving

Solutions:

# Check environment variables
echo $EMAIL_USER
echo $EMAIL_PASS

# Verify .env.local exists
ls -la .env.local

# Restart development server
npm run dev:clean

Checklist:

  • βœ… 2FA enabled on Gmail
  • βœ… App password generated (not regular password)
  • βœ… No spaces in app password
  • βœ… Correct email in EMAIL_USER
  • βœ… Port 587 not blocked by firewall

2. Google Analytics Not Tracking

Symptoms:

  • No data in GA4 dashboard
  • Real-time reports empty

Solutions:

  1. Check Measurement ID:
# .env.local
NEXT_PUBLIC_GA_MEASUREMENT_ID=G-XXXXXXXXXX
  1. Verify in Browser Console:
// Check if gtag is loaded
console.log(window.gtag);
console.log(window.dataLayer);
  1. Disable Ad Blocker:
  • Ad blockers prevent GA from loading
  • Test in incognito mode without extensions
  1. Wait 24-48 hours:
  • GA4 data processing takes time
  • Real-time reports update faster

3. Build Errors

Error: "Module not found"

# Clear node_modules and reinstall
rm -rf node_modules
rm package-lock.json
npm install

Error: "Type error in component"

# Check TypeScript errors
npm run build

# Fix type errors in the reported files

Error: "Cannot find module './public/...'"

# Ensure asset files exist
ls -la public/assets/

# Check file paths are correct (case-sensitive)

4. Styling Issues

Tailwind classes not working:

# Restart development server
npm run dev:clean

# Check tailwind.config.js includes your files
content: [
  "./app/**/*.{js,ts,jsx,tsx}",
  "./components/**/*.{js,ts,jsx,tsx}",
]

Custom fonts not loading:

// Verify font is imported in layout.tsx
import { JetBrains_Mono } from "next/font/google";

const jetbrainsMono = JetBrains_Mono({
  subsets: ["latin"],
  variable: "--font-jetbrainsMono",
});

5. Deployment Issues on Vercel

Environment variables not working:

  1. Go to Vercel Dashboard
  2. Project Settings β†’ Environment Variables
  3. Add all variables
  4. Redeploy the project

Build fails on Vercel:

# Check build works locally
npm run build

# Review build logs in Vercel dashboard
# Fix reported errors

6. Internationalization Issues

Language not persisting:

  • Check cookie settings in browser
  • Verify middleware.ts is properly configured
  • Check LanguageContext.tsx for cookie setting logic

Translations not loading:

  • Verify lib/translations.ts has all required keys
  • Check lib/i18n.ts configuration
  • Ensure I18nProvider wraps the app in layout.tsx

🀝 Contributing

This is an open-source project and contributions are welcome! Whether you want to:

  • πŸ› Fix bugs
  • ✨ Add new features
  • πŸ“š Improve documentation
  • 🎨 Enhance UI/UX
  • ⚑ Optimize performance
  • πŸ”§ Refactor code
  • 🌍 Add translations
  • πŸ’‘ Suggest improvements

Feel free to:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes with proper TypeScript types and linting
  4. Commit your changes (git commit -m 'Add some amazing feature')
  5. Push to the branch (git push origin feature/amazing-feature)
  6. Open a Pull Request

Development Guidelines

  • Use TypeScript with proper type definitions
  • Follow ESLint rules (run npm run lint)
  • Write clear commit messages
  • Add comments for complex logic
  • Test your changes before submitting
  • Update documentation if needed

Reporting Bugs

  1. Check if the bug is already reported in Issues
  2. Create a new issue with:
    • Clear title
    • Steps to reproduce
    • Expected vs actual behavior
    • Screenshots (if applicable)
    • Environment details (OS, browser, Node version)

Suggesting Features

  1. Open a new issue with the label "enhancement"
  2. Describe the feature and its benefits
  3. Provide examples or mockups

Commit Message Format

  • feat: - New feature
  • fix: - Bug fix
  • docs: - Documentation changes
  • style: - Code style changes (formatting)
  • refactor: - Code refactoring
  • test: - Adding tests
  • chore: - Maintenance tasks

Together, we can take this project to the next level! πŸš€


πŸ“„ License

This project is open-source and available under the MIT License.

What this means:

  • βœ… Free to use for personal and commercial projects
  • βœ… Modify and distribute as you wish
  • βœ… Include in private and public repositories
  • ⚠️ Must include the license notice
  • ⚠️ No warranty provided

For full license details, see the LICENSE file in the repository.


πŸ“ Conclusion

This project demonstrates a production-ready implementation of a modern portfolio website with:

  • Modern Architecture: Next.js App Router, Server Components, API Routes
  • Best Practices: TypeScript, proper error handling, input validation
  • Performance: Image optimization, lazy loading, code splitting
  • User Experience: Smooth animations, responsive design, accessibility
  • Developer Experience: Well-documented, type-safe, reusable components
  • SEO: Comprehensive metadata, structured data, sitemap generation
  • Internationalization: Multi-language support with persistence
  • Analytics: Google Analytics and Vercel Analytics integration

The codebase is well-documented and structured for easy understanding and extension. Each component can be reused independently in other projects, making this an excellent learning resource and starting point for portfolio websites.

Key Takeaways

  • Next.js 15 provides excellent developer experience with App Router
  • TypeScript ensures type safety and better code quality
  • TailwindCSS enables rapid UI development
  • Framer Motion creates smooth, professional animations
  • i18next makes internationalization straightforward
  • Nodemailer enables reliable email functionality
  • Component reusability saves time in future projects

Learning Resources


Happy Coding! πŸŽ‰

This is an open-source project - feel free to use, enhance, and extend this project further!

If you have any questions, want to contribute, or want to share your work, reach out via GitHub or my portfolio at https://www.arnobmahmud.com/.

Enjoy building and learning! πŸš€

Thank you! 😊


About

A cutting-edge, production-ready portfolio website built with Next.js 15, React 18, TypeScript, TailwindCSS, and Framer Motion. This project showcases modern web development practices, including server-side rendering, API routes, email functionality, analytics integration, internationalization (i18n), and stunning animations.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •