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

@pagenary/embed

v2026.7.23

Published

Framework-agnostic Pagenary blog embed web components.

Readme

Pagenary Embed

Drop Pagenary blog updates into any site with standards-based web components.

@pagenary/embed provides framework-agnostic custom elements for showing Pagenary content outside a Pagenary site. The first component, <pagenary-blog>, reads one or many Pagenary blog indexes, renders reachable posts newest first, and keeps source failures visible without taking down the page.

Built with AIWG, the multi-agent AI framework used to plan, audit, and ship Pagenary.

npm install @pagenary/embed
<script type="module" src="/vendor/pagenary-embed.js"></script>

<pagenary-blog
  sources="https://docs.example.com/product/blog/index.json,https://docs.example.com/api/blog/index.json"
  limit="10"
  show-source="true"></pagenary-blog>

npm version npm downloads Docs License: AGPL v3 Node Version Built with AIWG

Docs Site · Quick Start · Component API · Styling · CORS


What It Is

Pagenary publishes documentation sites and can expose blog-style indexes from those sites. @pagenary/embed is the browser-side embed layer for bringing those updates into another website: a product homepage, an app dashboard, a support portal, a docs hub, or a customer-facing status page.

The package uses native custom elements, so it does not require React, Vue, Svelte, Astro, or any other framework. The component renders into Shadow DOM, exposes stable part() selectors, and delegates fetching/normalization to @pagenary/blog-client.

Quick Start

Install the package:

npm install @pagenary/embed

Bundle it with your app:

import '@pagenary/embed';

Then use the element in your HTML:

<pagenary-blog
  sources="https://docs.example.com/product/blog/index.json"
  limit="5"></pagenary-blog>

For a static site that copies vendor assets, publish the module file from your own origin and load it directly:

<script type="module" src="/vendor/pagenary-embed.js"></script>

Aggregate several docbases:

<pagenary-blog
  sources="https://docs.example.com/product/blog/index.json,https://docs.example.com/api/blog/index.json"
  limit="10"
  show-source="true"></pagenary-blog>

Component API

<pagenary-blog>

Renders a list of posts from one or many Pagenary blog indexes.

Attributes:

| Attribute | Required | Purpose | |-----------|----------|---------| | sources | Yes | Comma-separated list of Pagenary blog/index.json URLs. | | limit | No | Maximum number of posts to render after newest-first sorting. | | show-source | No | Show the source/docbase title beside each post. Use show-source="true" or a boolean attribute. |

The element reacts to attribute changes. Updating sources, limit, or show-source re-renders the feed and aborts the previous in-flight fetch.

Example:

<pagenary-blog
  sources="https://docs.example.com/blog/index.json"
  limit="3"
  show-source></pagenary-blog>

Styling

The component is intentionally quiet by default and inherits typography from the host page. Theme it with CSS custom properties:

pagenary-blog {
  --pagenary-blog-color: #111827;
  --pagenary-blog-muted: #5f6673;
  --pagenary-blog-border: #d9dee8;
  --pagenary-blog-gap: 1rem;
  --pagenary-blog-link: #0f766e;
}

Use part() selectors for structural styling:

pagenary-blog::part(list) {
  display: grid;
  gap: 1.25rem;
}

pagenary-blog::part(item) {
  padding-block-end: 1.25rem;
}

pagenary-blog::part(title) {
  font-weight: 700;
}

pagenary-blog::part(notice) {
  font-style: italic;
}

Available parts:

| Part | Purpose | |------|---------| | root | Component root inside Shadow DOM. | | list | Rendered post list. | | item | Individual list item. | | title | Post title link. | | meta | Metadata row containing date and optional source. | | source | Source/docbase label when show-source is enabled. | | summary | Post summary text. | | notice | Loading, empty, or partial-failure notice. |

CORS and Hosting

Runtime embeds fetch blog indexes from the visitor's browser. Each source docbase must allow the host site to read the index.

Minimum static-host headers for a public blog index:

Access-Control-Allow-Origin: https://www.example.com
Access-Control-Allow-Methods: GET, HEAD, OPTIONS
Access-Control-Allow-Headers: Content-Type
Content-Type: application/json; charset=utf-8

Use Access-Control-Allow-Origin: * only for public indexes that do not expose private data. If the host page uses a strict CSP, include every Pagenary docbase in connect-src and include the embed module's origin in script-src.

The full guide, including Cloudflare/CDN examples, lives in the Pagenary repo: BLOG-CONSUMPTION.md.

When to Use It

Good fit:

  • Showing release notes or documentation updates on a product homepage.
  • Aggregating posts from several Pagenary docbases into one news block.
  • Adding docs updates to an existing CMS, marketing site, or support portal.
  • Embedding without tying the host page to a JavaScript framework.

Use @pagenary/blog-client directly when you need build-time rendering, SSR, or custom markup. Use @pagenary/publisher when you need to publish the source documentation site and blog index.

Troubleshooting

The component only shows Updates are unavailable right now.

Open the browser network panel and inspect the blog/index.json request. The most common cause is CORS: the source docbase did not include an Access-Control-Allow-Origin header that allows the host site.

The component only shows No blog sources configured.

The sources attribute is missing or empty. Provide one URL or a comma-separated list of URLs.

Some posts render, but there is an unavailable-source notice

At least one source failed while others succeeded. The component keeps the page useful and reports the partial failure. Fix the failing source URL, CORS policy, or hosting rule.

Source names are missing

Add show-source to the element and publish indexes with source/docbase metadata. The underlying client can derive a fallback source title from the URL, but explicit source titles are better for users.

Documentation