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

vitepress-plugin-moss

v1.0.0-beta.1

Published

Moss semantic search plugin for VitePress

Readme

vitepress-plugin-moss

A VitePress plugin that adds Moss semantic (AI) search to your docs. At build time it reads your Markdown source, chunks it, and uploads it to the Moss cloud. At runtime the search UI uses a hot-path: it queries the cloud immediately so search works from the very first keystroke, while the local model and index download in the background. Once ready, all queries automatically switch to sub-10 ms on-device search — no user action needed.

Live demo: moss-samples-plugin.vercel.app


How it works

Build time                                      Runtime (browser)
────────────────────────────────────────────    ──────────────────────────────────────
VitePress calls buildEnd hook                   User presses Ctrl/⌘+K or /
    ↓                                               ↓
mossIndexerPlugin reads siteConfig              Phase 1 — SDK imported, client created
    ↓                                           Queries routed to Moss cloud  ← hot-path
@moss-tools/md-indexer reads source .md             (instant results from first keystroke)
using VitePress's own markdown renderer             ↓  (parallel)
(understands includes, extensions, etc.)        Phase 2 — model + index download (background)
    ↓                                               ↓
Uploads via @inferedge-rest/moss REST client    Index ready → queries switch to local < 10 ms
(deletes old index, then re-uploads chunks)         ↓
    ↓                                           Active query re-run with local index
Index is live on Moss cloud                     (seamless handoff, no user action needed)

Two separate npm packages are involved:

  • @inferedge-rest/moss — Node.js REST client used at build time (inside @moss-tools/md-indexer) to upload documents
  • @inferedge/moss — WebAssembly browser SDK used at runtime to download the index and run local queries

Installation

npm install vitepress-plugin-moss
# or
pnpm add vitepress-plugin-moss
# or
yarn add vitepress-plugin-moss

Requirement: your project's package.json must have "type": "module" because VitePress is ESM-only.


Setup

1. Configure VitePress

The plugin is easy to integrate using the vite.plugins option in your VitePress config. This handles both the search configuration and the build-time indexing automatically.

// docs/.vitepress/config.ts
import { defineConfig } from 'vitepress'
import { mossIndexerPlugin } from 'vitepress-plugin-moss'

export default defineConfig({
  title: 'My Docs',
  themeConfig: {
    search: {
      provider: 'moss' as any,
      options: {
        projectId: process.env.MOSS_PROJECT_ID!,
        projectKey: process.env.MOSS_PROJECT_KEY!,
        indexName: 'my-docs',
      },
    },
  },
  vite: {
    plugins: [mossIndexerPlugin()]
  }
})

Once integrated via vite.plugins, the Moss search component will automatically replace the default VitePress search bar (Zero-Config UI).

The plugin activates only when search.provider is 'moss'. If the provider is anything else, mossIndexerPlugin returns a no-op and buildEnd exits immediately.

2. Get your Moss credentials

  1. Sign up at moss.dev
  2. Create a project and note your Project ID and API key
  3. Pass them via environment variables (see below)

3. Set environment variables

Never hard-code credentials in your config file.

# .env  ← add to .gitignore, never commit
MOSS_PROJECT_ID=your_project_id
MOSS_PROJECT_KEY=your_api_key
MOSS_INDEX_NAME=my-docs

Note: projectKey ends up embedded in the client-side JavaScript bundle. Treat it as you would an Algolia search-only API key — use a key scoped to read/query operations only.


Options reference

All options go under themeConfig.search.options:

{
  // Required
  projectId: string    // Moss project ID
  projectKey: string   // Moss API key
  indexName: string    // Name of the index to create/overwrite on every build

  // Optional — Search UI
  topK?: number        // Number of results to return (default: 10)
  placeholder?: string // Search input placeholder (default: 'Search docs...')
  buttonText?: string  // Nav bar button label (default: 'Search')
}

Indexing always runs on every vitepress build when the provider is 'moss' — there is no enabled flag to toggle.

Excluding a page from the index

Add search: false to the page's frontmatter:

---
search: false
---

Keyboard shortcuts

| Key | Action | |-----|--------| | Ctrl+K / ⌘+K | Open / close search | | / | Open search (when not focused on an input) | | / | Navigate results | | | Go to selected result | | Esc | Close search |


Build output

A successful build prints:

