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

@chimichurricode/web-app-kit

v0.1.3

Published

Shared Astro web shell — BaseLayout component + defineWebApp config factory + canonical site scripts. Built on @chimichurricode/design-system + @chimichurricode/analytics.

Readme

@chimichurricode/web-app-kit

Shared Astro web shell for every Chimi web property. Owns the invariant parts of an Astro web (HTML shell, head composition, body class wiring, analytics bootstrap, Astro config defaults) so each consumer only declares the variant parts (nav links, footer columns, copy strings, content collections).

Companion to @chimichurricode/design-system (which owns tokens, recipes, chrome components) and @chimichurricode/analytics (which owns the analytics adapter). This kit composes them into a turnkey site shell.


What it ships

| Subpath | What you get | |---|---| | @chimichurricode/web-app-kit/BaseLayout.astro | The shared <html> + <head> + <body> shell. Renders ThemeBootstrap, SEOHead, SiteHeader, <main> slot, SiteFooter, and the analytics bootstrap from typed props. | | @chimichurricode/web-app-kit/config | defineWebApp({ siteId, port, preact?, sitemapFilter?, … }) — Astro config factory with the canonical defaults and (when preact: true) the Preact integration + the upstream fix-preact-server-optimize workaround. | | @chimichurricode/web-app-kit/scripts | defineSiteScripts({ siteId, sitemapFilename?, disallow?, extra? }) — the canonical package.json scripts object. | | @chimichurricode/web-app-kit/seo | homeAppJsonLd({ siteId, name, description, applicationCategory? }) and homeEditorialJsonLd({ siteId, socials? }) — JSON-LD factories that consolidate the boilerplate previously duplicated across 6 of the 7 webs' src/seo/index.ts. | | @chimichurricode/web-app-kit/types | Recipe, SEOOverrides, BrandConfig, NavLink, FooterColumn, BaseLayoutProps, DefineWebAppOptions, DefineSiteScriptsOptions — the public type surface. |


Quick start

1. Add the kit to your web

// packages/<your-web>/package.json
{
  "dependencies": {
    "@chimichurricode/analytics": "*",
    "@chimichurricode/design-system": "*",
    "@chimichurricode/web-app-kit": "*"
  }
}

2. Replace your astro.config.mjs

// packages/<your-web>/astro.config.mjs
import { defineWebApp } from "@chimichurricode/web-app-kit/config";

export default defineWebApp({
  siteId: "simple-foo-tool",
  port: 4346,
  preact: true,
  // Optional: filter the sitemap (e.g. exclude private routes)
  sitemapFilter: (page) => !page.includes("/r/"),
});

3. Replace your src/layouts/Base.astro

---
import "../styles/global.css";
import BaseLayout from "@chimichurricode/web-app-kit/BaseLayout.astro";
import type { BaseLayoutProps } from "@chimichurricode/web-app-kit/types";

interface Props extends Pick<BaseLayoutProps, "title" | "description" | "recipe" | "seo"> {}

const { title, description, recipe, seo } = Astro.props;
---

<BaseLayout
  siteId="simple-foo-tool"
  title={title}
  description={description}
  recipe={recipe}
  seo={seo}
  header={{ brand: { label: "Simple Foo Tool", emText: "Foo", byline: "by Chimichurri Code", href: "/" }, mobileMenu: false }}
  footer={{ variant: "minimal" }}
>
  <slot />
</BaseLayout>

4. Use the JSON-LD factories in src/seo/index.ts

// packages/<your-web>/src/seo/index.ts
import { homeAppJsonLd } from "@chimichurricode/web-app-kit/seo";

export function homeJsonLd(): Array<Record<string, unknown>> {
  return homeAppJsonLd({
    siteId: "simple-foo-tool",
    name: "Simple Foo Tool",
    description: "What this tool does in one sentence.",
    applicationCategory: "DeveloperApplication",
  });
}

