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.
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 LCPbuild-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.