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

@myandgo/help

v0.1.0

Published

The AndGo fleet's embeddable in-app help surface. One widget, every product embeds it.

Readme

@myandgo/help

The AndGo fleet's embeddable in-app help surface. One widget, every product embeds it.

A user asks a question inside your product. Your assistant answers from your knowledge base if it can. If it cannot, the conversation becomes a tracked SupportAndGo ticket, and the agent's reply comes back into the same thread the user is already looking at.

  • ~11 kB gzipped, Preact, no host framework required
  • Renders in a closed shadow root, so your CSS and the widget's cannot touch each other
  • Config, not forks: branding, copy, suggestions and page context are all passed in
  • React binding included; also mounts into Vue, Svelte, or plain HTML

Install

npm install @myandgo/help

Use it

React:

import { HelpWidget } from "@myandgo/help/react";

<HelpWidget
  baseUrl="/api"
  branding={{ productName: "WorkAndGo", colour: "#1e3a5f", assistantName: "Jeeves" }}
  getHeaders={async () => ({ Authorization: `Bearer ${await getIdToken()}` })}
  getPageContext={() => ({ route: location.pathname })}
  suggestions={["How do I submit a timesheet?", "Why is my shift missing?"]}
/>;

Anything else:

import { mountHelp } from "@myandgo/help";

const unmount = mountHelp({
  baseUrl: "/api",
  branding: { productName: "WorkAndGo", colour: "#1e3a5f" },
});

The host contract

The widget is a thin client. Your backend implements three endpoints, and owns the conversation, the knowledge base, the escalation decision and the user's identity.

GET {baseUrl}/support/help/config

{ "enabled": true }

Whether this user gets the surface at all. The widget renders nothing unless this returns enabled: true — a 404, a 401, a network failure or a missing field all mean no. Fails closed on purpose: a help button that errors when clicked is worse than no button. Use it as your pilot-cohort flag.

GET {baseUrl}/support/help

{
  "conversation_id": "sup_a1b2c3",
  "status": "escalated",
  "ticket_status": "pending",
  "turns": [
    { "role": "user", "text": "My shift is missing", "at": "2026-07-26T01:00:00Z" },
    { "role": "assistant", "text": "Let me check that…", "at": "2026-07-26T01:00:01Z" },
    { "role": "agent", "text": "Fixed — refresh.", "at": "2026-07-26T01:04:00Z", "from_name": null }
  ]
}

The user's current thread. Polled every 8 s while the panel is open and the tab is visible (never in a background tab). Return the whole thread every time — the widget dedupes.

  • role — user, agent (a human on the desk), or anything else, which is treated as your assistant and labelled with your assistantName.
  • at — ISO 8601. The sort key. Stamp every turn, or ordering falls back to arrival order and messages can shuffle between polls.
  • from_name — the agent's name, or null while agents are unnamed (renders "Support").
  • ticket_status — open | pending | closed, once escalated. There is deliberately no resolved: closed is resolved. An unrecognised value renders no status at all rather than a wrong one.

POST {baseUrl}/support/help/message

{ "text": "My shift is missing", "context": { "route": "/timesheets" } }

Returns the updated thread, same shape as above. context is present only if you passed getPageContext — if your request schema is strict, simply don't pass it and it will never appear.

Identity — read this bit

The widget never tells you who the user is, by design. It sends your session credentials (cookies by default, or whatever getHeaders returns) and nothing else. Your backend derives the identity from that authenticated session and sets, when it forwards to SupportAndGo:

  • requester.uid — the platform myandgo_uid. This is the fleet's canonical join key. Email is loose: it changes, it collides across products, and it is not a stable identity.
  • requester.orgId — your product's business/tenant reference.

A uid asserted by the browser would be spoofable, and because that uid is the join key for cross-product support history, one product trusting a client-supplied value would corrupt attribution for every product. Deriving it server-side from a verified session costs nothing and cannot be forged. WorkAndGo's relay already does exactly this (requester_uid=user["myandgo_uid"]).

The widget carries no secrets and never talks to SupportAndGo directly. It cannot: the ingest endpoint is HMAC-signed with a per-product secret, and a browser is not a place a secret can live.

Options

| Option | Default | What it does | | --- | --- | --- | | baseUrl | — | Where your three endpoints live. Required. | | branding.productName | — | Header text. Required. | | branding.colour | #111827 | Launcher, user bubbles, focus rings. | | branding.logoUrl | — | Shown in the panel header. | | branding.assistantName | Assistant | What you call your bot. | | branding.agentFallbackName | Support | Label for an unnamed human. | | copy | sensible defaults | Every user-facing string. | | position | right | left or right. | | getHeaders | — | Resolved on every request, so refreshed tokens keep working. | | credentials | include | Passed to fetch. | | getPageContext | — | Opt-in context sent with each message. | | suggestions | — | Opening prompts, shown on an empty thread. | | pollIntervalMs | 8000 | Minimum 2000. | | defaultOpen | false | Start with the panel open. | | onOpenChange | — | For your own analytics. | | target | document.body | Mount point. |

Behaviour worth knowing

  • Optimistic send. Your message appears instantly and is reconciled with the server's copy when it echoes back. If the send fails, the bubble is removed and your text is put back in the box — nobody loses what they typed.
  • Polling pauses when the tab is hidden and resumes (with an immediate refresh) when you come back.
  • Enter sends, Shift+Enter is a newline.
  • Mobile: full-screen panel under 460 px.
  • Accessibility: the thread is an aria-live log, the panel is a labelled dialog, focus rings use your brand colour, and animation respects prefers-reduced-motion.

Adopting it if you already piloted your own surface

The three endpoints above are the shape WorkAndGo's pilot relay already serves (/api/support/help/config, /api/support/help, /api/support/help/message). If yours matches, delete your bespoke UI and mount this — no backend change. If your roles differ, they still work: anything that isn't user or agent renders as your assistant.

Development

npm install
npm test          # 32 tests: thread merge/dedupe/order, status mapping, transport contract
npm run build     # dist/help.js + dist/react.js + types
npm run demo      # a mock host on http://localhost:5174 — no backend needed