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

@moss-tools/founding-agent

v2.1.0

Published

Embeddable voice founding agent for Moss-powered company websites. Ships a Node-side token helper and a React component.

Readme

@moss-tools/founding-agent

Embeddable voice founding agent for Moss-powered company websites. Drop the React component onto any page and your visitors can talk to a voice agent powered by your Q&A knowledge base.

  • Server helper for minting LiveKit session tokens from your backend.
  • React component that renders the voice UI and connects to LiveKit on click.
  • Works with Next.js, Remix, Vite, or any React setup.

Install

npm install @moss-tools/founding-agent
# required peers for the React component
npm install react react-dom tslib @livekit/components-react @livekit/components-styles livekit-client motion lucide-react zustand

Server-only usage (no React) has zero runtime dependencies; Node 18+ fetch is all it needs.

Environment

You get two credentials from the Moss dashboard when you create a founding agent:

  • MOSS_FA_API_KEY — server-only. Keep this in a backend env var (e.g. Vercel Environment Variables). Starts with sk_.
  • MOSS_FA_PUBLISHABLE_KEY — safe to ship to the browser. Passed to the React component. Starts with pk_.

1. Backend: mint a session token

The React component POSTs to a token endpoint you provide. That endpoint calls the Moss service with your server-only API key and returns the LiveKit token to the browser. A Next.js App Router example:

// app/api/moss-token/route.ts
import { createFoundingAgentSession } from "@moss-tools/founding-agent";

export async function POST() {
  const session = await createFoundingAgentSession({
    apiKey: process.env.MOSS_FA_API_KEY!,
  });
  return Response.json(session);
}

createFoundingAgentSession returns { token, serverUrl, roomName }.

For more control (custom error handling, reusing the client) use the class form:

import { MossFoundingAgent } from "@moss-tools/founding-agent";

const agent = new MossFoundingAgent({
  apiKey: process.env.MOSS_FA_API_KEY!,
  timeoutMs: 10_000, // optional
});

export async function POST() {
  const session = await agent.createSession();
  return Response.json(session);
}

2. Frontend: drop in the component

Wrap your page (or app) once with MossFoundingAgentProvider (it fetches the public config and wires the token endpoint), then render MossFoundingAgentBubble anywhere inside. By default the bubble pins itself to the bottom-right of the viewport.

"use client";

import {
  MossFoundingAgentBubble,
  MossFoundingAgentProvider,
} from "@moss-tools/founding-agent/react";

export default function LandingPage() {
  return (
    <MossFoundingAgentProvider
      publishableKey={process.env.NEXT_PUBLIC_MOSS_FA_PUBLISHABLE_KEY!}
    >
      <main>
        <h1>Talk to our team</h1>
      </main>
      <MossFoundingAgentBubble />
    </MossFoundingAgentProvider>
  );
}

That's the minimum. The bubble:

  1. Renders as a 56px circle, fixed to the bottom-right, showing the agent's portal-configured orb (or the preset color aura if it has none).
  2. On click, POSTs to /api/moss-token to get a session token and connects to LiveKit.
  3. Once live, the circle morphs into a horizontal pill: avatar, status line, mute, and an end-call button.
  4. End the call (or press Esc) and the pill collapses back to the icon.

For inline placement (e.g. inside a hero CTA section), pass position="inline":

<MossFoundingAgentBubble position="inline" />

Tailwind setup

The bubble uses Tailwind utility classes internally. If your app is on Tailwind v4, point its CSS at the package's compiled output so the utilities get picked up:

/* globals.css */
@import "tailwindcss";
@source "../node_modules/@moss-tools/founding-agent/dist/**/*.{js,mjs}";

Props

<MossFoundingAgentProvider>

| Prop | Type | Default | Description | |------|------|---------|-------------| | publishableKey | string | — | Required. The pk_... key for this agent. | | tokenEndpoint | string | /api/moss-token | URL of your backend route that returns { token, serverUrl }. | | serviceUrl | string | Moss default | Backend base URL. Changing this (or publishableKey) clears the cached config so a reused Provider cannot show the previous agent's identity. | | onError | (error: Error) => void | — | Fires on config fetch errors. |

<MossFoundingAgentBubble>

| Prop | Type | Default | Description | |------|------|---------|-------------| | position | "fixed" \| "inline" | "fixed" | "fixed" pins to the bottom-right of the viewport (with safe-area insets). "inline" renders where you place it. | | label | string | Agent name from config | Tooltip + aria-label on the idle bubble. | | appearance | AgentAppearance | Fetched from the portal | Explicit override of the portal-configured look: { shape, colors, soften, noise, widget_theme }. Normally omit it — the widget fetches whatever was saved in the portal and renders that orb automatically. An explicit value pins both the orb and the theme. | | color | BubbleColorInput | "violet" | Aura color, used only when the agent has no configured appearance. A preset name ("violet" \| "cobalt" \| "teal" \| "emerald" \| "coral" \| "amber") or an arbitrary #RRGGBB hex. | | themeMode | "dark" \| "light" | Portal widget_theme, else "light" | Themes the pill chrome and the aura. Omitted means follow the configured appearance's widget_theme. | | className | string | — | Override applied to the bubble/pill container. | | style | CSSProperties | — | Inline style override (merged after position styling). | | id | string | — | DOM id on the container. |

The exported BUBBLE_COLORS constant maps preset names to their hex values, and resolveBubbleColor(value) returns the resolved hex.

Appearance

Agents configured in the portal carry an appearance: one of five canvas orb shapes (Pixel, Flow, Radio, Stripes, Conic), one or two custom hex colors, a soften blur, a grain amount, and a light/dark widget theme. The widget fetches it with the publishable key and renders it with no host-site code change, so changing the look in the portal does not require a redeploy.

Resolution order for the avatar is: explicit appearance prop, then the fetched portal appearance, then the legacy color preset aura. Theme follows explicit themeMode, then the appearance's widget_theme, then light.

<AgentOrb> is exported if you want the same renderer outside the bubble:

import { AgentOrb, DEFAULT_APPEARANCE } from "@moss-tools/founding-agent/react";

<AgentOrb appearance={DEFAULT_APPEARANCE} state="listening" size={64} />;

It honours prefers-reduced-motion (painting one static frame) and stops animating while offscreen or in a hidden tab.

Live pill

While a call is live the bubble expands into a pill: the agent's avatar on the left, a status line (Tap to speak / Listening ... / Speaking ...), a mic toggle, and a red end button. M mutes and Esc ends the call. There is no elapsed-time counter (it was removed in 2.1.0).

Security model

  • The API key is never exposed to the browser. The component only ever sees the publishable key and the short-lived LiveKit token returned by your backend.
  • LiveKit tokens are minted server-side by the Moss service with minimal grants (audio publish/subscribe only, no data channel, no room create).
  • Room names are chosen by the service (fa-{slug}-{timestamp}). The browser never proposes a room name.

License

MIT