npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@power-seo/links

v1.0.12

Published

Internal link graph analysis, orphan detection, link suggestions, and link equity scoring

Readme

@power-seo/links

links banner

Build a directed link graph from your site's pages, detect orphan pages with zero inbound links, generate keyword-overlap-based link suggestions, and score link equity with a PageRank-style algorithm.

npm version npm downloads Socket License: MIT TypeScript tree-shakeable

@power-seo/links gives you a complete internal linking intelligence layer for your SEO tooling. Internal link structure is one of the most actionable on-page SEO signals — it determines how search engines discover and understand your content, and how link equity flows through your site. Yet most SEO tools treat it as a secondary concern. This package makes it a first-class concern.

Given a list of pages and their outbound links, buildLinkGraph constructs a full directed graph in memory. From that graph you can immediately find orphan pages (pages that no other page links to — invisible to crawlers that start from the homepage), compute PageRank-style equity scores to understand which pages accumulate the most link authority, and generate contextual internal link suggestions based on keyword and topic overlap between pages.

The package is designed to integrate directly with @power-seo/audit for site-wide SEO audits, and with @power-seo/analytics for correlating link equity with traffic data. It is dependency-free, fully typed, and tree-shakeable.

Zero dependencies — no runtime dependencies; pure TypeScript computation.


Why @power-seo/links?

| | Without | With | | ------------------ | --------------------- | -------------------------------------------------- | | Orphan detection | ❌ Manual crawl | ✅ findOrphanPages() in-memory graph | | Link suggestions | ❌ Guesswork | ✅ Keyword-overlap-based contextual suggestions | | Link equity | ❌ Third-party tools | ✅ PageRank-style scoring built-in | | Graph construction | ❌ Build from scratch | ✅ buildLinkGraph() — directed graph in one call | | Audit integration | ❌ Separate toolchain | ✅ Designed to integrate with @power-seo/audit | | TypeScript support | ❌ Untyped | ✅ Full type coverage for all graph structures | | Zero dependencies | ❌ External libs | ✅ Pure TypeScript, no runtime dependencies |

Links Comparison


Features

  • Directed link graph constructionbuildLinkGraph(pages) builds an in-memory directed graph from page URL arrays, computing both outbound and inbound link sets for each node
  • Orphan page detectionfindOrphanPages(graph) returns all pages that have zero inbound internal links, making them invisible to crawlers following links from the homepage
  • Keyword-overlap link suggestionssuggestLinks(pages, options?) compares page titles and content to find thematically related pages that should be linking to each other but are not
  • PageRank-style link equity scoringanalyzeLinkEquity(graph, options?) runs a damping-factor iterative algorithm to assign a relative equity score to every node in the graph
  • Configurable suggestion options — control minimum similarity threshold, maximum suggestions per page, and whether to include bidirectional suggestions
  • Configurable equity options — set the damping factor (default 0.85), number of iterations, and convergence threshold for the PageRank algorithm
  • Inbound and outbound link counts — every LinkNode in the graph exposes both inbound and outbound arrays plus inboundCount and outboundCount for direct inspection
  • Normalized URL handling — URLs are normalized before graph construction to prevent duplicate nodes from trailing slashes or case differences
  • Zero dependencies — no runtime dependencies; pure TypeScript computation

Link Dashboard UI


Comparison

| Feature | @power-seo/links | Screaming Frog | Ahrefs | Custom scripts | | ------------------------- | :--------------: | :------------: | :----: | :------------: | | Programmatic link graph | ✅ | ❌ | ❌ | Manual | | Orphan page detection | ✅ | ✅ | ✅ | Manual | | Keyword-based suggestions | ✅ | ❌ | ❌ | Manual | | PageRank-style equity | ✅ | ❌ | ✅ | Manual | | Audit integration | ✅ | ❌ | ❌ | — | | Zero dependencies | ✅ | ❌ | ❌ | — | | TypeScript-first | ✅ | ❌ | ❌ | — | | Tree-shakeable | ✅ | ❌ | ❌ | — |

Link Equity Accuracy


Installation

npm install @power-seo/links
yarn add @power-seo/links
pnpm add @power-seo/links

Quick Start

import { buildLinkGraph, findOrphanPages, suggestLinks, analyzeLinkEquity } from '@power-seo/links';

