@spicez21/moss
v0.1.2
Published
Drop-in RAG-powered AI chat for Next.js — Claude + Pinecone + PostgreSQL
Maintainers
Readme
moss
Drop-in RAG-powered AI chat for Next.js. Claude + Pinecone + PostgreSQL. Zero boilerplate.
npm install @spicez21/moss
npx moss initWhat 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 initThe init wizard will ask for your API keys and write:
.env.local— all your environment variableslib/moss.ts— your moss configurationapp/api/moss/[...route]/route.ts— all API routes, wired upmiddleware.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 actionConfiguration
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:
- Middleware (
middleware.ts) — blocks requests before they reach your handlers - Handler guard —
isLocalhost()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.sqlSupported 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
