Skip to main content
Back to all posts
Blog Update

Update #1

A deep dive into refactoring this portfolio: migrating to dynamic routing, optimizing the Velite MDX pipeline under Turbopack, and structuring metadata.

3 min read

Over the past few days, I restructured and optimized this site to improve performance, maintainability, and developer experience. What started as a basic static layout evolved into a modular, type-safe content platform.

Here is a breakdown of what changed, the architectural decisions behind the migration, and how technical blockers like Turbopack module resolution were resolved.


Key Objectives#

  1. Scalable Routing Architecture: Transition from hardcoded subpages to data-driven dynamic routes (app/(site)/projects/[slug] and app/(site)/blog/[slug]).
  2. Next.js 16 & Turbopack Compatibility: Handle asynchronous route parameters (params: Promise<...>) and adapt bundler hooks.
  3. Type-Safe Content Pipeline: Leverage Velite for compile-time schema validation, automated reading time estimation, and rehype-based syntax highlighting.
  4. Automated SEO & Structured Data: Implement dynamic OpenGraph images, automated sitemaps, JSON-LD (BlogPosting), and contextual keyword generation.

1. Data-Driven Projects & Dynamic Routing#

Previously, project showcases lived in static subdirectories. This pattern was refactored into a centralized data model:

// config/projects.ts
export interface Project {
  slug: string;
  title: string;
  description: string;
  category: "Security & Tools" | "Web Applications" | "Libraries" | "Infrastructure";
  tags: string[];
  githubUrl?: string;
  downloadUrl?: string;
  featured: boolean;
  highlights?: string[];
}
 

With app/(site)/projects/[slug]/page.tsx, new project pages are automatically statically generated at build time via generateStaticParams() without modifying route structures.


2. Resolving #site/content with Turbopack#

Because Turbopack handles module resolution differently from Webpack, standard Webpack compiler plugins for Velite do not execute automatically.

To ensure the .velite data directory builds reliably before Next.js inspects the module tree, the setup was updated across three files:

Subpath Imports in package.json#

{
  "imports": {
    "#site/content": "./.velite/index.js"
  },
  "scripts": {
    "predev": "velite",
    "prebuild": "velite",
    "dev": "next dev",
    "build": "next build"
  }
}
 

TypeScript Path Mapping in tsconfig.json#

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./*"],
      "#site/content": ["./.velite"]
    }
  }
}
 

Programmatic Startup in next.config.ts#

// next.config.ts
import type { NextConfig } from "next";
 
const isDev = process.env.NODE_ENV === "development";
 
if (!process.env.VELITE_STARTED) {
  process.env.VELITE_STARTED = "1";
  import("velite").then((m) =>
    m.build({
      watch: isDev,
      clean: !isDev,
    })
  );
}
 
const nextConfig: NextConfig = {
  reactStrictMode: true,
  poweredByHeader: false,
  compress: true,
};
 
export default nextConfig;
 

3. Enhanced MDX Primitives & Code Highlighting#

The MDX rendering pipeline now supports custom interactive callouts and code blocks with syntax highlighting powered by rehype-pretty-code:

// components/mdx/mdx-content.tsx
const components = {
  a: CustomLink,
  img: CustomImage,
  Image: CustomImage,
  pre: MdxPre,
  code: MdxInlineCode,
  Callout,
  Badge,
};
 

This enables cleaner technical documentation and CTF writeups, allowing responsive multi-language code snippets alongside annotated warnings, flags, and notes:


4. SEO & Dynamic Metadata Pipeline#

Each post and project page now generates its own contextual metadata and Schema.org structured data dynamically:

  • JSON-LD: Embedded BlogPosting and Person schemas for rich search results.
  • Dynamic Keywords: Aggregates post tags, category definitions, and primary topic markers.
  • OpenGraph & Twitter Cards: Dynamic social sharing cards generated via Edge API routes (app/api/og).

Summary#

This update establishes a solid foundation for publishing future technical writeups, CTF solutions, and open-source tooling. The full source code and project configuration are maintained on GitHub.