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

@sonordev/agency-site-kit

v0.13.0

Published

Portfolio data, proof rules and types for Sonor-powered agency websites

Readme

@sonordev/agency-site-kit

Case studies for agency websites built on Sonor. The kit fetches your portfolio from Sonor and gives your site the rules every case study follows: which numbers it may claim and the credit a client's number wears, the order its sections read in, JSON-LD, image sizes, the device-stage decision, and what happens when the API can't be reached. How your case studies look is up to you: the kit doesn't render any markup, and the setup CLI scaffolds a starter renderer that's yours to restyle.

Built for the Next.js App Router. Full docs live at sonor.dev/agency-site-kit.

Install

pnpm add @sonordev/agency-site-kit @sonordev/site-kit

@sonordev/site-kit (>= 6.5.0) is a peer dependency. It carries the shared Sonor data plane and the portfolio contract the kit's proof rules build on. Next.js >= 14 and React >= 18 are peers too.

You need one environment variable, in .env.local:

SONOR_API_KEY=sonor_xxxxxxxx_xxxxxxxxxxxx

It's read on the server only. There's no NEXT_PUBLIC_ variant and no project ID: Sonor works out the project from the key.

Quickstart

From your Next.js project root:

npx agency-site-kit-setup --site-url https://youragency.com --agency-name "Your Agency"

That writes the /work index, category pages, case study pages, a starter renderer, the webhook Sonor calls when content changes and the dashboard's draft preview route. It never overwrites a file, so it's safe to run again. Then wrap your root layout in AgencySiteKitLayout and add your case studies to the sitemap. The Quickstart walks through every flag and file.

A case study page

// app/work/[slug]/page.tsx
import { notFound } from 'next/navigation';
import { curatePortfolioProof, formatMetricValue, metricNote, sectionData } from '@sonordev/agency-site-kit/portfolio';
import { getPortfolioItem } from '@sonordev/agency-site-kit/portfolio/server';

export default async function CaseStudyPage({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params;
  const item = await getPortfolioItem(slug);
  if (!item) notFound(); // null means it doesn't exist; an outage throws instead

  const hero = sectionData(curatePortfolioProof(item), 'portfolioHero');

  return (
    <article>
      <h1>{hero?.headline ?? item.title}</h1>
      <dl>
        {hero?.kpis.map((kpi) => {
          const note = metricNote(kpi, 'short');
          return (
            <div key={kpi.label}>
              <dt>{kpi.label}</dt>
              <dd>{formatMetricValue(kpi)}</dd>
              {note ? <dd>{note}</dd> : null}
            </div>
          );
        })}
      </dl>
    </article>
  );
}

metricNote is the line a number wears when you didn't measure it: per Northwind Engineering on a client-reported number, Estimated on an estimate, nothing on a measured one.

What's in the box

| Area | What you get | Docs | |---|---|---| | Proof | curatePortfolioProof, metricNote, headlineKpi, gateMetricsDeltas, formatMetricValue, the measured / reported / estimated model and the Verification section (checks that each state what they don't cover) | Proof and provenance | | Sections | The four stages of the story, groupedSections, orderedSections, stageLede, sectionData, projectBrandColor, and the one-laptop-or-three-devices decision | Sections and devices | | Images and labels | resolvePortfolioImage, category, service and date formatting, Site Architecture page titles and path sanitizing | Images, labels and paths | | Structured data | buildPortfolioJsonLd and jsonLdString | JSON-LD | | Data | The server fetchers, metadata, static params and sitemap helpers, and the error contract | Fetching, Types | | Brand | AgencySiteKitLayout, which publishes your brand as --sk-* CSS variables | Brand layout | | Live updates | createRevalidateHandler and createPortfolioPreviewHandler | Live updates and preview | | Device frames | Showing a client's live site inside a device frame | Live device frames |

Where to import from

  • @sonordev/agency-site-kit/portfolio: the rules and the types. Pure, so it imports from a server component, a client component, a plain module or a test.
  • @sonordev/agency-site-kit/portfolio/server: the fetchers and Next.js helpers, plus the same rules. Server only.
  • @sonordev/agency-site-kit: everything, including AgencySiteKitLayout. Server only.

The Subpath map lists every entry and what it exports.

Keeping up to date

The kit is pre-1.0, so breaking changes can land in a minor release. The changelog says when one does.

A new release doesn't reach your site on its own. Your lockfile pins the version and your host installs from it, so run pnpm update @sonordev/agency-site-kit and commit the new lockfile. The build succeeds either way and the site looks the same, so an update that never landed is easy to miss. Install from the npm registry, never as a link: dependency: a link works locally and fails on a fresh clone.

License

MIT