That's it. Your web inherits the canonical <head>, theme bootstrap, ecosystem chrome, analytics, and SEO conventions automatically. When the kit gets updated (e.g. a new required <head> tag), your web picks it up on the next npm install.



Component inventory

BaseLayout.astro

File: packages/web-app-kit/BaseLayout.astro

Purpose: The shared HTML shell for every Chimi web property. Composes <html> + <head> (meta, SEO, icons, theme bootstrap, analytics) + <body> with SiteHeader, <main> slot, and SiteFooter. All chrome and head composition is handled here — consumer webs wrap their content and pass props.

Import path:

import BaseLayout from "@chimichurricode/web-app-kit/BaseLayout.astro";

Props (see @chimichurricode/web-app-kit/types for full types):

| Prop | Type | Default | Description | |---|---|---|---| | siteId | string | required | Site identifier used by analytics and SEO systems | | title | string | required | Page <title> (suffix appended automatically) | | description | string | "" | Meta description | | recipe | Recipe | "canvas-quiet" | Active color recipe applied to <body> | | lang | string | "es" | <html lang> attribute | | seo | SEOOverrides | {} | JSON-LD, canonical override, noindex flag | | header | HeaderConfig | required | { brand, links, mobileMenu } | | footer | FooterConfig | required | { variant, columns, … } | | analytics | boolean | true | Set false to disable analytics bootstrap |

Consumer sites:

| Site | Package | |---|---| | brand | packages/brand | | blog | packages/blog | | techconf | packages/techconf | | talks | packages/talks | | rfp | packages/rfp | | All simple-* tools | packages/simple-* |

Minimal usage example:

---
import BaseLayout from "@chimichurricode/web-app-kit/BaseLayout.astro";

interface Props {
  title: string;
  description?: string;
}

const { title, description = "" } = Astro.props;
---

<BaseLayout
  siteId="my-site"
  title={title}
  description={description}
  recipe="canvas-quiet"
  header={{
    brand: { label: "My Site", emText: "Site", byline: "by Chimichurri Code", href: "/" },
    links: [
      { href: "/about", label: "About" },
    ],
    mobileMenu: true,
  }}
  footer={{ variant: "minimal" }}
>
  <slot />
</BaseLayout>

Migration from a hand-written shell

The kit is opt-in per web. Each migration is a single PR:

  1. Replace astro.config.mjs with defineWebApp({ … }). Verify dev server boots.
  2. Replace src/layouts/Base.astro with the <BaseLayout> wrapper. Run a snapshot diff (build before/after, compare HTML body hashes) — expect zero functional diff.
  3. (Optional) Replace per-site homeJsonLd() boilerplate with homeAppJsonLd / homeEditorialJsonLd.

See openspec/changes/archive/2026-…-extract-web-app-kit/ for the full design rationale.


What stays in your web

The kit owns only what's invariant. Each web continues to author:

  • Per-site nav links (passed as header.links).
  • Per-site footer columns / brand description (passed as footer.columns / footer.brandName / etc.).
  • Per-site copy strings (src/lib/copy.ts).
  • Per-site CSS (src/styles/global.css).
  • Per-site pages and components.
  • Per-site tsconfig.json (extends the future root tsconfig.base.json from C6).

If the kit's API doesn't fit your web (e.g. you need a one-off <script> in <head>), keep the wrapper layer in your Base.astro and add what you need around <BaseLayout>.


Conventions enforced by the kit

  • Recipe: every web declares one default recipe (passed as recipe prop, defaults to canvas-quiet). Pages may override per-page via <BaseLayout recipe="paper">.
  • Lang: <html lang> defaults to "es" (overridable via lang prop).
  • Analytics: bootstraps @chimichurricode/analytics with site = siteId, adapter = vercel | console (based on import.meta.env.PROD), perf = true. Disable via analytics={false}.
  • <main id="main">: always rendered, so skip-link patterns work out of the box.

Adoption status

Run npm run check:web-app-kit-adoption (after C2 ships) to see which webs consume the kit.