Technical SEO for Next.js has never been easier — the framework handles most of the heavy lifting if you know where to configure it. Here is the complete guide to ranking a Next.js app in 2026, with real code, not theory.
Metadata: The Foundation
Every page needs a unique title, description, and canonical URL. In Next.js App Router, export a Metadata object from your page.tsx.
// app/services/page.tsx
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Full Stack Development Services | Umar Saleem — Punjab, Pakistan',
description: 'Hire a Full Stack AI Engineer from Punjab, Pakistan. MVP development, SaaS architecture, AI automation for global clients. Reply within 24 hours.',
keywords: ['Full Stack Developer Pakistan', 'SaaS Development Pakistan', 'AI Developer for hire'],
openGraph: {
title: 'Full Stack Development Services | Umar Saleem',
description: 'MVP development and AI engineering from Punjab, Pakistan.',
url: 'https://umarsaleemdev.com/services',
images: [{ url: '/og/services.png', width: 1200, height: 630 }],
},
alternates: {
canonical: 'https://umarsaleemdev.com/services',
},
}Structured Data with JSON-LD
Structured data helps search engines understand what your content is. For a developer portfolio, include Person and WebSite schema at minimum.
// In your root layout or page component
const personSchema = {
"@context": "https://schema.org",
"@type": "Person",
"name": "Umar Saleem",
"jobTitle": "Full Stack AI Engineer",
"url": "https://umarsaleemdev.com",
"address": {
"@type": "PostalAddress",
"addressLocality": "Punjab",
"addressCountry": "PK"
}
}
// In your JSX
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(personSchema) }}
/>Sitemaps and Robots.txt
// app/sitemap.ts
import { MetadataRoute } from 'next'
export default function sitemap(): MetadataRoute.Sitemap {
return [
{ url: 'https://umarsaleemdev.com', changeFrequency: 'weekly', priority: 1 },
{ url: 'https://umarsaleemdev.com/services', changeFrequency: 'monthly', priority: 0.8 },
{ url: 'https://umarsaleemdev.com/about', changeFrequency: 'monthly', priority: 0.7 },
// Dynamic blog posts
...posts.map(p => ({
url: `https://umarsaleemdev.com/blog/${p.slug}`,
lastModified: new Date(p.date),
priority: 0.6,
})),
]
}Core Web Vitals in Next.js
- LCP (Largest Contentful Paint): Add priority prop to your hero image. Use next/image always.
- CLS (Cumulative Layout Shift): Always set width and height on images. Reserve space for dynamic content.
- INP (Interaction to Next Paint): Keep client components lean. Move data fetching to server.
- Use next/font for fonts — eliminates FOUT and layout shift from custom fonts.
The single biggest SEO investment for a developer portfolio is writing content that answers real questions. One good blog post outranks ten keyword-stuffed pages.