// 1. Build the graph from your site's pages
const graph = buildLinkGraph([
  { url: 'https://example.com/', links: ['https://example.com/about', 'https://example.com/blog'] },
  { url: 'https://example.com/about', links: ['https://example.com/'] },
  { url: 'https://example.com/blog', links: ['https://example.com/'] },
  { url: 'https://example.com/orphan', links: [] },
]);

// 2. Find pages no other page links to
const orphans = findOrphanPages(graph);
// [{ url: 'https://example.com/orphan', title: undefined, outboundCount: 0 }]

// 3. Get link equity scores
const equityScores = analyzeLinkEquity(graph);
// [{ url: 'https://example.com/', score: 0.48, inboundCount: 2 }, { url: 'https://example.com/about', score: 0.18, inboundCount: 1 }, ...]

Orphan Detection Benefit


Usage

Build a Link Graph

buildLinkGraph accepts an array of PageData objects and returns a LinkGraph — a Map<string, LinkNode> keyed by normalized URL. Each LinkNode contains the page's URL, its set of outbound links, and the set of pages that link to it (inbound links).

import { buildLinkGraph } from '@power-seo/links';
import type { PageData, LinkGraph } from '@power-seo/links';

const pages: PageData[] = [
  {
    url: 'https://example.com/',
    links: ['https://example.com/blog', 'https://example.com/about', 'https://example.com/contact'],
  },
  {
    url: 'https://example.com/blog',
    links: [
      'https://example.com/',
      'https://example.com/blog/post-1',
      'https://example.com/blog/post-2',
    ],
  },
  {
    url: 'https://example.com/blog/post-1',
    links: ['https://example.com/blog'],
  },
  {
    url: 'https://example.com/blog/post-2',
    links: ['https://example.com/blog', 'https://example.com/blog/post-1'],
  },
  {
    url: 'https://example.com/about',
    links: ['https://example.com/'],
  },
  {
    url: 'https://example.com/contact',
    links: [],
  },
];

const graph: LinkGraph = buildLinkGraph(pages);

// Inspect a node
const blogNode = graph.nodes.get('https://example.com/blog');
console.log(blogNode?.inbound); // ['https://example.com/']
console.log(blogNode?.inboundCount); // 1
console.log(blogNode?.outbound); // ['https://example.com/', ...]
console.log(blogNode?.outboundCount); // ...

Find Orphan Pages

findOrphanPages iterates the graph and returns all nodes whose inboundCount is zero. These pages cannot be reached by following links from any other page — making them effectively invisible to Googlebot unless they appear in your sitemap.

import { buildLinkGraph, findOrphanPages } from '@power-seo/links';
import type { OrphanPage } from '@power-seo/links';

const graph = buildLinkGraph(pages);
const orphans: OrphanPage[] = findOrphanPages(graph);

orphans.forEach(({ url, outboundCount }) => {
  console.log(`Orphan page: ${url} (${outboundCount} outbound links)`);
});

// Example output:
// Orphan page: https://example.com/contact (0 outbound links)

Tip: Cross-reference orphan pages with your sitemap. Pages that appear in the sitemap but have no inbound links are priority candidates for internal linking improvements.

Generate Link Suggestions

suggestLinks analyzes page titles and content to find pairs of pages that share significant topical overlap but do not currently link to each other. It uses a term-frequency-based similarity algorithm that does not require an external NLP library.

import { suggestLinks } from '@power-seo/links';
import type { LinkSuggestion, LinkSuggestionOptions } from '@power-seo/links';

const pages = [
  {
    url: '/guide/react-seo',
    title: 'React SEO Guide',
    content:
      'Learn how to optimize React applications for search engines using meta tags, structured data, and server-side rendering.',
  },
  {
    url: '/guide/meta-tags',
    title: 'HTML Meta Tags Explained',
    content:
      'Meta tags control how search engines index your pages. The title tag and meta description are the most important.',
  },
  {
    url: '/guide/nextjs-setup',
    title: 'Next.js Project Setup',
    content:
      'Set up a Next.js application with TypeScript, ESLint, and Prettier for a production-ready project.',
  },
];

const options: LinkSuggestionOptions = {
  maxSuggestions: 3, // optional — cap suggestions per page (default: 20)
  minRelevance: 0.15, // optional — minimum overlap score 0-1 (default: 0.1)
};

const suggestions: LinkSuggestion[] = suggestLinks(pages, options);

