Technical SEO Checklist for Developers
Technical SEO is the foundation. Without it, the best content is worthless. This checklist covers everything you need to know as a developer – with code examples you can implement directly.
1. Crawling & Indexing
robots.txt
Location: /robots.txt
User-agent: *
Allow: /
# Block admin and API routes
Disallow: /admin/
Disallow: /api/
Disallow: /_next/
# Sitemap location
Sitemap: https://example.com/sitemap.xml
Checklist:
- robots.txt exists and is accessible
- Important pages are not blocked
- Sitemap location specified
- API/Admin areas blocked
Test: site:yourdomain.com in Google – do you see all important pages?
XML Sitemap
Location: /sitemap.xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://example.com/</loc>
<lastmod>2026-01-21</lastmod>
<changefreq>weekly</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://example.com/blog/article-1</loc>
<lastmod>2026-01-15</lastmod>
<changefreq>monthly</changefreq>
<priority>0.8</priority>
</url>
</urlset>
For Next.js (auto-generate):
// next-sitemap.config.js
module.exports = {
siteUrl: 'https://example.com',
generateRobotsTxt: true,
sitemapSize: 7000,
changefreq: 'weekly',
priority: 0.7,
exclude: ['/admin/*', '/api/*'],
}
Checklist:
- Sitemap contains all important URLs
- lastmod dates are current
- Sitemap submitted to Search Console
- No 4xx/5xx URLs in sitemap
Canonical Tags
Avoid duplicate content:
<link rel="canonical" href="https://example.com/blog/article" />
Typical problems:
/blog/articlevs/blog/article/http://vshttps://www.vs non-www- URL parameters (e.g.,
?utm_source=...)
Next.js Example:
import Head from 'next/head';
export default function Page() {
return (
<Head>
<link rel="canonical" href="https://example.com/page" />
</Head>
);
}
2. Core Web Vitals
LCP (Largest Contentful Paint)
Target: < 2.5 seconds
Common problems and solutions:
1. Optimize images:
<!-- Before -->
<img src="hero.jpg" />
<!-- After -->
<img
src="hero.webp"
srcset="hero-400.webp 400w, hero-800.webp 800w, hero-1200.webp 1200w"
sizes="(max-width: 400px) 400px, (max-width: 800px) 800px, 1200px"
loading="eager"
fetchpriority="high"
alt="Hero Image"
/>
2. Preload critical resources:
<link rel="preload" href="/fonts/main.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/hero.webp" as="image">
3. Server Response Time:
- Use CDN
- Implement caching
- Server-Side Rendering for critical content
FID/INP (First Input Delay / Interaction to Next Paint)
Target: < 100ms (FID), < 200ms (INP)
Main problem: JavaScript blocks the main thread
Solutions:
1. Code Splitting:
// Dynamic import
const HeavyComponent = dynamic(() => import('./HeavyComponent'), {
loading: () => <Skeleton />,
});
2. Web Workers for heavy calculations:
// worker.js
self.onmessage = function(e) {
const result = heavyCalculation(e.data);
self.postMessage(result);
};
// main.js
const worker = new Worker('worker.js');
worker.postMessage(data);
worker.onmessage = (e) => console.log(e.data);
3. Debounce and Throttle:
const handleScroll = throttle(() => {
// Expensive operation
}, 100);
CLS (Cumulative Layout Shift)
Target: < 0.1
Main problems and solutions:
1. Images without dimensions:
<!-- Bad -->
<img src="photo.jpg" />
<!-- Good -->
<img src="photo.jpg" width="800" height="600" />
<!-- Or with aspect-ratio -->
<img src="photo.jpg" style="aspect-ratio: 4/3; width: 100%;" />
2. Ads and Embeds:
.ad-container {
min-height: 250px; /* Reserve space */
}
3. Web Fonts:
@font-face {
font-family: 'CustomFont';
src: url('/font.woff2') format('woff2');
font-display: swap; /* or optional */
size-adjust: 100%;
ascent-override: 95%;
descent-override: 20%;
}
3. Structured Data (Schema Markup)
Article Schema
{
"@context": "https://schema.org",
"@type": "Article",
"headline": "Technical SEO Checklist for Developers",
"description": "Everything developers need to know about technical SEO",
"author": {
"@type": "Person",
"name": "Jonas Höttler",
"url": "https://hoettler.com"
},
"datePublished": "2026-06-30",
"dateModified": "2026-06-30",
"publisher": {
"@type": "Organization",
"name": "Höttler Tech",
"logo": {
"@type": "ImageObject",
"url": "https://hoettler.com/logo.png"
}
},
"image": "https://hoettler.com/article-image.jpg"
}
FAQ Schema
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "What is technical SEO?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Technical SEO encompasses all technical optimizations..."
}
}
]
}
HowTo Schema
Perfect for tutorials:
{
"@context": "https://schema.org",
"@type": "HowTo",
"name": "How to improve Core Web Vitals",
"step": [
{
"@type": "HowToStep",
"name": "Optimize images",
"text": "Convert images to WebP and use responsive images."
}
]
}
Implementation in Next.js:
export default function Article({ data }) {
const jsonLd = {
"@context": "https://schema.org",
"@type": "Article",
headline: data.title,
// ...
};
return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
{/* Article content */}
</>
);
}
4. Mobile Optimization
Viewport Meta Tag
<meta name="viewport" content="width=device-width, initial-scale=1" />
Mobile-First CSS
/* Base styles (mobile) */
.container {
padding: 1rem;
}
/* Tablet */
@media (min-width: 768px) {
.container {
padding: 2rem;
}
}
/* Desktop */
@media (min-width: 1024px) {
.container {
padding: 3rem;
max-width: 1200px;
}
}
Touch Targets
button, a {
min-height: 48px;
min-width: 48px;
padding: 12px;
}
5. HTTPS & Security
HSTS Header
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
In Next.js (next.config.js):
module.exports = {
async headers() {
return [
{
source: '/:path*',
headers: [
{
key: 'Strict-Transport-Security',
value: 'max-age=31536000; includeSubDomains'
}
]
}
]
}
}
Content Security Policy
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://www.googletagmanager.com; style-src 'self' 'unsafe-inline';
6. Internationalization (i18n)
hreflang Tags
<link rel="alternate" hreflang="de" href="https://example.com/de/page" />
<link rel="alternate" hreflang="en" href="https://example.com/en/page" />
<link rel="alternate" hreflang="x-default" href="https://example.com/en/page" />
In the Sitemap
<url>
<loc>https://example.com/de/page</loc>
<xhtml:link rel="alternate" hreflang="de" href="https://example.com/de/page"/>
<xhtml:link rel="alternate" hreflang="en" href="https://example.com/en/page"/>
</url>
7. Performance Optimization
Resource Hints
<!-- DNS Prefetch for external domains -->
<link rel="dns-prefetch" href="//fonts.googleapis.com">
<!-- Preconnect for critical domains -->
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<!-- Preload for critical resources -->
<link rel="preload" href="/critical.css" as="style">
<!-- Prefetch for likely needed resources -->
<link rel="prefetch" href="/next-page.js">
Lazy Loading
<!-- Native Lazy Loading -->
<img src="image.jpg" loading="lazy" alt="...">
<!-- Intersection Observer for complex cases -->
<script>
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.src = entry.target.dataset.src;
observer.unobserve(entry.target);
}
});
});
document.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));
</script>
The Ultimate Checklist
Crawling & Indexing
- robots.txt correctly configured
- XML Sitemap present and current
- Sitemap submitted to Search Console
- Canonical tags on all pages
- No duplicate content issues
Core Web Vitals
- LCP < 2.5s
- INP < 200ms
- CLS < 0.1
- Images optimized (WebP, responsive)
- Fonts optimized (preload, font-display)
Structured Data
- Article Schema on blog posts
- FAQ Schema where relevant
- Organization Schema on homepage
- Schema validated (Rich Results Test)
Mobile
- Viewport Meta Tag present
- Mobile-responsive design
- Touch targets minimum 48x48px
- No horizontal scrollbars
Security
- HTTPS everywhere
- HSTS header set
- Mixed content avoided
Internationalization
- hreflang tags correct
- Language specified in HTML tag
- Language versions in sitemap
Tools for Verification
| Tool | Checks | Link |
|---|---|---|
| Google Search Console | Indexing, errors | search.google.com/search-console |
| PageSpeed Insights | Core Web Vitals | pagespeed.web.dev |
| Rich Results Test | Structured Data | search.google.com/test/rich-results |
| Mobile-Friendly Test | Mobile optimization | search.google.com/test/mobile-friendly |
| Lighthouse | Everything | In Chrome DevTools |
Conclusion
Technical SEO is not a one-time project – it's continuous work. But once set up correctly, it forms the foundation for all further SEO measures.
The most important priorities:
- Be crawlable – robots.txt, sitemap, no blockers
- Be fast – optimize Core Web Vitals
- Be structured – implement Schema Markup
- Mobile-first – responsive, touch-friendly
Use the checklist as a starting point and work through it systematically.
Want to learn more about keyword research without expensive tools? Our guide SEO for Tech Blogs shows you free methods.


