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

@glowrank/next

v0.2.0

Published

Next.js adapter for GlowRank own-site content — a one-line App Router route handler with ISR/tag revalidation, sitemap, and connection verification.

Readme

@glowrank/next

Next.js (App Router) adapter for GlowRank own-site content. One route handler serves your GlowRank pages on your domain — with ISR, tag-based revalidation, a sitemap, and the connection-verification probe built in.

This content is yours — pages render on your origin and canonical URLs point at your domain.

Recommended: render Markdown in your own layout

For full control of the look — and a zero-trust integration where you never inject our HTML — fetch pages with the underlying client and render each page's markdown field with your own components. GlowRank owns the words; your design system owns everything else.

// app/guides/[slug]/page.tsx
import { createClient } from "@glowrank/next";
import Markdown from "react-markdown";

const gr = createClient({ siteKey: process.env.GLOWRANK_SITE_KEY! });

export default async function Guide({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params;
  const page = await gr.getPageBySlug(slug);
  if (!page) notFound();
  return (
    <YourArticleLayout title={page.title}>
      <Markdown>{page.markdown ?? ""}</Markdown>
    </YourArticleLayout>
  );
}

markdown is derived server-side from sanitised HTML and stored, so it always matches the page body. See Trust model.

Fastest path: the one-line route handler

Don't want to wire up rendering yourself? One handler serves complete, server-sanitised HTML documents:

npm install @glowrank/next
// app/guides/[[...slug]]/route.ts  (use the base path from your GlowRank connection)
import { createGlowRankHandler } from "@glowrank/next";

export const GET = createGlowRankHandler({ siteKey: process.env.GLOWRANK_SITE_KEY! });

That's it. The handler now serves, under /guides:

| Path | Response | | --- | --- | | /guides/<slug> | Full HTML document for a published GlowRank page | | /guides/sitemap.xml | Sitemap of all live GlowRank pages | | /guides/__glowrank-check | Verification probe (echoes your siteKey) | | anything else | 404 |

Requires next >= 14 (peer dependency) and Node ≥ 18.

ISR & revalidation

Every upstream fetch is made with next: { revalidate, tags: ['glowrank'] }:

  • Time-based (ISR): pages refresh automatically every revalidate seconds (default 300). Override per handler:

    export const GET = createGlowRankHandler({
      siteKey: process.env.GLOWRANK_SITE_KEY!,
      revalidate: 60, // seconds; or `false` to cache until tag revalidation
    });
  • On-demand: purge all GlowRank content instantly from a Server Action or webhook route:

    import { revalidateTag } from "next/cache";
    revalidateTag("glowrank"); // exported as GLOWRANK_CACHE_TAG

Responses also carry Cache-Control: public, s-maxage=<revalidate>, stale-while-revalidate so CDNs in front of your app behave consistently.

Verification (__glowrank-check)

When you click Verify in the GlowRank dashboard, GlowRank requests https://your-site.com/<basePath>/__glowrank-check and expects your siteKey echoed back — proving the SDK is mounted at the path configured on your connection. The handler answers this automatically (no API call involved), so verification passes as soon as the route above is deployed. If verification fails, check that the route directory matches your connection's base path exactly and that GLOWRANK_SITE_KEY is set in the deployed environment.

Merging into your own sitemap

Prefer one sitemap at the site root? Merge GlowRank entries into app/sitemap.ts instead:

import type { MetadataRoute } from "next";
import { createClient, glowrankSitemapEntries } from "@glowrank/next";

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const client = createClient({ siteKey: process.env.GLOWRANK_SITE_KEY! });
  const glowrank = await glowrankSitemapEntries(client);
  return [{ url: "https://example.com" }, ...glowrank];
}

Not on the App Router?

Use @glowrank/content directly — the framework-agnostic core this adapter is built on (Express, Fastify, Remix, plain http, …).

Trust model

GlowRank content is model-generated from inputs we don't fully control (your scraped site copy, review text), so we treat it as untrusted and harden it before it reaches you — at write time and again at the API boundary.

  • markdown (recommended). No markup to trust — render it with your own components. The zero-trust path.
  • html (sanitised). Allowlist sanitisation keeps only semantic content (headings, paragraphs, lists, emphasis, blockquotes, tables, code/pre, hr/br, http/https a links with forced rel="noopener noreferrer") and strips script/style/iframe/object/embed/form, all on* handlers, and javascript:/data: URLs. This is what createGlowRankHandler serves.

Both are safe to render; Markdown just gives you a format with no HTML to review.

License

MIT