Dawood Sarfraz

Dawood Sarfraz - Portfolio Website

Personal portfolio website built with Next.js 15, React 19, TypeScript, and Tailwind CSS. Features a single-page portfolio layout with separate pages for blogs and educational notes (Machine Learning & Reinforcement Learning) rendered from MDX.

Tech Stack


Getting Started

Prerequisites

Install Dependencies

npm install

Run Development Server

npm run dev

Open http://localhost:3000 in your browser.

Build for Production

npm run build

This generates a static export in the out/ directory, ready for GitHub Pages deployment.

Lint

npm run lint

Project Structure

src/
├── app/
│   ├── layout.tsx                  # Root layout (fonts, metadata, CDN links)
│   ├── page.tsx                    # Main portfolio page
│   ├── _components/               # Shared UI components
│   │   ├── navbar.tsx              # Top navigation bar
│   │   ├── social-links.tsx        # Social media icons
│   │   ├── about.tsx               # About section
│   │   ├── education.tsx           # Education section
│   │   ├── experience.tsx          # Experience section
│   │   ├── projects.tsx            # Projects section
│   │   ├── publications.tsx        # Publications section
│   │   ├── skills.tsx              # Skills section
│   │   ├── miscellaneous.tsx       # Miscellaneous section
│   │   ├── footer.tsx              # Footer
│   │   ├── badge.tsx               # Badge component for blog tags
│   │   ├── linksSection.tsx        # Numbered links list for notes
│   │   └── markdown/              # MDX rendering components
│   ├── blogs/
│   │   ├── page.tsx                # Blogs listing page
│   │   ├── blogsList.tsx           # Blog list client component
│   │   └── data.ts                 # Blog entries data
│   └── notes/
│       ├── page.tsx                # Notes grid page
│       ├── notesList.tsx           # Notes cards client component
│       ├── layout.tsx              # Notes layout wrapper
│       ├── machine-learning/
│       │   ├── page.tsx            # ML notes listing
│       │   └── [id]/
│       │       ├── page.tsx        # Server component (generateStaticParams)
│       │       ├── client.tsx      # Client component (MDX renderer)
│       │       ├── data.ts         # ML note entries with lazy imports
│       │       └── notes/          # MDX files for each ML note
│       └── reinforcement-learning/
│           ├── page.tsx            # RL notes listing
│           └── [id]/
│               ├── page.tsx        # Server component (generateStaticParams)
│               ├── client.tsx      # Client component (MDX renderer)
│               ├── data.ts         # RL note entries with lazy imports
│               └── notes/          # MDX files for each RL note
├── data/                           # Portfolio data files
│   ├── education.ts
│   ├── experience.ts
│   ├── projects.ts
│   ├── publications.ts
│   ├── skills.ts
│   └── miscellaneous.ts
├── styles/
│   └── globals.css                 # Global styles + Tailwind directives
├── types/
│   └── mdx.d.ts                    # MDX module type declaration
└── utils.ts                        # Utility functions (cn)

public/
└── assets/                         # Images (profile, logos, project thumbnails)

How to Add a New Blog

  1. Open src/app/blogs/data.ts

  2. Add a new entry to the blogs array:

{
  title: "Your Blog Title",
  description: "A short description of the blog post.",
  date: "Month Day, Year",          // e.g. "August 20, 2026"
  tags: ["tag1", "tag2"],           // Tags shown as badges
  link: "https://example.com/blog", // External link to the full blog post
}
  1. That’s it. The blog will appear on the /blogs page with search and tag filtering.

How to Add a New Note

Adding a note to an existing category (ML or RL)

Example: Adding a new Machine Learning note

  1. Create the MDX file at:
    src/app/notes/machine-learning/[id]/notes/your-note-name.mdx
    

    Write your content in MDX format. You can use KaTeX math with $inline$ and $$block$$ syntax.

  2. Register the note in src/app/notes/machine-learning/[id]/data.ts:
