Seo internal linking
Skill mvstepanek/nextjs-ecommerce-seo-skills/skills/seo-internal-linking
Internal linking strategy and rules for SEO. Use when adding navigation, breadcrumbs, footer links, related products, cross-links, or language switcher components.From its SKILL.md
npx -y skills add mvstepanek/nextjs-ecommerce-seo-skills --skill seo-internal-linkingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
8.1 KB, ~1.9k tokens by cl100k_base, as published. Nobody here has run it
Internal Linking SEO Guidelines
Follow these rules when building navigation, breadcrumbs, and cross-linking features.
Why Internal Linking Matters
Internal links distribute PageRank (ranking power) across your site and help search engines discover pages. A product page with 50 internal links pointing to it will outrank an identical page with only 1 internal link.
Use next/link for All Internal Links
- Always use
<Link>fromnext/linkfor internal navigation — never raw<a>tags - next/link enables client-side navigation (faster) and prefetching (even faster)
- Raw
<a>tags trigger full page reloads
// GOOD
import Link from 'next/link';
<Link href={`/${locale}/products/${product.id}/${product.slug}`}>
{product.name}
</Link>
// BAD
<a href={`/${locale}/products/${product.id}/${product.slug}`}>
{product.name}
</a>
Breadcrumbs
Every page except the homepage should have visible breadcrumbs AND matching BreadcrumbList schema. Note: as of January 2025, Google no longer displays breadcrumbs in mobile search results (they still appear on desktop). Breadcrumbs remain valuable for desktop SERP display, site hierarchy understanding, and user navigation.
Implementation Rules
- Mirror the URL/site hierarchy — Home > Category > Subcategory > Product
- Every level is a clickable link except the current page
- Current page is plain text (not a link)
- Consistent across locales — same hierarchy, translated labels
- Visible in the page — not hidden, not only in schema
- Minimum 2 breadcrumb items required for Google to recognize the trail
- Represent the user's navigation path, not necessarily the URL hierarchy
// Example breadcrumbs component — adapt to your project
import Link from 'next/link';
import { JsonLd } from './JsonLd';
// Example import — use your project's actual config
import { siteConfig } from '@/config/site';
interface Crumb {
label: string;
href?: string;
}
export function Breadcrumbs({ items, locale }: { items: Crumb[]; locale: string }) {
const schema = {
"@type": "BreadcrumbList",
itemListElement: items.map((item, index) => ({
"@type": "ListItem",
position: index + 1,
name: item.label,
...(item.href ? { item: `${siteConfig.url}${item.href}` } : {}),
})),
};
return (
<>
<JsonLd data={{ "@context": "https://schema.org", ...schema }} />
<nav aria-label="Breadcrumb">
<ol>
{items.map((item, index) => (
<li key={index}>
{item.href ? (
<Link href={item.href}>{item.label}</Link>
) : (
<span aria-current="page">{item.label}</span>
)}
</li>
))}
</ol>
</nav>
</>
);
}
// Usage on a product page:
<Breadcrumbs
locale="en-GB"
items={[
{ label: 'Home', href: `/${locale}/` },
{ label: 'Electronics', href: `/${locale}/categories/electronics` },
{ label: 'Wireless Headphones', href: `/${locale}/categories/electronics/wireless-headphones` },
{ label: 'Widget Pro 500W' }, // Current page — no href
]}
/>
Anchor Text
Anchor text (the clickable text of a link) tells search engines what the target page is about.
Rules
- Use descriptive text — the product name, category name, or action
- Never use "click here" or "read more" or "learn more" as the sole anchor text
- Include keywords naturally — "View our industrial widgets" not "click here for products"
- Vary anchor text — don't use the exact same text for every link to the same page
- Don't over-optimize — natural language, not keyword-stuffed
// GOOD
<Link href={`/${locale}/categories/electronics/wireless-headphones`}>
Wireless Headphones
</Link>
<Link href={`/${locale}/products/${id}/${slug}`}>
{product.name} — {product.shortSpec}
</Link>
// BAD
<Link href={url}>Click here</Link>
<Link href={url}>Read more</Link>
<Link href={url}>Link</Link>
Related Products / Cross-Linking
Product pages should link to related products:
- Same category — other products in a similar range
- Compatible accessories — add-ons, parts, maintenance kits for this product
- Upgrade/downgrade — next model up/down in the range
- Bundles — if this product is part of a bundle, link to the bundle
// components/RelatedProducts.tsx
export function RelatedProducts({ products, locale }: Props) {
return (
<section>
<h2>Related Products</h2>
<ul>
{products.map(product => (
<li key={product.id}>
<Link href={`/${locale}/products/${product.id}/${product.slug}`}>
<Image src={product.image} alt={`${product.name} - ${product.shortSpec}`} width={200} height={150} />
<span>{product.name}</span>
</Link>
</li>
))}
</ul>
</section>
);
}
Navigation (Header/Footer)
Header Navigation
- Include links to top-level categories
- Include subcategory links in dropdown menus
- Links should use the current locale prefix
- Include the language/country switcher
Footer Navigation
- Include links to: all top-level categories, FAQ, contact, legal, services
- Consistent across all pages and locales — same structure, translated labels
- Footer links help search engines discover important pages from every page on the site
Language Switcher
The language/country switcher MUST:
- Link to the same page in the target locale — not the homepage
- Preserve the full URL path — switching from
/en-GB/products/123/widget-proto French →/fr-FR/products/123/widget-pro - Be a visible, crawlable link — not hidden behind JavaScript-only interaction
- Use
<Link>from next/link
// components/LanguageSwitcher.tsx
export function LanguageSwitcher({ currentLocale, currentPath }: Props) {
return (
<nav aria-label="Language">
{ALL_LOCALES.map(locale => (
<Link
key={locale}
href={`/${locale}${currentPath}`}
hrefLang={locale}
aria-current={locale === currentLocale ? 'true' : undefined}
>
{getLocaleName(locale)}
</Link>
))}
</nav>
);
}
Why the switcher matters for SEO: Search engine crawlers use the language switcher to discover locale variants of pages. If the switcher only links to homepages, crawlers won't efficiently find all localized versions.
Nofollow Usage
Use rel="nofollow" sparingly and only where appropriate:
| Link Type | nofollow? | Reason |
|---|---|---|
| Internal navigation | No | You want PageRank to flow |
| Internal product links | No | You want PageRank to flow |
| External affiliate links | Yes | Paid/sponsored links |
| User-generated content | Yes | Untrusted content |
| Login/register links | Optional | Low SEO value |
| Social media links | No | But they're external, so limited value |
Default rule: Do NOT add nofollow to internal links. Only add it to external untrusted or paid links.
// External affiliate link — use nofollow
<a href="https://partner-site.com" rel="nofollow noopener" target="_blank">
Partner Name
</a>
// Internal link — NEVER nofollow
<Link href={`/${locale}/products/${id}/${slug}`}>
{productName}
</Link>
Common Mistakes to Avoid
- Raw
<a>for internal links — always use next/link - "Click here" anchor text — use descriptive text
- Language switcher linking to homepage — must preserve current page path
- Missing breadcrumbs — required on every page except homepage
- Breadcrumb schema without visible breadcrumbs — both must exist and match
- nofollow on internal links — never nofollow your own pages
- Orphan product pages — every product must be linked from at least one category page
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.
Gives 0 of the 12 instructions most marketing audience skills give in ~1.9k tokens
Counted across 690 of the 894 authors here whose files we hold, read 2026-08-07
- Apply Poppins font to headingsin 41 of 690, across 6 files
- Apply Lora font to body textin 41 of 690, across 6 files
- Use Arial fallback for headingsin 39 of 690, across 4 files
- Use Georgia fallback for body textin 39 of 690, across 4 files
- Maintain text hierarchy and formattingin 39 of 690, across 4 files
- Use accent colors for non-text shapesin 38 of 690, across 3 files
- Use RGB values for precise color matchingin 38 of 690, across 3 files
- Use brand colors for primary text and backgroundsin 36 of 690, across 1 file
- Read product marketing context file before asking questions, starting, or auditingin 35 of 690, across 23 files
- Use active voice instead of passive voicein 26 of 690, across 10 files
- Implement or generate appropriate JSON-LD structured datain 24 of 690, across 17 files
- Prioritize clarity over clevernessin 22 of 690, across 8 files
Said here and by no other author read
- use next/link for internal links
- include BreadcrumbList schema matching visible breadcrumbs
- mirror site hierarchy in breadcrumbs
- render the current page breadcrumb as plain text
- vary anchor text between links to the same page
- cross-link related products on product pages
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.