Back to projects

Professional Portfolio & Blog Platform

A modern, high-performance portfolio website built with Next.js 15, showcasing enterprise fintech projects, technical blog posts, and professional achievements with optimal SEO and accessibility.

October 10, 2024
Full-Stack Developer & Designer
Solo
2 months
LiveFeatured
Next.js 15TypeScriptTailwind CSS v4MDXFramer MotionShadcnUI
Professional Portfolio & Blog Platform
Share:

Project Overview

This portfolio website serves as both a showcase of my work and a platform for sharing technical insights through blog posts. Built with the latest Next.js features, it emphasizes performance, accessibility, and developer experience.

Design Philosophy

The design follows these core principles:

  • Minimalism: Clean, distraction-free layout that puts content first
  • Performance: Optimized for fast load times and smooth interactions
  • Accessibility: WCAG 2.1 AA compliant for inclusive user experience
  • Responsive: Seamless experience across all device sizes
  • Dark Mode: System-aware theme switching

Key Features

Blog System

  • MDX Support: Write blog posts with React components embedded in Markdown
  • Syntax Highlighting: Beautiful code highlighting with sugar-high
  • Reading Time: Automatic calculation of estimated reading time
  • Tag System: Organize posts by topics and technologies
  • Search Functionality: Client-side search across posts
  • Related Posts: AI-powered related content suggestions

Portfolio Showcase

  • Project Gallery: Filterable showcase of development work
  • Case Studies: Detailed project breakdowns with technical insights
  • Technology Tags: Filter projects by tech stack
  • Live Demos: Direct links to deployed projects
  • Source Code: GitHub repository links

User Experience

  • Theme Toggle: Smooth dark/light mode switching with persistence
  • Smooth Animations: Subtle transitions using Framer Motion
  • Progressive Enhancement: Works without JavaScript
  • RSS Feed: Subscribe to blog updates via RSS
  • Share Buttons: Easy social media sharing

Technical Implementation

Next.js App Router

Leveraging Next.js 15's latest features:

// app/posts/[slug]/page.tsx
export async function generateStaticParams() {
  const posts = await getAllPosts()
  return posts.map(post => ({
    slug: post.slug
  }))
}

export async function generateMetadata({ params }): Promise<Metadata> {
  const post = await getPostBySlug(params.slug)

  return {
    title: post.metadata.title,
    description: post.metadata.summary,
    openGraph: {
      title: post.metadata.title,
      description: post.metadata.summary,
      images: [post.metadata.image]
    }
  }
}

MDX Content Pipeline

Custom MDX setup for blog posts:

// lib/post.ts
import fs from 'fs'
import matter from 'gray-matter'
import path from 'path'

export async function getPostBySlug(slug: string): Promise<Post | null> {
  try {
    const filePath = path.join(process.cwd(), 'content', 'posts', `${slug}.mdx`)
    const fileContents = fs.readFileSync(filePath, 'utf8')

    const { data, content } = matter(fileContents)

    return {
      metadata: { ...data, slug },
      content
    }
  } catch (error) {
    return null
  }
}

MDX Components

Custom components for rich content:

// components/mdx-content.tsx
import { MDXRemote } from 'next-mdx-remote/rsc'
import { highlight } from 'sugar-high'

const components = {
  pre: ({ children, ...props }) => {
    const code = children.props.children
    const highlighted = highlight(code)
    return (
      <pre {...props}>
        <code dangerouslySetInnerHTML={{ __html: highlighted }} />
      </pre>
    )
  },
  img: ({ src, alt }) => (
    <Image
      src={src}
      alt={alt}
      width={800}
      height={400}
      className="rounded-lg"
    />
  )
}

export default function MDXContent({ source }) {
  return <MDXRemote source={source} components={components} />
}

Styling Architecture

Tailwind CSS v4

Using the latest Tailwind features:

/* app/globals.css */
@import 'tailwindcss';

@theme {
  --color-primary: #3b82f6;
  --font-sans: 'Inter', sans-serif;
  --font-serif: 'Playfair Display', serif;
}

@layer utilities {
  .title {
    @apply font-serif text-4xl font-bold tracking-tight;
  }
}

Theme System

Dark mode implementation with next-themes:

// components/providers.tsx
'use client'

import { ThemeProvider } from 'next-themes'

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <ThemeProvider attribute="class" defaultTheme="system" enableSystem>
      {children}
    </ThemeProvider>
  )
}

Performance Optimizations

Image Optimization

Using Next.js Image component:

<Image
  src={post.image}
  alt={post.title}
  width={1200}
  height={630}
  priority={isFeatured}
  sizes="(max-width: 768px) 100vw, (max-width: 1200px) 80vw, 1200px"
/>

Font Loading

Optimized font loading strategy:

// app/layout.tsx
import { Inter, Playfair_Display } from 'next/font/google'

const inter = Inter({
  subsets: ['latin'],
  variable: '--font-sans',
  display: 'swap'
})

const playfair = Playfair_Display({
  subsets: ['latin'],
  variable: '--font-serif',
  display: 'swap'
})

export default function RootLayout({ children }) {
  return (
    <html className={`${inter.variable} ${playfair.variable}`}>
      <body>{children}</body>
    </html>
  )
}

SEO Optimization

Metadata Configuration

Comprehensive SEO setup:

// app/layout.tsx
export const metadata: Metadata = {
  metadataBase: new URL('https://yourportfolio.com'),
  title: {
    default: 'Your Name - Full Stack Developer',
    template: '%s | Your Name'
  },
  description: 'Portfolio and blog of a full-stack developer...',
  openGraph: {
    type: 'website',
    locale: 'en_US',
    url: 'https://yourportfolio.com',
    siteName: 'Your Name Portfolio'
  },
  robots: {
    index: true,
    follow: true
  }
}

Structured Data

JSON-LD for better search engine understanding:

// components/structured-data.tsx
export function BlogPostStructuredData({ post }) {
  const structuredData = {
    '@context': 'https://schema.org',
    '@type': 'BlogPosting',
    headline: post.title,
    description: post.summary,
    author: {
      '@type': 'Person',
      name: post.author
    },
    datePublished: post.publishedAt,
    image: post.image
  }

  return (
    <script
      type="application/ld+json"
      dangerouslySetInnerHTML={{ __html: JSON.stringify(structuredData) }}
    />
  )
}

Accessibility Features

  • Semantic HTML: Proper heading hierarchy and landmarks
  • ARIA Labels: Descriptive labels for interactive elements
  • Keyboard Navigation: Full keyboard accessibility
  • Focus Management: Visible focus indicators
  • Color Contrast: WCAG AA compliant contrast ratios
  • Screen Reader: Optimized for screen reader users

Analytics & Monitoring

// lib/analytics.ts
export function trackPageView(url: string) {
  if (typeof window !== 'undefined' && window.gtag) {
    window.gtag('config', 'GA_MEASUREMENT_ID', {
      page_path: url
    })
  }
}

export function trackEvent(event: string, params?: Record<string, any>) {
  if (typeof window !== 'undefined' && window.gtag) {
    window.gtag('event', event, params)
  }
}

Content Management

Writing Workflow

Simple file-based workflow:

  1. Create MDX file in content/posts/
  2. Add frontmatter metadata
  3. Write content with MDX
  4. Commit and deploy

Frontmatter Schema

---
title: 'Blog Post Title'
summary: 'Brief description of the post'
author: 'Your Name'
publishedAt: '2024-01-15'
image: '/images/blog/post-image.jpg'
tags: ['Next.js', 'TypeScript', 'Web Development']
readTime: 5
---

Deployment

Vercel Configuration

{
  "buildCommand": "npm run build",
  "outputDirectory": ".next",
  "framework": "nextjs",
  "installCommand": "pnpm install"
}

Environment Variables

NEXT_PUBLIC_SITE_URL=https://yourportfolio.com
NEXT_PUBLIC_GA_MEASUREMENT_ID=G-XXXXXXXXXX

Performance Metrics

Lighthouse scores (mobile):

  • Performance: 99
  • Accessibility: 100
  • Best Practices: 100
  • SEO: 100

Core Web Vitals:

  • LCP: 1.2s (Good)
  • FID: 8ms (Good)
  • CLS: 0.01 (Good)

Lessons Learned

  1. Static Generation: Using SSG for blog posts dramatically improves performance
  2. Type Safety: TypeScript catches errors early in development
  3. Component Reusability: shadcn/ui components provide consistency
  4. Content Strategy: File-based MDX is simple yet powerful

Future Improvements

  • [ ] Add comments system (with Giscus)
  • [ ] Newsletter subscription
  • [ ] Advanced search with Algolia
  • [ ] Reading progress indicator
  • [ ] View counter for posts
  • [ ] Interactive code playgrounds

Conclusion

This portfolio demonstrates modern web development best practices with Next.js 15. It showcases my commitment to performance, accessibility, and clean code architecture.