seo adapter pack
SEO capability pack operating on PROVIDED html/text (no network — fetching is the 'scraping' pack's job). Generates meta/OpenGraph/Twitter tags, schema.org JSON-LD...
seo adapter pack
On-page SEO capabilities that operate on provided html/text. Pure JS, zero npm deps.
No network. This pack never fetches a URL. Pulling remote HTML is the job of thescrapingpack — pass its output in here. (scrapingalso parses existing sitemap.xml / robots.txt; this pack generates them.)
Tools
| Tool | Args | Returns |
|---|---|---|
metaTags | { title, description, url?, image?, type='website', twitterCard='summary_large_image', keywords? } | { tags:[], html } — title + description + canonical + OG + Twitter |
openGraph | { title?, description?, url?, image?, type='website' } | { tags:[], html } |
twitterCard | { title?, description?, image?, twitterCard='summary_large_image' } | { tags:[], html } |
jsonLd | { type, data } | { type, json, script } — schema.org for Article/Product/Organization/BreadcrumbList/FAQPage |
sitemap | { urls:[{loc,lastmod?,changefreq?,priority?}] } | { xml, count } — valid <urlset> |
robotsTxt | { rules:[{userAgent,allow?,disallow?}], sitemap? } | { txt, blocks } |
audit | { html } | { score, issues:[], checks:{} } — title/desc/h1/img-alt/canonical checks |
keywordDensity | { text, top=10 } | { total, terms:[{term,count,density}] } |
slugify | { text } | { slug } |
readingTime | { text, wpm=200 } | { words, wpm, minutes, text } |
serpSnippet | { title, description } | { title, description, warnings } — pixel-ish char limits |
Usage
import seo from './index.js';
seo.adapters.metaTags({ title: 'Hello', description: 'A short but sufficient description of the page.', url: 'https://x.io' });
seo.adapters.sitemap({ urls: [{ loc: 'https://x.io/', changefreq: 'daily', priority: 1 }] });
seo.adapters.audit({ html: '<html><body><p>no title</p></body></html>' }); // → score/issues flag missing title
seo.adapters.jsonLd({ type: 'Article', data: { title: 'T', author: 'A', datePublished: '2026-01-01' } });
DRY boundaries
- Fetching stays in
scraping. This pack is offline-only. slugifyalso exists ina-transformation(string.slugify).seo.slugifyis a convenience
so an SEO caller need not cross packs; for heavy transliteration use a-transformation.