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

kooby

v1.0.9

Published

A simple Chatbot component that uses WebSockets to interact with a backend server

Readme

Kooby

A simple Chatbot component that uses WebSockets to interact with a backend server

Usage

// Import the kooby component
import { Kooby } from "kooby";

const MyComponent = () => {
  return (
    <Kooby url="ws://localhost:8000">
      <Kooby.Toolbar />
      <Kooby.Conversation />
      <Kooby.ConnectionStatus />
      <Kooby.TextBox />
    </Kooby>
  );
};

With metadata

import { Kooby } from "kooby";

const MyComponent = () => {
  return (
    <Kooby
      url="ws://localhost:8000"
      metadata={{
        user: "Joe",
      }}
    >
      <Kooby.Toolbar />
      <Kooby.Conversation />
      <Kooby.ConnectionStatus />
      <Kooby.TextBox />
    </Kooby>
  );
};

When not expandable

// Import the kooby component
import { Kooby } from "kooby";

const MyComponent = () => {
  return (
    <Kooby url="ws://localhost:8000">
      <Kooby.Toolbar expandable={false} />
      <Kooby.Conversation />
      <Kooby.ConnectionStatus />
      <Kooby.TextBox />
    </Kooby>
  );
};

Always Expanded

Will always take up fill width of parent container 100%

// Import the kooby component
import { Kooby } from "kooby";

const MyComponent = () => {
  return (
    <Kooby url="ws://localhost:8000" expanded>
      <Kooby.Toolbar />
      <Kooby.Conversation />
      <Kooby.ConnectionStatus />
      <Kooby.TextBox />
    </Kooby>
  );
};

When you want to hide the reset button

// Import the kooby component
import { Kooby } from "kooby";

const MyComponent = () => {
  return (
    <Kooby url="ws://localhost:8000">
      <Kooby.Toolbar reset={false} />
      <Kooby.Conversation />
      <Kooby.ConnectionStatus />
      <Kooby.TextBox />
    </Kooby>
  );
};

With History ( seeding the conversation )

// Import the kooby component
import { Kooby } from "kooby";

const MyComponent = () => {
  return (
    <Kooby
      url="ws://localhost:8000"
      conversation={[
        {
          role: "user",
          content: "Hi, I would like to know about the barker project",
        },
      ]}
    >
      <Kooby.Toolbar />
      <Kooby.Conversation />
      <Kooby.ConnectionStatus />
      <Kooby.TextBox />
    </Kooby>
  );
};

Custom Chat Components

Kooby allows you to customize what gets output by your agent. You can build custom React components that will get rendered when your agent returns specific keywords.

Example: ( Mermaid Diagrams )

When the agent returns text like this you may want Kooby to render that as a diagram:

    <mermaid>
     graph TD
         A[Start] -->|Step 1| B[Process]
         B -->|Step 2| C[End]
     </mermaid>

In order to get its contents to render inside of your custom Mermaid.jsx component, you simply need to register your component like so:

import { Kooby } from "kooby";
import { Mermaid } from "./Mermaid.jsx";
import { QR } from "./QR.jsx";

const mdjsx = {
  overrides: {
    mermaid: {
      component: Mermaid,
    },
    qr: {
      component: QR,
    },
  },
};

const MyComponent = () => {
  return (
    <Kooby url="ws://localhost:8000">
      <Kooby.Toolbar />
      <Kooby.Conversation mdjsx={mdjsx} />
      <Kooby.ConnectionStatus />
      <Kooby.TextBox />
    </Kooby>
  );
};

Custom Toolbar

Kooby allows you to customize what gets rendered in the toolbar (at the top of the Kooby window).

import { Kooby } from "kooby";

const CustomToolbar = ({ agent, conversation, socketId }) => {
  const copyConversation = () => {
    const conversationJson = JSON.stringify(conversation, null, 2);
    navigator.clipboard.writeText(conversationJson);
  };

  return (
    <button
      type="button"
      onClick={copyConversation}
      aria-label="Copy conversation"
    >
      Copy
    </button>
  );
};

