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

@cool-ai/beach-a2ui-patterns

v0.1.3

Published

Curated surface-composition helpers for Beach A2UI — productCard, narrativePanel, searchResultList, and more. Returns SurfaceCommand[] against the A2UI v0.9 basic catalog.

Downloads

301

Readme

@cool-ai/beach-a2ui-patterns

Pre-built A2UI surface patterns for Beach agents. Each pattern returns a SurfaceCommand[] ready to send via context.routeEvent — no manual createSurface/updateComponents wiring needed.

Home: cool-ai.org · Documentation: cool-ai.org/docs

Install

npm install @cool-ai/beach-a2ui-patterns @cool-ai/beach-a2ui

@cool-ai/beach-a2ui is a peer dependency.

Patterns

productCard

A titled card with labelled line items and a bold total row, separated by a divider. Renders identically via A2UI browser renderer, renderToHtml (email), and renderToText (WhatsApp / SMS).

import { productCard } from '@cool-ai/beach-a2ui-patterns';

const cmds = productCard({
  surfaceId: 'order-123',
  title: 'Your Order',
  items: [
    { label: 'Flight LHR-FCO', amount: '£299' },
    { label: 'Hotel Centro',   amount: '$1,200' },
  ],
  total: { label: 'Total', amount: '£1,499' },
});

| Option | Type | Description | |---|---|---| | surfaceId | string | Unique surface id. | | title | string | Card heading. | | items | ProductCardLine[] | Line items shown above the divider. | | total | ProductCardLine | Total row shown below the divider in bold. |

ProductCardLine has label: string and amount: string.


narrativePanel

A heading plus prose body. The simplest pattern: one card, one heading, one paragraph. Channel-neutral.

import { narrativePanel } from '@cool-ai/beach-a2ui-patterns';

const cmds = narrativePanel({
  surfaceId: 'summary-panel',
  heading: 'Your trip summary',
  body: 'Your Paris flights are confirmed. Check in opens 24 hours before departure.',
  level: 2, // optional, defaults to 2
});

| Option | Type | Description | |---|---|---| | surfaceId | string | Unique surface id. | | heading | string | Panel heading. | | body | string | Prose body text. | | level | 1 \| 2 \| 3 \| 4 | Heading level. Defaults to 2. |


searchResultList

A ranked list of results. Each result renders as a card with a heading-styled title, optional caption-styled subtitle, and an optional star-rating Text (★/☆ characters). An empty-state Text is shown when the results array is empty.

import { searchResultList } from '@cool-ai/beach-a2ui-patterns';

const cmds = searchResultList({
  surfaceId: 'hotel-results',
  results: [
    { id: 'hotel-1', title: 'Hotel Centro', subtitle: 'Florence, IT', score: 4.5 },
    { id: 'hotel-2', title: 'Pensione Canova', subtitle: 'Florence, IT' },
  ],
  emptyText: 'No hotels found for your dates.', // optional
});

| Option | Type | Description | |---|---|---| | surfaceId | string | Unique surface id. | | results | SearchResult[] | Ordered results. | | emptyText | string | Empty-state text. Defaults to "No results found." |

SearchResult fields:

| Field | Type | Description | |---|---|---| | id | string | Stable per-result key. Used as the component-id segment for the result's card and its descendants (e.g. ${surfaceId}/result/${id}), so ids stay stable across re-renders even if the list reorders. | | title | string | Primary title. | | subtitle | string? | Optional secondary line, rendered as a caption-variant Text. | | score | number? | Optional numeric score (0–5). A2UI v0.9's basic catalog has no Rating component, so the score is rendered as a caption-variant Text containing / characters rounded to the nearest integer. |


Testing patterns

Use @cool-ai/beach-a2ui-test to assert on pattern output without reaching into raw message JSON:

import { surfaceOf } from '@cool-ai/beach-a2ui-test';
import { productCard } from '@cool-ai/beach-a2ui-patterns';

const s = surfaceOf(productCard({ ... }));

expect(s.find('Card')).toMatchObject({ title: 'Your Order' });
expect(s.findAll('Row')).toHaveLength(3); // 2 items + 1 total
expect(s.find('Divider')).toBeDefined();

Constants

import { A2UI_BASIC_CATALOG_ID } from '@cool-ai/beach-a2ui-patterns';
// 'https://a2ui.org/specification/v0_9/basic_catalog.json'

All patterns use the A2UI v0.9 basic catalog. Pass A2UI_BASIC_CATALOG_ID whenever you need the catalog id string directly.