Welcome to my first blog post! Starting something new always feels exciting and a bit uncertain. Today, I want to share how I built this website — the technologies I chose, the problems I solved, and the lessons I learned along the way.
Why I Built This Site
Every developer needs a place to share their work, thoughts, and experiments. I wanted a website that was:
- Fast — Lightning-quick load times with static generation
- SEO-friendly — Easy for search engines to discover and rank
- Maintainable — Clean code with type safety and modern tools
- Accessible — Usable by everyone, regardless of ability
Let me walk you through how I achieved these goals.
The Foundation: Core Technologies
Next.js 16 — The Framework
I chose Next.js 16 as my foundation. I've used Next.js since version 13, and it continues to impress with its developer experience and performance features.
What makes Next.js great for this project:
- Server Components — Components render on the server by default, sending less JavaScript to browsers
- Static Generation — Pages are pre-built as HTML files for instant loading
- Image Optimization — Automatic image resizing, format conversion, and lazy loading
- File-based Routing — The folder structure becomes your site's URL structure
Resources: Next.js Documentation • App Router Guide
TypeScript — Type Safety
TypeScript catches bugs before they reach production. Every function, component, and configuration is fully typed, making refactoring safe and development faster with autocomplete support.
Resources: TypeScript Documentation
Styling: Building a Consistent Design System
Tailwind CSS v4 — Utility-First Styling
I'm using Tailwind CSS v4, which brings exciting new features like improved CSS variable support.
My approach to styling:
Instead of using colors directly in components, I created reusable utility classes in my CSS file. This keeps the code clean and makes design changes easier.
Theme System — Light and Dark Modes
The site supports both light and dark modes with automatic detection of your system preference. There's a theme toggle in the bottom right corner to switch manually.
How it works:
- CSS variables store all colors with different values for each theme
- A small JavaScript snippet runs before React loads to prevent flash of the wrong theme
- The theme toggle updates a
data-themeattribute on the<html>element - CSS automatically applies the correct colors based on this attribute
Resources: Tailwind CSS v4 • OKLCH Colors
Content Management: Writing with MDX
Why MDX?
MDX combines the simplicity of Markdown with the power of React components. This means I can write blog posts in Markdown and embed interactive React components directly in the content.
Example:
##My Blog Post
This is regular Markdown text.
<Button>Click me!</Button>
This button is a real React component!
Custom Component Configuration
I've configured MDX to use custom components throughout the site:
import { MDXComponents } from "mdx/types";
import { Button } from "@/components/button";
import NextLink from "next/link";
export function useMDXComponents(components: MDXComponents): MDXComponents {
return {
...components,
Button,
Link: NextLink, // Use Next.js Link for better navigation
h1: (props) => <h1 {...props} />,
// ... other elements
};
}
This ensures all content follows the same design system and accessibility patterns.
Resources: MDX Documentation • Next.js MDX Guide
Content Collections — Type-Safe Content
While Next.js supports MDX natively, I needed more robust content management. Enter Content Collections.
Every blog post's metadata (title, summary, tags, etc.) is validated against a schema. If something is missing or wrong, the build fails with a clear error message.
Resources: Content Collections • Zod Validation
Static Site Generation
The entire website is pre-built as static HTML files. This means:
- Instant Loading — No server processing time
- Better SEO — Search engines can crawl HTML directly
- Lower Costs — No server to run
- High Reliability — Static files served from a CDN can handle traffic spikes
Blog posts are generated at build time from MDX files, with Content Collections ensuring type safety throughout the process.
SEO: Being Discoverable
Building a website is one thing. Making sure people can find it is another. Here's my SEO strategy:
Metadata API
Next.js provides a powerful Metadata API for managing meta tags. Every page has:
- Unique titles and descriptions optimized for search engines
- Open Graph tags for rich previews on social media
- Twitter Card metadata for enhanced sharing on Twitter/X
- Canonical URLs to prevent duplicate content issues
export function getBlogPostMetadata(blog: BlogPost, slug: string): Metadata {
return {
title: blog.title,
description: blog.summary,
openGraph: {
title: blog.title,
description: blog.summary,
url: `/blogs/${slug}`,
images: [`/blogs/${slug}/opengraph-image`],
},
alternates: {
canonical: `/blogs/${slug}`,
},
};
}
Dynamic Open Graph Images
Each page has a unique social media preview image, generated automatically using next/og.
How it works:
Next.js detects opengraph-image.tsx files in your routes and generates images at build time using Satori — a library that converts JSX to images.
For static pages:
export default async function Image() {
return new ImageResponse(
(
<div
style={
{
/* design */
}
}
>
Blog Posts | Mudasir Pandith
</div>
),
{ width: 1200, height: 630 }
);
}
For blog posts (dynamic):
export default async function Image({ params }) {
const { slug } = await params;
const blog = allBlogs.find((b) => getSlug(b.title) === slug);
return new ImageResponse(
(
<div
style={
{
/* design */
}
}
>
<h1>{blog.title}</h1>
<p>{blog.summary}</p>
</div>
),
{ width: 1200, height: 630 }
);
}
Benefits:
- Unique preview image for every blog post
- Better click-through rates on social media
- Professional appearance when sharing links
- Consistent branding across all shared content
Resources: Next.js OG Images
JSON-LD Structured Data
JSON-LD helps search engines understand your content better, potentially leading to rich results in search listings.
What I've implemented:
Person Schema
Describes me as the author:
{
"@type": "Person",
"name": "Mudasir Pandith",
"jobTitle": "Software Developer",
"url": "https://mudasirpandith.com",
"sameAs": ["https://github.com/mudasirpandith", "https://linkedin.com/in/mudasirpandith"]
}
WebSite Schema
Describes the website itself:
{
"@type": "WebSite",
"name": "Mudasir Pandith",
"url": "https://mudasirpandith.com",
"author": { "@type": "Person", "name": "Mudasir Pandith" }
}
BlogPosting Schema
For each blog post:
{
"@type": "BlogPosting",
"headline": "Building My Personal Website",
"description": "A technical deep dive...",
"datePublished": "2024-01-15",
"author": { "@type": "Person", "name": "Mudasir Pandith" },
"keywords": ["nextjs", "web-development"]
}
Implementation:
export function JsonLd({ data }) {
return <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }} />;
}
Benefits:
- Rich snippets in search results
- Better understanding by search engines
- Improved voice search compatibility
- Potential Knowledge Graph inclusion
Validation Tools:
Resources: JSON-LD Specification • Schema.org Guide
Robots.txt & Sitemap
Robots.txt tells search engines what they can crawl:
export default function robots() {
return {
rules: {
userAgent: "*",
allow: "/",
},
sitemap: "https://mudasirpandith.com/sitemap.xml",
};
}
Sitemap.xml lists all pages with metadata:
export default function sitemap() {
return [
{
url: "https://mudasirpandith.com",
lastModified: new Date(),
changeFrequency: "weekly",
priority: 1,
},
{
url: "https://mudasirpandith.com/blogs",
lastModified: new Date(),
changeFrequency: "weekly",
priority: 0.8,
},
];
}
Resources: Google Sitemap Guidelines
Hosting: Vercel
I'm hosting on Vercel, which is built by the creators of Next.js. It provides:
- Zero Configuration — Detects Next.js automatically and configures everything
- Global CDN — Fast loading worldwide with edge caching
- Automatic Deployments — Every push to GitHub triggers a new deployment
- Preview URLs — Every pull request gets its own preview link
- Performance Analytics — Built-in monitoring of Core Web Vitals
While I'm exploring Cloudflare Pages for future projects, Vercel remains an excellent choice for Next.js applications.
Resources: Vercel Documentation
Wrapping Up
Building this website taught me a lot about modern web development. The combination of Next.js, React, TypeScript, and thoughtful tooling creates a solid foundation for a fast, maintainable, and accessible website.
I'm excited to share more technical insights, lessons learned, and development workflows in future posts. If you have questions about any of these topics, feel free to reach out!