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

@spicez21/moss

v0.1.2

Published

Drop-in RAG-powered AI chat for Next.js — Claude + Pinecone + PostgreSQL

Readme

moss

Drop-in RAG-powered AI chat for Next.js. Claude + Pinecone + PostgreSQL. Zero boilerplate.

npm install @spicez21/moss
npx moss init

What you get

  • Floating chat widget — customer-facing, streams responses via Server-Sent Events
  • Admin panel — upload docs, watch them index in real time, manage your knowledge base
  • RAG pipeline — embed queries, search Pinecone, inject context into Claude
  • Anonymous sessions — cookie-based, no auth required for customers
  • Localhost-only admin — the admin panel is completely blocked in production

Requirements

  • Next.js 14+ (App Router)
  • PostgreSQL database
  • Pinecone account (free tier works)
  • Anthropic API key (anthropic.com)
  • Voyage AI API key for embeddings (voyageai.com — free tier available)

Quick start

1. Install and initialize

npm install @spicez21/moss @anthropic-ai/sdk @pinecone-database/pinecone pg
npx moss init

The init wizard will ask for your API keys and write:

  • .env.local — all your environment variables
  • lib/moss.ts — your moss configuration
  • app/api/moss/[...route]/route.ts — all API routes, wired up
  • middleware.ts — admin route guard

2. Create your Pinecone index

In the Pinecone dashboard, create an index with:

  • Dimension: 1024 (required for voyage-3)
  • Metric: cosine

3. Add the chat widget to your layout

// app/layout.tsx
import { ChatWidget } from '@spicez21/moss/client'
import { mossContext } from '@/lib/moss'

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <body>
        {children}
        <ChatWidget theme={mossContext.config.theme} />
      </body>
    </html>
  )
}

4. Add the admin panel

// app/admin/page.tsx
import { AdminPanel } from '@spicez21/moss/client'

export default function AdminPage() {
  return <AdminPanel />
}

5. Run and upload your docs

npm run dev
# Visit http://localhost:3000/admin
# Upload your FAQs, docs, or any text — they'll be chunked, embedded, and indexed
# Then visit http://localhost:3000 to see the chat widget in action

Configuration

Edit lib/moss.ts to customize everything:

import { createMossConfig } from '@spicez21/moss'

export const mossContext = createMossConfig({
  // AI provider
  provider: 'claude',
  apiKey: process.env.ANTHROPIC_API_KEY!,
  voyageApiKey: process.env.VOYAGE_API_KEY!,  // for embeddings

  // Vector store
  pineconeApiKey: process.env.PINECONE_API_KEY!,
  pineconeIndex: process.env.PINECONE_INDEX!,

  // Database
  db: 'postgres',
  dbConnectionString: process.env.DATABASE_URL!,

  // Optional customization
  systemPrompt: 'You are Acme Support. Be concise and helpful.',
  topK: 5,            // number of context chunks to retrieve
  chunkSize: 2000,    // chars per chunk (~500 tokens)
  chunkOverlap: 200,  // overlap between chunks

  // Widget theme
  theme: {
    primaryColor: '#0f172a',
    accentColor: '#6366f1',
    position: 'bottom-right',
    botName: 'Acme Support',
    welcomeMessage: 'Hi! How can I help you today?',
  },
})

API routes

All routes are served from app/api/moss/[...route]/route.ts:

| Method | Path | Access | Description | |--------|------|--------|-------------| | POST | /api/moss/chat | Public | Streaming chat (SSE) | | GET | /api/moss/me/history | Public | Session message history | | POST | /api/moss/admin/ingest | Localhost only | Upload and index a document | | GET | /api/moss/admin/documents | Localhost only | List all documents | | DELETE | /api/moss/admin/documents/:id | Localhost only | Delete a document |

AG-UI events

The chat endpoint streams typed events (Server-Sent Events). Use the useAgui hook to consume them in your own components:

import { useAgui } from '@spicez21/moss/client'
import type { MossAGUIEvent } from '@spicez21/moss/client'

function MyCustomChat() {
  const { send, isStreaming } = useAgui({
    url: '/api/moss/chat',
    onEvent: (event: MossAGUIEvent) => {
      if (event.type === 'TEXT_DELTA') {
        // append event.delta to your UI
      }
    },
  })

  return <button onClick={() => send('Hello!')}>Ask</button>
}

Security

The admin panel and all /api/moss/admin/* routes are completely inaccessible in production. This is enforced at two layers:

  1. Middleware (middleware.ts) — blocks requests before they reach your handlers
  2. Handler guardisLocalhost() check inside each admin handler (belt-and-suspenders)

There is no login, no password, no token. Localhost = trusted. Production = 403.

Environment variables

| Variable | Required | Description | |----------|----------|-------------| | ANTHROPIC_API_KEY | Yes | Anthropic API key | | VOYAGE_API_KEY | Yes (with Claude) | Voyage AI key for embeddings | | PINECONE_API_KEY | Yes | Pinecone API key | | PINECONE_INDEX | Yes | Pinecone index name | | DATABASE_URL | Yes | PostgreSQL connection string |

Database

The schema is applied automatically on first startup. To apply manually:

psql $DATABASE_URL -f node_modules/@spicez21/moss/schema.sql

Supported file types

| Type | MIME type | Notes | |------|-----------|-------| | Plain text | text/plain | Direct UTF-8 read | | Markdown | text/markdown | Symbols preserved | | PDF | application/pdf | Text-based PDFs only (no OCR) |

License

MIT