Moss Sync: Starting End-to-End Process
---------------------------------------

Step 1: Building Index in Memory...
Processing N pages...
✅ Index built in memory: N chunks generated

Step 2: Uploading to Moss...
  ✅ Deleted existing index "my-docs"
✅ Upload success! Index "my-docs" is live.

 Sync Successfully Completed!

If indexing fails (network error, bad credentials, etc.) the build does not fail — the error is logged and the rest of the VitePress build continues.


Creating and Loading Indexes

Automatic indexing on build

When you run vitepress build, the mossIndexerPlugin automatically builds and uploads the index to Moss at the end of the build. No extra step is needed — just make sure your credentials are set in environment variables.

Manual indexing with index:docs

The demo site includes a standalone script for building and uploading the index without running a full VitePress build. This is useful when you update documentation content and want to refresh the index quickly.

# From demo-site/
pnpm index:docs                    # index the documentation/ folder (default)
pnpm index:docs docs               # index the docs/ folder instead
pnpm index:docs documentation --inspect   # preview chunks as JSON, no upload

The script:

  1. Reads all .md files and chunks them using @moss-tools/md-indexer
  2. Filters out chunks with 3 or fewer words (lone headings, empty sections, nav-only content)
  3. Uploads the remaining chunks to your Moss index

The --inspect flag writes chunks to .index-preview.json and exits without uploading — useful for verifying index quality before committing to an upload.


Testing Locally (Demo Site)

The repository includes a demo site in demo-site/ with two VitePress sites:

  • documentation/ — full Moss SDK docs with Moss search enabled (recommended for testing)
  • docs/ — minimal site

Step 1 — Build the plugin

From the repository root:

pnpm install
pnpm build

Step 2 — Set up the demo site

cd demo-site
pnpm install

Create a .env file with your Moss credentials:

# demo-site/.env  (never commit this file)
MOSS_PROJECT_ID=your_project_id
MOSS_PROJECT_KEY=your_api_key
MOSS_INDEX_NAME=your_index_name

Step 3 — Populate the index

Before starting the dev server, upload the documentation to your Moss index:

# From demo-site/
pnpm index:docs

You only need to re-run this when you add or change Markdown content.

Step 4 — Start the dev server

pnpm documentation:dev

Open http://localhost:5173 and use Ctrl/⌘+K or / to test the search modal.

Production build

pnpm docs:build     # builds docs/ site (also runs pnpm build in plugin root first)
pnpm docs:preview   # preview at http://localhost:4173

Troubleshooting

| Symptom | Likely cause | Fix | |---------|-------------|-----| | Build error: "vitepress" resolved to an ESM file | package.json missing "type": "module" | Add "type": "module" to your project's package.json | | Missing Moss configuration error | projectId, projectKey, or indexName not set | Check environment variables and themeConfig.search.options | | Could not load search index in browser | Index not built yet, or wrong credentials | Run vitepress build first; verify credentials | | No results returned | Index is empty or query doesn't match | Check the Moss dashboard for your index contents | | Page not indexed | Page has search: false in frontmatter | Remove the flag to include the page | | Modal doesn't open | Keyboard shortcut conflict | Try clicking the nav button directly |


Project structure

vitepress-plugin-moss/
├── index.ts          # mossIndexerPlugin — the main export; hooks into VitePress buildEnd
├── indexing.ts       # Re-exports buildJsonDocs + uploadDocuments from @moss-tools/md-indexer
├── Search.vue        # Search modal UI component (browser SDK)
├── SearchButton.vue  # Nav bar search button
├── types.ts          # MossSearchOptions interface + DefaultTheme module augmentation
├── vite.config.ts    # Build config for the plugin itself
├── tsconfig.json
└── package.json

Dependency split

vitepress-plugin-moss
├── @moss-tools/md-indexer   ← build time only (Node.js)
│   ├── @inferedge-rest/moss     REST client for uploading to Moss cloud
│   ├── vitepress                uses resolveConfig + createMarkdownRenderer
│   └── cheerio / gray-matter   HTML parsing, frontmatter
└── @inferedge/moss          ← runtime only (browser WebAssembly)
    └── Queries run locally after index is downloaded

Running Tests

# Install dependencies
pnpm install

# Run unit tests
pnpm test

# Run tests with watch mode
pnpm test -- --watch

Tests are also run automatically in the CI pipeline.


License

MIT