NNicheStackTutorials
← All tutorials
SEO & Web Vitals

Internal Link Structure for Small Tech Blogs (Hub Pages, Contextual Links, Orphan Fix)

47 orphan pages fixed. Topic hub template in Hugo. Organic sessions +31% in 90 days on 180-post blog.

·13 min read·SEO & Web Vitals
Internal Link Structure for Small Tech Blogs (Hub Pages, Contextual Links, Orphan Fix) cover

Audit tool: Ahrefs Site Audit → Links → orphan pages (no internal inlinks). Found: 47 published posts with zero internal links pointing to them. Cause: New posts added without linking from older related content.

Hub-and-spoke model

/pillar/seo-guide/          ← hub (links to all SEO posts)
  ├── /posts/core-web-vitals/
  ├── /posts/lazy-load-ads/
  └── /posts/image-optimization/

/pillar/monetization-guide/  ← hub
  ├── /posts/adsense-markdown/
  └── /posts/ad-layout-rpm/

Hub pages are curated lists with 150+ words intro — not bare link dumps.

Hugo hub template

content/pillar/seo-guide.md:

---
title: "SEO & Web Vitals — Complete Guide"
description: "Every SEO tutorial on this site, ordered beginner to advanced."
---

Start with [Core Web Vitals](/posts/core-web-vitals/) if ads are slowing your site.

## Performance
- [Lazy-load ads](/posts/lazy-load-ads/)
- [Image optimization](/posts/image-optimization/)

## Crawling
- [Sitemap automation](/posts/sitemap-xml/)
- [robots.txt](/posts/robots-txt/)

Contextual links in every post

Rule: each post links to 2–4 related posts in body copy, not just "Related posts" footer.

Bad: See also: [link] at bottom only. Good: "When you've fixed LCP, the next bottleneck is usually CLS from ads."

Automated related posts (Hugo)

{{- $related := where site.RegularPages "Params.topic" .Params.topic | first 5 -}}
<aside class="related">
  <h2>Related</h2>
  <ul>
  {{- range $related }}
    {{- if ne .Permalink $.Permalink }}
    <li><a href="{{ .Permalink }}">{{ .Title }}</a></li>
    {{- end }}
  {{- end }}
  </ul>
</aside>

Filter by topic tag — better than random recent posts.

Fix orphans in bulk

Script to list orphans:

# posts with no incoming links (simplified — use Ahrefs for production)
for f in content/posts/*.md; do
  slug=$(basename "$f" .md)
  count=$(grep -r "$slug" content/ --include='*.md' | wc -l)
  [ "$count" -lt 2 ] && echo "ORPHAN: $slug ($count refs)"
done

For each orphan: add 2 links FROM existing high-traffic posts.

Breadcrumb internal links

<nav aria-label="Breadcrumb">
  <a href="/">Home</a><a href="/pillar/seo-guide/">SEO</a><span>{{ .Title }}</span>
</nav>

Breadcrumbs = automatic parent hub link on every post.

Anchor text variety

Don't use "click here". Use descriptive anchors:

  • lazy-load AdSense without hurting LCP
  • build-time OG image generation

Link equity on ad-monetized blogs

Category pages with ads are fine. Don't noindex hubs — they're your best internal link targets.

Results (90 days)

Orphan pages: 47 → 0
Avg internal links per post: 1.2 → 4.8
Organic sessions: +31%
Top 10 rankings: 34 → 51 keywords

Internal linking is free SEO. Hub pages organize users AND crawlers.

Tags: Internal LinkingTopic ClustersOrphan PagesHugo