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

@useavalon/seo

v0.1.0

Published

SEO plugin for Avalon — auto-injects Open Graph, Twitter cards, canonical URLs, JSON-LD structured data, and robots meta tags

Readme

@useavalon/seo

SEO plugin for Avalon — auto-injects Open Graph, Twitter cards, canonical URLs, JSON-LD structured data, and font preconnect links into every page.

Install

bun add @useavalon/seo

Usage

Add the plugin to your vite.config.ts:

import { seo } from '@useavalon/seo';
import { avalon } from '@useavalon/avalon';
import { defineConfig } from 'vite';

export default defineConfig(async () => {
  const avalonPlugins = await avalon({ /* ... */ });

  return {
    plugins: [
      seo({
        siteUrl: 'https://mysite.com',
        siteName: 'My Site',
        defaultDescription: 'A site built with Avalon',
        defaultOgImage: {
          url: '/og-image.png',
          width: 1200,
          height: 630,
        },
        twitterSite: '@mysite',
        twitterCreator: '@author',
        searchPath: '/search',
        author: {
          name: 'Jane Doe',
          url: 'https://mysite.com/about',
          image: 'https://mysite.com/jane.jpg',
          jobTitle: 'Software Engineer',
          sameAs: ['https://twitter.com/janedoe', 'https://github.com/janedoe'],
        },
        publisher: {
          name: 'My Company',
          url: 'https://mysite.com',
          logo: { url: 'https://mysite.com/logo.png', width: 600, height: 60 },
        },
        fontPreconnect: [
          'https://fonts.googleapis.com',
          'https://fonts.gstatic.com',
        ],
      }),
      ...avalonPlugins,
    ],
  };
});

What It Does

The plugin intercepts every HTML response and auto-injects missing SEO tags. It reads existing tags to avoid duplication — if your layout already sets og:title, the plugin won't add another one.

Meta Tags

  • Canonical URL<link rel="canonical"> from the current request path
  • Open Graphog:title, og:description, og:url, og:type, og:locale, og:site_name, og:image with og:image:width and og:image:height
  • Twitter Cardstwitter:card, twitter:site, twitter:creator, twitter:title, twitter:description, twitter:image
  • Font Preconnect<link rel="preconnect"> for configured font CDNs

JSON-LD Structured Data

  • WebPage — on every page
  • WebSite — with SearchAction when searchPath is configured (enables Google sitelinks search box)
  • BreadcrumbList — auto-generated from URL path segments
  • Article — when the page has article:published_time meta tag, includes full Person author (E-E-A-T), Organization publisher with logo ImageObject, and image with dimensions
  • SpeakableSpeakableSpecification on Article schema for voice engines

Config Reference

| Option | Type | Default | Description | |--------|------|---------|-------------| | siteUrl | string | required | Base URL of the site | | siteName | string | required | Site name for OG and JSON-LD | | defaultDescription | string? | — | Fallback meta description | | defaultOgImage | { url, width?, height? }? | — | Default OG image with dimensions | | twitterSite | string? | — | Twitter handle for twitter:site | | twitterCreator | string? | — | Twitter handle for twitter:creator | | locale | string? | 'en_US' | Default OG locale | | author | PersonConfig? | — | Author info for Article JSON-LD | | publisher | OrganizationConfig? | — | Publisher info for Article JSON-LD | | searchPath | string? | — | Path to search page (enables SearchAction) | | searchQueryParam | string? | 'q' | Query param name for search | | canonical | boolean? | true | Inject canonical URLs | | openGraph | boolean? | true | Inject OG meta tags | | twitterCards | boolean? | true | Inject Twitter card tags | | structuredData | boolean? | true | Inject JSON-LD | | breadcrumbs | boolean? | true | Inject BreadcrumbList JSON-LD | | speakable | boolean? | true | Add Speakable to Article JSON-LD | | speakableSelectors | string[]? | ['h1', '[data-speakable]'] | CSS selectors for speakable content | | fontPreconnect | string[]? | — | URLs to preconnect for fonts |

How Pages Opt Into Article Schema

The plugin reads article:* meta tags from the HTML to decide when to inject Article JSON-LD. Set these in your page's frontmatter/metadata:

export const metadata = {
  title: 'My Blog Post',
  description: 'A great article about...',
};

// In your layout, emit these meta tags from frontmatter:
<meta property="article:published_time" content="2026-01-15" />
<meta property="article:modified_time" content="2026-02-01" />
<meta property="article:author" content="Jane Doe" />
<meta property="article:section" content="Tech" />
<meta property="article:tag" content="javascript" />
<meta property="article:tag" content="seo" />

When article:published_time is present, the plugin generates full Article JSON-LD with author, publisher, image dimensions, and speakable specification.

License

MIT