Skip to content
Back to skills

Internal Link Audit

ASecurity

Internal-linking tool for an Astro site built with the new-website kit. Builds the site's inbound-link graph from dist/ and reports which pages are ORPHANED (in the sitemap but no internal link points at them), THIN (a single inbound link, no contextual in-body link), or DEEP (more than ~3 clicks from home), then suggests WHERE to add the missing links using `site-architecture`'s internal-linking strategy. The judgment-side complement to the offline `tests/orphans.spec.ts` gate. Run before a ...

  • 6 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 19, 2026
ai-agentsrustgobash

Works with

  • cli

Security analysis

A100/100

Scanned September 19, 2026

npx -y skills add karero/website-builder --skill internal-link-audit --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Internal Link Audit?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Internal Link Audit
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/karero-internal-link-audit/badge)](https://www.skillsdirectory.com/skills/karero-internal-link-audit)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: internal-link-audit
description: >
  Internal-linking tool for an Astro site built with the new-website kit.
  Builds the site's inbound-link graph from dist/ and reports which pages are
  ORPHANED (in the sitemap but no internal link points at them), THIN (a
  single inbound link, no contextual in-body link), or DEEP (more than ~3
  clicks from home), then suggests WHERE to add the missing links using
  `site-architecture`'s internal-linking strategy. The judgment-side
  complement to the offline `tests/orphans.spec.ts` gate. Run before a
  release, after adding pages, or when GSC reports orphaned/low-coverage
  pages. Trigger phrases: "internal link audit", "orphaned pages", "are any
  pages orphaned", "internal linking", "which pages link to nothing", "fix
  orphan pages", "improve internal links", "cross-link the comparison pages".
---

# Internal Link Audit

Pages rot in the OTHER direction too: not the links that go dead, but the pages that
nothing links TO. A page can be in the sitemap, pass every QA spec, and still be
**orphaned** — reachable by no internal link, so crawlers find it late (or never) and
no human browsing the site ever lands on it. The classic cause: a footer/nav link
group that lists only ONE of a sibling set (e.g. one `acme-vs-<competitor>` comparison),
leaving the rest linked from nowhere.

This is the internal-link twin of `outgoing-link-audit`:

| | offline CI gate | active sweep (this) |
|---|---|---|
| **outgoing** (dead/rebranded) | `tests/links.spec.ts` | `outgoing-link-audit` |
| **internal** (orphan/thin) | `tests/orphans.spec.ts` | **`internal-link-audit`** |

Read-only with respect to the site: it diagnoses and suggests. You apply fixes only
after the user confirms.

## The strategy it enforces

This skill does not invent its own linking rules — it **measures the built site against
the strategy in `site-architecture`** (its "Internal Linking Strategy" section, plus its
"3-Click Rule"; read them before suggesting fixes). The strategies, and how this audit
checks each:

| Strategy (from `site-architecture`) | How the audit enforces it |
|---|---|
| **No orphan pages** — every page has ≥1 inbound internal link | ORPHANS list (0 inbound) — the hard gate `tests/orphans.spec.ts` also fails on this |
| **Hub-and-spoke / topic clusters** — hub links all spokes, spokes link the hub and each other | sibling sets that don't cross-link surface as orphans/thin; suggest the hub + cross-links |
| **Important pages get the most inbound links** — home, pricing, key features | the inbound COUNT ranking shows whether your money pages actually lead |
| **Descriptive, keyword-bearing anchor text** — not "click here" | judgment: read the anchor text of the links you add/keep (see `website-seo-geo`) |
| **3-Click Rule** — important pages within ~3 clicks of home | DEEP list (>3 clicks from home, computed by BFS) |
| **Contextual links beat boilerplate** — in-body editorial links > nav/footer | THIN list flags pages held up only by the global nav/footer |

(Linking to the clean canonical URL — no `.html`, no redirect/trailing-slash hop — is link
hygiene the `navigation` spec already guards; apply it to every link you add, step 4.)

## When to run

Before a release / launch, after adding any batch of pages (the moment a set of
siblings gets created but only some get linked), or when Google Search Console flags
"Crawled - currently not indexed" / "Discovered - not indexed" / orphaned pages.

Unlike `outgoing-link-audit`, this makes **no network calls** — it reads the local
build — so it's cheap to run any time.

## Shortcut: the shared script does the graph

`scripts/check_internal_links.sh` builds (if needed), extracts every internal anchor
from `dist/`, and prints the inbound-link graph grouped as **ORPHANS / THIN / OK**.
Run it first:

```bash
bash scripts/check_internal_links.sh
```

Then apply **judgment** to its output (the part a script can't do — *which* related
page should link to each orphan, and with what anchor text) and hand off the fixes.

## Procedure

### 1. Build the inbound-link graph

Audit the built `dist/` so it matches what Cloudflare serves. For every page, the
script counts the **distinct other pages** that link to it (self-links and the home
root excluded; query/fragment/`www`/trailing-slash variants collapse to one target,
matching the test) and its **click depth** from home (BFS). Classify each page:

- **ORPHAN** — 0 inbound internal links. The high-value finding: a page no one can
  reach by browsing. This is exactly what `tests/orphans.spec.ts` fails on.
- **THIN** — exactly 1 inbound link, and that link is the global nav/footer (no
  contextual in-body link). Not broken, but weakly connected: little internal
  PageRank flows to it (the "contextual links beat boilerplate" strategy).
- **DEEP** — more than ~3 clicks from home. Crawlers spend less budget on deep pages
  and pass them less equity (the "shallow crawl depth" strategy). Orthogonal to inbound
  count — a page can be both THIN and DEEP.
- **OK** — ≥2 inbound links and within 3 clicks.

Then sanity-check the inbound RANKING against intent: your most important pages
(home, pricing, primary feature/conversion pages) should be among the most-linked. A
key conversion page sitting at 1 inbound link is a strategy miss even though it isn't
technically orphaned.

### 2. Suggest WHERE to add the links (the judgment step)

For each orphan/thin page, the fix is not "link it from anywhere" — it's to add a link
where it's *topically* earned, so the link helps a real reader:

- **Sibling sets cross-link.** If `/acme-vs-crm`, `/acme-vs-chat`, `/acme-vs-calendar`, …
  exist, every comparison page should link to its siblings (a "Compare with other
  tools" block), and a hub/overview page should list them all. A footer "Product"
  group that names only `acme-vs-crm` is the bug — add the siblings to that
  group in `src/config.ts`, or build the hub page.
- **Contextual in-body links beat nav links.** A sentence on a related page that
  links the orphan in context ("see how we compare to a CRM") is worth more than a
  footer entry, to both readers and crawlers.
- **Pick anchor text that carries the target's keyword**, not "click here"/"read more"
  — it's a ranking signal for the target page (see `website-seo-geo`). Vary it
  naturally across links; don't paste the exact-match phrase every time.
- **Pull DEEP pages shallower.** Link a >3-click page from a hub or section page that
  itself sits near home, so it lands within ~3 clicks.
- **Feed the important pages.** If a money/conversion page is under-linked relative to
  its importance, add links to it from high-traffic related pages — important pages
  should have the most inbound links, not the fewest.
- **Use the free links.** Breadcrumbs and a "related pages" block are inbound links on
  every page at no editorial cost — a structural fix for whole clusters at once.
- **Always link the canonical URL** — clean path, no `.html`, no trailing slash, no
  redirect hop (so equity isn't lost to a 301 and `navigation.spec` stays green).

> Judgment, not just counts: a deliberately-unlinked page (a paid-campaign landing
> page reached only from an ad, a print-QR page) is *correctly* orphaned — it should
> go in `ORPHAN_EXEMPT` in `tests/orphans.spec.ts` with a reason, not get a forced
> link. Use the model to tell a real orphan from an intentional one.

### 3. Report

Group by severity. Lead with ORPHANS (the actionable ones), then THIN, then DEEP, then
OK as a count. For each orphan/thin/deep page, name the specific page(s) that should link to it and
the suggested anchor text.

### 4. Hand off the fixes

For each finding, after the user confirms:

1. Add the link in the source page (`src/pages/*.astro`, a content-collection entry,
   or a nav/footer group in `src/config.ts`). Use keyword-bearing anchor text and the
   clean URL (no `.html`, no trailing slash).
2. For a deliberately-unlinked page, add it to `ORPHAN_EXEMPT` in
   `tests/orphans.spec.ts` with the reason instead.
3. Re-run `npm run build && npm test` to confirm green (`orphans.spec.ts` must pass),
   then commit.

## Scope notes

- Audits the **active branch** you're on; `dist/` is the build of `src/`, which is
  what Cloudflare serves.
- **Internal** links only. Outgoing (external) link liveness is `outgoing-link-audit`;
  dead in-site links and `#fragment` integrity are the `navigation` + `anchors` specs
  in `website-qa`. This skill answers the orthogonal question: *is every page a link
  target, linked the way the strategy says?*
- **Strategy lives in `site-architecture`** (its Internal Linking Strategy section) —
  this skill is its enforcement arm against the built site, not a second rulebook. When
  the two could drift, `site-architecture` wins; flag the gap rather than re-deciding here.
- The hard gate (`tests/orphans.spec.ts`) only knows pass/fail on reachability-from-
  home; this skill is the richer report (inbound COUNT per page, THIN pages, link
  suggestions) you act on to keep it green.
- **Page-relative links:** `scripts/check_internal_links.sh` resolves only root-relative
  (`/about`) and absolute-on-host links — the kit's convention. It does **not** resolve
  page-relative hrefs (`about`, `./team`, `../pricing`), so a page reachable only via one
  is over-reported as ORPHAN/THIN by the script. The gate `tests/orphans.spec.ts` *does*
  resolve them and is authoritative — trust the gate over the script for those, and prefer
  root-relative links so the two never diverge.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.