suggestions.forEach(({ from, to, anchorText, relevanceScore }) => {
  console.log(`Link from ${from} to ${to}`);
  console.log(`  Suggested anchor: "${anchorText}" (score: ${relevanceScore.toFixed(2)})`);
});

Analyze Link Equity

analyzeLinkEquity runs a PageRank-style iterative algorithm over the graph and returns a LinkEquityScore[] array assigning each page a normalized equity score, sorted by score in descending order. Pages with many high-quality inbound links receive higher scores.

import { buildLinkGraph, analyzeLinkEquity } from '@power-seo/links';
import type { LinkEquityScore, LinkEquityOptions } from '@power-seo/links';

const graph = buildLinkGraph(pages);

const options: LinkEquityOptions = {
  damping: 0.85, // optional — PageRank damping factor (default: 0.85)
  iterations: 20, // optional — max iterations (default: 20)
};

const equityScores = analyzeLinkEquity(graph, options);

// Sort pages by equity score (highest first)
const ranked = equityScores.sort((a, b) => b.score - a.score);

ranked.forEach(({ url, score, inboundCount }) => {
  console.log(`${url}: equity=${score.toFixed(4)}, inbound=${inboundCount}`);
});

Integration with Audit

Combine @power-seo/links with @power-seo/audit to surface link issues as part of a full site audit.

import { buildLinkGraph, findOrphanPages, analyzeLinkEquity } from '@power-seo/links';
import { auditSite } from '@power-seo/audit';

const graph = buildLinkGraph(sitePages);
const orphans = findOrphanPages(graph);
const equityScores = analyzeLinkEquity(graph);
const equityMap = new Map(equityScores.map((eq) => [eq.url, eq]));

const auditReport = auditSite({ pages: sitePages });

// Enrich audit results with link equity data
const enrichedPages = auditReport.pages.map((page) => ({
  ...page,
  linkEquity: equityMap.get(page.url)?.score ?? 0,
  isOrphan: orphans.some((o) => o.url === page.url),
}));

API Reference

buildLinkGraph(pages)

| Parameter | Type | Default | Description | | --------- | ------------ | -------- | ------------------------------------------------------ | | pages | PageData[] | required | Array of pages with their URL and outbound link arrays |

Returns LinkGraph — object with nodes: Map<string, LinkNode>, totalPages: number, totalLinks: number.


findOrphanPages(graph, entryPoints?)

| Parameter | Type | Default | Description | | ------------- | ----------- | -------- | ------------------------------------------------------ | | graph | LinkGraph | required | A directed link graph built by buildLinkGraph | | entryPoints | string[] | [] | URLs to exclude from orphan detection (e.g., homepage) |

Returns OrphanPage[] — array of { url: string; title?: string; outboundCount: number } objects.


suggestLinks(pages, options?)

| Parameter | Type | Default | Description | | ------------------------ | ------------ | -------- | ----------------------------------------------------------- | | pages | PageData[] | required | Pages with url, title, and content for analysis | | options.minRelevance | number | 0.1 | Minimum keyword overlap score (0–1) to include a suggestion | | options.maxSuggestions | number | 20 | Maximum number of suggestions returned per source page |

Returns LinkSuggestion[] — array of { from, to, anchorText, relevanceScore } objects.


analyzeLinkEquity(graph, options?)

| Parameter | Type | Default | Description | | -------------------- | ----------- | -------- | ------------------------------------------------------------------------------ | | graph | LinkGraph | required | A directed link graph built by buildLinkGraph | | options.damping | number | 0.85 | PageRank damping factor — probability of following a link vs. jumping randomly | | options.iterations | number | 20 | Maximum number of power-iteration steps |

Returns LinkEquityScore[] — array sorted by score descending.


Types

import type {
  PageData, // { url: string; links: string[]; title?: string; content?: string }
  LinkNode, // { url: string; inbound: string[]; outbound: string[]; inboundCount: number; outboundCount: number }
  LinkGraph, // { nodes: Map<string, LinkNode>; totalPages: number; totalLinks: number }
  OrphanPage, // { url: string; title?: string; outboundCount: number }
  LinkSuggestion, // { from: string; to: string; anchorText: string; relevanceScore: number }
  LinkSuggestionOptions, // { maxSuggestions?: number; minRelevance?: number }
  LinkEquityScore, // { url: string; score: number; inboundCount: number }
  LinkEquityOptions, // { damping?: number; iterations?: number }
} from '@power-seo/links';