const MyComponent = () => {
  return (
    <Kooby url="ws://localhost:8000">
      <Kooby.Toolbar>
        {({ conversation }) => <CustomToolbar conversation={conversation} />}
      </Kooby.Toolbar>
      <Kooby.Conversation />
      <Kooby.ConnectionStatus />
      <Kooby.TextBox />
    </Kooby>
  );
};

Kooby Api

You can get access to the internal kooby api via a ref

// Import useRef
import React, { useRef } from "react";

// Import the kooby component
import { Kooby } from "kooby";

const MyComponent = () => {
  const koobyApiRef = useRef();

  return (
    <>
      <Button
        onClick={() => {
          koobyApiRef.current?.resetConversation();
        }}
        variant="secondary"
      >
        Reset
      </Button>
      <Kooby url="ws://localhost:8000" apiRef={koobyApiRef}>
        <Kooby.Toolbar />
        <Kooby.Conversation />
        <Kooby.ConnectionStatus />
        <Kooby.TextBox />
      </Kooby>
    </>
  );
};

Sending Feedback

// Import the kooby component
import { Kooby } from "kooby";

const MyComponent = () => {
  return (
    <Kooby url="ws://localhost:8000">
      <Kooby.Toolbar />
      <Kooby.Conversation
        negative={{
          onSubmit: (feedback) => {
            console.log(JSON.stringify(feedback, null, 2));
          },
        }}
        positive={{
          onSubmit: (feedback) => {
            console.log(JSON.stringify(feedback, null, 2));
          },
        }}
      />
      <Kooby.ConnectionStatus />
      <Kooby.TextBox />
    </Kooby>
  );
};

Example Output from negative feedback log

{
  "feedback": "Wish it just told me what was new!",
  "message": "Are you asking about new models, features, or updates? Could you please specify?",
  "conversation": [
    {
      "role": "system",
      "content": "Hello, I'm Test! I'm here to help you with any questions you may have."
    },
    {
      "role": "user",
      "content": "Hi!"
    },
    {
      "role": "assistant",
      "content": "Hello! How can I assist you today?"
    },
    {
      "role": "user",
      "content": "What new ? "
    },
    {
      "role": "assistant",
      "content": "Are you asking about new models, features, or updates? Could you please specify?"
    }
  ]
}

Showing feedback on all messages

By default feedback will only be shown on the most recent message. By passing showFeedbackOnAllMessages you can change that behavior.

// Import the kooby component
import { Kooby } from "kooby";

const MyComponent = () => {
  return (
    <Kooby url="ws://localhost:8000">
      <Kooby.Toolbar />
      <Kooby.Conversation
        showFeedbackOnAllMessages
        negative={{
          onSubmit: (feedback) => {
            console.log(JSON.stringify(feedback, null, 2));
          },
        }}
        positive={{
          onSubmit: (feedback) => {
            console.log(JSON.stringify(feedback, null, 2));
          },
        }}
      />
      <Kooby.ConnectionStatus />
      <Kooby.TextBox />
    </Kooby>
  );
};

Project Layout

client - a simple react app with a chat window ( using the exported Kooby react component ) server - a simple js express server that serves up the chatbot and connects to the chat api

Getting It Running

Step1: First you need to make sure you have node installed on your computer

Visit this site HERE

Step2: you need to install the dependencies

npm i

This will install all the dependencies

Step3: Add required secrets

Get chat token and put it in the following file in the root of this project ( used grok in example )

touch token_grok.txt

Step4: Run it!

npm run start:dev

This will start a express web server with basic chatbot and also a sample front end react app that connects to the servers endpoint

Go here to view the frontend example

http://localhost:3000/

WebSocket URL (example app)

ws://localhost:3000/kooby