Modernizing my Portfolio: From Vanilla PHP to Next.js (and why my server thought I was DDOSing it)

Published: (January 12, 2026 at 03:43 PM EST)
3 min read
Source: Dev.to

Source: Dev.to

Why a redesign?

New, clean, fast, and smooth. While countless creative designers inspire me, this transition marks a milestone. It reflects my evolution as a (Spring Boot) developer. Vanilla PHP served me well for years, but a seamless user experience and optimized rendering required a technology pivot. Switching to Next.js lets me utilize Static Site Generation (SSG).

  • Before: Server‑side rendering on every request, wasting precious milliseconds.
  • Now: Pre‑rendered HTML pages served instantly, delivering an “instant‑on” experience. Dynamic data can still be fetched via client‑side APIs when needed.

SEO Optimizations: The Technical Foundation

Good SEO isn’t an add‑on; it’s rooted deep in the architecture. Inspired by my own SEO strategies for Devs (German), I’ve implemented the following:

  • Structured data: A central Person schema links my portfolio to my tools on Blogkurs (a blog of mine) using sameAs and rel="me" to validate my identity across domains.
  • Semantic HTML: Using , , “, and proper header hierarchies (h1h6) helps crawlers understand content relevance without guesswork.
  • Next.js Metadata API: Every subpage receives dynamic, highly optimized meta tags and OpenGraph images, improving rankings and social sharing previews.
  • Performance: Image optimization (WebP/AVIF), font preloading, and removal of render‑blocking scripts achieve top scores in Core Web Vitals.

Note: Accessibility still needs more work.

Prefetching on Shared Hosting

Switching to a JavaScript framework increases complexity. Configuring .htaccess for static exports and handling hydration errors requires deep technical knowledge to avoid SEO losses.

  • Automatic pre‑fetching: By default, Next.js prefetches all linked pages as soon as they appear in the viewport.
  • Issue on Apache shared hosting: This can generate a massive number of requests in a short time, triggering security modules like mod_evasive or fail2ban, which interpret the traffic as a DDOS attack.

During a static export, my server automatically blocked my IP. The fix was to disable prefetching:

import Link, { LinkProps } from 'next/link';
import { ReactNode } from 'react';

interface SafeLinkProps extends LinkProps {
  children: ReactNode;
  className?: string;
}

export default function SafeLink({ children, ...props }: SafeLinkProps) {
  return (
    
      {children}
    
  );
}

From Classic CMS to MDX

Classic CMSs like WordPress limit my workflow. Bulky WYSIWYG editors and cluttered menus feel foreign to a developer’s workflow, forcing a structure that blocks creativity and speed.

Chosen architecture

  • Markdown (MDX) as standard: I write content where I write code – in my IDE. It’s fast, clean, and versionable.
  • Design freedom: Customizing every page with React and Tailwind CSS makes me faster and more relaxed.
  • Version control via Git: Every content update is a commit, providing full history, branches, and clean deployments.

Conclusion

The switch to Next.js wasn’t for its own sake; it’s the foundation for positioning my projects as a trusted entity on the web. Modern software must speak the language of search engines fluently. For developers uncomfortable with traditional CMS environments, static site generators offer ultimate liberation.

Originally published in German on my portfolio: Hendrik Haustein Portfolio.

Back to Blog

Related posts

Read more »