Use Cases

  • Content audit tools — detect orphan pages and prioritize internal linking improvements across your site
  • Headless CMS — run link analysis after every publish to keep the site graph healthy
  • SEO dashboards — visualize link equity distribution and identify pages that need more inbound links
  • CI/CD pipelines — fail builds when orphan pages exceed a configurable threshold
  • Content strategy — use link suggestions to build topical clusters automatically

Architecture Overview

  • Pure TypeScript — no compiled binary, no native modules
  • Zero dependencies — no runtime dependencies; pure TypeScript computation
  • Framework-agnostic — works in Next.js, Remix, Vite, Node.js, Edge, or any JS runtime
  • SSR compatible — no browser-specific APIs; safe for server-side or CLI usage
  • Edge runtime safe — no Node.js-specific APIs; runs in Cloudflare Workers, Vercel Edge, Deno
  • Tree-shakeable"sideEffects": false with named exports per function
  • Dual ESM + CJS — ships both formats via tsup for any bundler or require() usage

Supply Chain Security

  • No install scripts (postinstall, preinstall)
  • No runtime network access
  • No eval or dynamic code execution
  • CI-signed builds — all releases published via verified github.com/CyberCraftBD/power-seo workflow
  • Safe for SSR, Edge, and server environments

The @power-seo Ecosystem

All 17 packages are independently installable — use only what you need.

| Package | Install | Description | | ------------------------------------------------------------------------------------------ | ----------------------------------- | ----------------------------------------------------------------------- | | @power-seo/core | npm i @power-seo/core | Framework-agnostic utilities, types, validators, and constants | | @power-seo/react | npm i @power-seo/react | React SEO components — meta, Open Graph, Twitter Card, breadcrumbs | | @power-seo/meta | npm i @power-seo/meta | SSR meta helpers for Next.js App Router, Remix v2, and generic SSR | | @power-seo/schema | npm i @power-seo/schema | Type-safe JSON-LD structured data — 23 builders + 22 React components | | @power-seo/content-analysis | npm i @power-seo/content-analysis | Yoast-style SEO content scoring engine with React components | | @power-seo/readability | npm i @power-seo/readability | Readability scoring — Flesch-Kincaid, Gunning Fog, Coleman-Liau, ARI | | @power-seo/preview | npm i @power-seo/preview | SERP, Open Graph, and Twitter/X Card preview generators | | @power-seo/sitemap | npm i @power-seo/sitemap | XML sitemap generation, streaming, index splitting, and validation | | @power-seo/redirects | npm i @power-seo/redirects | Redirect engine with Next.js, Remix, and Express adapters | | @power-seo/links | npm i @power-seo/links | Link graph analysis — orphan detection, suggestions, equity scoring | | @power-seo/audit | npm i @power-seo/audit | Full SEO audit engine — meta, content, structure, performance rules | | @power-seo/images | npm i @power-seo/images | Image SEO — alt text, lazy loading, format analysis, image sitemaps | | @power-seo/ai | npm i @power-seo/ai | LLM-agnostic AI prompt templates and parsers for SEO tasks | | @power-seo/analytics | npm i @power-seo/analytics | Merge GSC + audit data, trend analysis, ranking insights, dashboard | | @power-seo/search-console | npm i @power-seo/search-console | Google Search Console API — OAuth2, service account, URL inspection | | @power-seo/integrations | npm i @power-seo/integrations | Semrush and Ahrefs API clients with rate limiting and pagination | | @power-seo/tracking | npm i @power-seo/tracking | GA4, Clarity, PostHog, Plausible, Fathom — scripts + consent management |


About CyberCraft Bangladesh

CyberCraft Bangladesh is a Bangladesh-based enterprise-grade software development and Full Stack SEO service provider company specializing in ERP system development, AI-powered SaaS and business applications, full-stack SEO services, custom website development, and scalable eCommerce platforms. We design and develop intelligent, automation-driven SaaS and enterprise solutions that help startups, SMEs, NGOs, educational institutes, and large organizations streamline operations, enhance digital visibility, and accelerate growth through modern cloud-native technologies.

Website GitHub npm Email

© 2026 CyberCraft Bangladesh · Released under the MIT License