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

@lanechat/js

v0.2.0

Published

Typed, SSR-safe JavaScript SDK for the Lane.Chat browser widget.

Readme

@lanechat/js

Typed, SSR-safe JavaScript SDK for the Lane.Chat browser widget. It injects the widget loader for you (once), takes over the lifecycle, and wraps the global window.laneChat API with real TypeScript types.

Framework wrappers: @lanechat/react, @lanechat/vue. Prefer a plain <script> tag? See Plain HTML.

Install

npm install @lanechat/js

Quick start

import { LaneChat } from '@lanechat/js';

const lc = LaneChat.init({ appId: 'YOUR_APP_KEY' });

// React to panel state
const off = lc.on('open', () => console.log('panel opened'));

// After the visitor logs in, set their identity (in-place, no remount)
lc.identify({ email: '[email protected]', name: 'Jane Doe', plan: 'pro' });

// Programmatic control
lc.open();
lc.toggle();
off(); // unsubscribe

YOUR_APP_KEY is the same value you would put in data-app-key on the classic snippet. Calls made before the loader finishes downloading are buffered and replayed in order, so you never need to await anything.

Configuration

LaneChat.init({
  appId: 'YOUR_APP_KEY',        // required
  serverUrl: 'https://...',     // override widget server origin (optional)
  mode: 'floating',             // or 'inline' (requires container)
  container: '#chat-host',      // CSS selector or Element, inline mode only
  customizations: {             // widget theme / text / sizing overrides
    mainColor: '#2563eb',
  },
  allowedOrigins: ['https://app.example.com'],
  debug: false,
  externalUserId: 'user_123',   // stable id pass-through
  scriptUrl: 'https://cdn.lane.chat/js/widget.js', // override loader URL
});

API

LaneChat.init(config) returns a LaneChatInstance:

| Method | Returns | Description | | ------------------------- | ---------------- | ----------- | | open() | void | Open the panel. Emits open. | | close() | void | Close the panel. Emits close. | | toggle() | void | Toggle the panel. | | isOpen() | boolean | Whether the panel is open (false until ready). | | isMounted() | boolean | Whether the widget is mounted. | | identify(traits) | void | Set/update visitor identity + custom attributes. | | updateTheme(theme) | void | Update theme config at runtime. | | on(event, cb) | unsubscribe fn | Subscribe to 'open' / 'close'. | | destroy() | void | Unmount the widget (loader script stays). | | whenReady() | Promise | Resolves with the raw API, or null on SSR / load failure. |

Static: LaneChat.init(config), LaneChat.current.

identify(traits)

Standard fields are promoted to the visitor profile server-side (fill-if-empty); anything else is stored as a custom attribute visible to agents.

lc.identify({
  email: '[email protected]', // standard (also: email_address)
  name: 'Jane Doe',       // standard
  phone: '+1 415-555-2671', // standard (also: phone_number)
  plan: 'pro',            // custom attribute
  seats: 12,              // custom attribute
});

Always in-place and fire-and-forget — it never remounts the widget. Prefer it over destroy() + init() for pushing visitor data.

TypeScript

All types are exported:

import type {
  LaneChatConfig,
  LaneChatInstance,
  VisitorTraits,   // standard fields + index signature for custom attrs
  LaneChatEvent,   // 'open' | 'close'
  LaneChatThemeConfig,
} from '@lanechat/js';

SSR notes

  • LaneChat.init() is safe to call on the server: it returns an inert instance whose methods are no-ops, and it never touches window/document.
  • Nothing loads until you are in the browser. In frameworks, call init() from a client-only effect (or use @lanechat/react / @lanechat/vue, which do this for you).
  • isOpen() / isMounted() return false until the widget is ready.

Plain HTML (no build step)

You do not need this package for a plain site — the classic snippet works:

<script src="https://cdn.lane.chat/js/widget.js" data-app-key="YOUR_APP_KEY"></script>
<script>
  // The widget exposes window.laneChat (alias window.laneChatSDK)
  window.addEventListener('load', function () {
    window.laneChat.on('open', function () { console.log('opened'); });
    // After your app knows who the visitor is:
    window.laneChat.identify({ email: '[email protected]', name: 'Jane Doe' });
  });
</script>

License

MIT