Skip to main content
The blog system in this portfolio is built with Next.js App Router, featuring static site generation, markdown processing, and SEO optimization.

Architecture

The blog follows a file-based routing structure with markdown content:
src/
├── app/
│   ├── blog/
│   │   ├── page.tsx              # Blog listing page
│   │   └── post/
│   │       └── [slug]/
│   │           └── page.tsx      # Individual post page
│   └── components/
│       └── blog/
│           ├── BlogHeader.tsx
│           ├── BlogPostCard.tsx
│           ├── BlogPostContent.tsx
│           └── BlogPostList.tsx
├── content/
│   └── blog/
│       ├── openai-townhall.md
│       ├── intern-experience-aws.md
│       └── ...
└── lib/
    └── blog.ts                    # Blog utilities

Key Components

Blog Listing (/blog)

The main blog page displays all posts in a grid layout: File: src/app/blog/page.tsx:41
export default function BlogListingPage() {
  const blogPosts = getSortedPostsData();
  
  return (
    <div className="min-h-screen text-white">
      <BlogHeader
        title="Writings"
        subtitle=""
        backLink="/"
        backText="Back to Portfolio"
      />
      <BlogPostList posts={blogPosts} />
      <Footer />
    </div>
  );
}
The blog listing includes structured data (JSON-LD) for SEO, helping search engines understand the blog content.

Individual Posts (/blog/post/[slug])

Dynamic routes are generated at build time using generateStaticParams: File: src/app/blog/post/[slug]/page.tsx:177
export async function generateStaticParams() {
  const slugs = getAllPostSlugs();
  return slugs;
}

export default async function IndividualBlogPostPage({
  params,
}: BlogPostPageProps) {
  const { slug } = await params;
  const post = await getPostData(slug);

  if (!post) {
    notFound();
  }

  return (
    <div className="min-h-screen text-white">
      <BlogHeader title="" backLink="/blog" backText="Back to Writings" />
      <BlogPostContent post={post} />
      <Footer />
    </div>
  );
}

Blog Utilities

The src/lib/blog.ts file provides core functionality:

Key Functions

1

getSortedPostsData()

Reads all markdown files from src/content/blog/, parses frontmatter with gray-matter, and returns posts sorted by date (latest first).File: src/lib/blog.ts:28
2

getPostData(slug)

Fetches a specific post by slug, processes markdown to HTML using remark, and applies custom Spotify-themed styling.File: src/lib/blog.ts:72
3

getAllPostSlugs()

Returns all available post slugs for static generation.File: src/lib/blog.ts:60

SEO Features

The blog system includes comprehensive SEO optimization:

Dynamic Metadata

Each post generates dynamic metadata including:
  • Title and description
  • Open Graph tags for social sharing
  • Twitter Card metadata
  • Canonical URLs
  • Structured data (JSON-LD) for BlogPosting schema
File: src/app/blog/post/[slug]/page.tsx:33
export async function generateMetadata({
  params,
}: BlogPostPageProps): Promise<Metadata> {
  const { slug } = await params;
  const post = await getPostData(slug);

  return {
    title: `${post.title} | ${DEFAULT_AUTHOR}`,
    description: excerpt,
    openGraph: {
      type: "article",
      url: canonicalUrl,
      title: post.title,
      images: [{ url: post.image }],
      publishedTime: toIsoDate(post.date),
    },
    // ... more metadata
  };
}

TypeScript Interfaces

Blog posts use well-defined TypeScript interfaces: File: src/lib/blog.ts:9
export interface BlogPost {
  id: string;
  title: string;
  description: string;
  date: string;
  readTime: string;
  image: string;
  slug: string;
  author?: string;
  tags?: string[];
  category?: string;
  excerpt?: string;
  content?: string;
}

export interface BlogPostWithContent extends BlogPost {
  content: string;
}

Styling System

The blog uses a Spotify-inspired dark theme with custom CSS classes:
  • spotify-green - Primary accent color (#1DB954)
  • spotify-white - Text color with opacity variations
  • spotify-light-dark - Card backgrounds
  • spotify-dark - Main background
Custom styling is applied to markdown HTML in src/lib/blog.ts:106 using the applyCustomStyling() function, which transforms standard HTML elements into styled components.

Next Steps

Creating Posts

Learn how to write and publish new blog posts

Markdown Support

Explore supported markdown features and syntax

Build docs developers (and LLMs) love