Technical SEO audit and implementation: structured data (JSON-LD), meta tags, Open Graph/Twitter Cards, XML sitemap, robots.txt, Core Web Vitals optimization, crawl budget management, and canonical URL strategy.
The canonical home for this skill is seo-technical in JaviMontano/mao-sovereign-architect
"Technical SEO is the foundation. No amount of content or links helps if Googlebot can't parse, render, or index your pages correctly."
Five-step procedure to audit and implement technical SEO: metadata architecture, structured data for rich results, sitemap and robots.txt configuration, Core Web Vitals as ranking signals, and crawl budget management for large sites.
robots.txt — verify no accidental Disallow: / rules blocking prod.<meta name="robots"> on key pages — confirm no noindex leaking from staging.curl -I https://domain.com/page — check for redirects, X-Robots-Tag headers.robots.txt PatternUser-agent: *
Allow: /
# Block parameterized facets that don't add indexable value
Disallow: /search?*
Disallow: /products?sort=*
Disallow: /products?page=*
# Block admin, API, auth
Disallow: /admin/
Disallow: /api/
Disallow: /_next/
Sitemap: https://www.example.com/sitemap.xml
Sitemap: https://www.example.com/sitemap-blog.xml// app/layout.tsx — root metadata
import { Metadata } from 'next';
export const metadata: Metadata = {
metadataBase: new URL('https://www.example.com'),
title: {
default: 'Company Name — Value Proposition',
template: '%s | Company Name',
},
description: 'Under 160 characters. Imperative, specific, keyword-rich.',
robots: {
index: true,
follow: true,
googleBot: {
index: true,
follow: true,
'max-video-preview': -1,
'max-image-preview': 'large',
'max-snippet': -1,
},
},
alternates: {
canonical: 'https://www.example.com',
languages: {
'en-US': 'https://www.example.com',
'es-MX': 'https://es.example.com',
},
},
};// app/blog/[slug]/page.tsx
export async function generateMetadata({ params }): Promise<Metadata> {
const post = await getPost(params.slug);
return {
title: post.title,
description: post.excerpt,
openGraph: {
type: 'article',
title: post.title,
description: post.excerpt,
url: `https://www.example.com/blog/${post.slug}`,
images: [{ url: post.ogImage, width: 1200, height: 630, alt: post.title }],
publishedTime: post.publishedAt,
modifiedTime: post.updatedAt,
authors: [post.author.url],
},
twitter: {
card: 'summary_large_image',
title: post.title,
description: post.excerpt,
images: [post.ogImage],
creator: '@handle',
},
};
}// components/StructuredData.tsx
export function OrganizationSchema() {
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify({
'@context': 'https://schema.org',
'@type': 'Organization',
name: 'Example Company',
url: 'https://www.example.com',
logo: 'https://www.example.com/logo.png',
sameAs: [
'https://www.linkedin.com/company/example',
'https://twitter.com/example',
],
}),
}}
/>
);
}
export function ArticleSchema({ post }: { post: Post }) {
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify({
'@context': 'https://schema.org',
'@type': 'Article',
headline: post.title,
description: post.excerpt,
image: post.ogImage,
datePublished: post.publishedAt,
dateModified: post.updatedAt,
author: { '@type': 'Person', name: post.author.name, url: post.author.url },
publisher: {
'@type': 'Organization',
name: 'Example Company',
logo: { '@type': 'ImageObject', url: 'https://www.example.com/logo.png' },
},
mainEntityOfPage: {
'@type': 'WebPage',
'@id': `https://www.example.com/blog/${post.slug}`,
},
}),
}}
/>
);
}{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "How does X work?",
"acceptedAnswer": {
"@type": "Answer",
"text": "X works by... [full answer, not truncated]"
}
}
]
}// app/sitemap.ts — Next.js dynamic sitemap
import { MetadataRoute } from 'next';
import { getAllPosts, getAllProducts } from '@/lib/api';
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const [posts, products] = await Promise.all([getAllPosts(), getAllProducts()]);
const staticPages: MetadataRoute.Sitemap = [
{ url: 'https://www.example.com', lastModified: new Date(), changeFrequency: 'daily', priority: 1.0 },
{ url: 'https://www.example.com/about', changeFrequency: 'monthly', priority: 0.8 },
{ url: 'https://www.example.com/blog', changeFrequency: 'daily', priority: 0.9 },
];
const postPages: MetadataRoute.Sitemap = posts.map((post) => ({
url: `https://www.example.com/blog/${post.slug}`,
lastModified: new Date(post.updatedAt),
changeFrequency: 'weekly',
priority: 0.7,
}));
return [...staticPages, ...postPages];
}// Preload hero image — most impactful LCP fix
// Next.js Image with priority:
<Image src="/hero.webp" alt="..." width={1200} height={630} priority />
// Generates: <link rel="preload" as="image" fetchpriority="high" />/* Always set explicit dimensions on images and embeds */
img { width: 100%; height: auto; aspect-ratio: attr(width) / attr(height); }
/* Reserve space for dynamic content — fonts */
@font-face {
font-display: swap; /* Prevents invisible text during font load */
}// Defer non-critical JS
<Script src="/analytics.js" strategy="lazyOnload" />
// Yield to browser for long tasks
async function processLargeList(items: Item[]) {
for (const item of items) {
processItem(item);
// yield every 50ms to allow browser to handle input
if (performance.now() % 50 < 1) {
await new Promise(resolve => setTimeout(resolve, 0));
}
}
}# Lighthouse CI in GitHub Actions
npx lhci autorun \
--collect.url=https://example.com \
--upload.target=temporary-public-storage
# PageSpeed Insights API
curl "https://www.googleapis.com/pagespeedonline/v5/runPagespeed?url=https://example.com&strategy=mobile&key=$PSI_API_KEY" \
| jq '.lighthouseResult.categories.performance.score'<title> and <meta description> — No duplicates, under 60/160 chars.fetchPriority="high".noindex on production pages — Staging noindex not leaked to prod.<title> tag in <body> — Some frameworks accidentally render it outside <head>; crawlers may ignore it.loading="lazy" on the above-the-fold hero image delays LCP by 200-500ms.@import in stylesheets — Each @import is a serial round trip; use <link> tags or bundler.<head>.robots.txt blocking JS/CSS — Googlebot cannot render pages if core assets are disallowed; renders mobile-unfriendly.b56591e
Canonical home
since Aug 28, 2026
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.