// Add a lazy import at the top of the component array or inline:
{
  id: "your-note-id",               // URL slug (e.g. "your-note-id" -> /notes/machine-learning/your-note-id)
  title: "Your Note Title",
  component: lazy(() => import("./notes/your-note-name.mdx")),
}
  1. The note will automatically:
    • Appear in the ML notes listing at /notes/machine-learning
    • Be accessible at /notes/machine-learning/your-note-id
    • Get a static page generated during build

For Reinforcement Learning notes, follow the same steps but in the reinforcement-learning directory instead.

Adding a new note category

  1. Create the directory structure:
    src/app/notes/your-category/
    ├── page.tsx                      # Category listing page
    └── [id]/
        ├── page.tsx                  # Server component
        ├── client.tsx                # Client component
        ├── data.ts                   # Note entries
        └── notes/                    # MDX files
    
  2. page.tsx (category listing) - Use LinksSection to display note links:
    import LinksSection from "../../_components/linksSection";
    import { data } from "./[id]/data";
    
    export default function YourCategoryPage() {
      const links = data.map((note) => ({
        title: note.title,
        href: `/notes/your-category/${note.id}`,
      }));
      return <LinksSection title="Your Category" links={links} />;
    }
    
  3. [id]/page.tsx (server component) - Required for static export:
    import { data } from "./data";
    import YourCategoryNote from "./client";
    
    export function generateStaticParams() {
      return data.map((note) => ({ id: note.id }));
    }
    
    export default async function Page({ params }: { params: Promise<{ id: string }> }) {
      await params;
      return <YourCategoryNote />;
    }
    
  4. [id]/client.tsx (client component) - Renders the MDX content:
    "use client";
    import { useEffect, useMemo } from "react";
    import { useParams, useRouter } from "next/navigation";
    import MDXSection from "../../../_components/markdown/mdxSection";
    import { data } from "./data";
    import { ArrowLeft2 } from "iconsax-react";
    
    export default function YourCategoryNote() {
      const { id } = useParams();
      const router = useRouter();
    
      useEffect(() => {
        if (!id || !data.find((note) => note.id === id)) {
          router.replace("/notes/your-category");
        }
      }, [id, router]);
    
      const title = useMemo(() => data.find((note) => note.id === id)?.title, [id]);
      const Component = useMemo(() => data.find((note) => note.id === id)?.component, [id]);
    
      return (
        <>
          <ArrowLeft2 size={20} className="fixed top-4 left-4 text-white opacity-50 hover:opacity-100 cursor-pointer" onClick={() => router.replace("/notes/your-category")} />
          <MDXSection title={title ?? "Your Category"}>{Component && <Component />}</MDXSection>
        </>
      );
    }
    
  5. [id]/data.ts - Define your note entries:
    import { lazy } from "react";
    
    export const data = [
      {
        id: "note-slug",
        title: "Note Title",
        component: lazy(() => import("./notes/note-slug.mdx")),
      },
    ];
    
  6. Update the notes grid in src/app/notes/notesList.tsx to add a card for your new category.

How to Update Portfolio Sections

All portfolio data is in src/data/. Edit the relevant file:

Section File
Education src/data/education.ts
Experience src/data/experience.ts
Projects src/data/projects.ts
Publications src/data/publications.ts
Skills src/data/skills.ts
Miscellaneous src/data/miscellaneous.ts

Each file exports a typed array. Follow the existing entry format to add new items.


Deployment (GitHub Pages)

The project is configured for static export with output: "export" in next.config.js.

  1. Run npm run build to generate the out/ directory
  2. The out/ directory contains the full static site
  3. Push to the main branch (or configure GitHub Pages to serve from a specific branch/directory)
  4. A .nojekyll file should be present in the root to prevent GitHub Pages from processing files with Jekyll

Available Scripts

Command Description
npm run dev Start development server (localhost:3000)
npm run build Build static export to out/
npm run start Start production server
npm run lint Run ESLint

Notes