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

@stritti/vitepress-plugin-openspec

v0.7.0

Published

A VitePress plugin that integrates OpenSpec documentation into your VitePress site

Downloads

1,085

Readme

@stritti/vitepress-plugin-openspec

A VitePress plugin that renders your project's OpenSpec folder as structured documentation pages — specs, changes, and artifacts — with sidebar and nav integration.

npm version npm downloads License: MIT CI


Installation

npm install @stritti/vitepress-plugin-openspec
# or with bun:
bun add @stritti/vitepress-plugin-openspec

Usage

Add the following to your .vitepress/config.ts:

import { defineConfig } from 'vitepress'
import { withOpenSpec } from '@stritti/vitepress-plugin-openspec'

export default defineConfig(
  withOpenSpec({
    // your regular VitePress config
    themeConfig: {
      nav: [{ text: 'Home', link: '/' }],
      sidebar: {},
    },
  })
)

withOpenSpec handles everything in one call: page generation, the Vite plugin for live reload, the nav entry, and the sidebar section. All fields are optional — it works with an empty config object and sensible defaults.

Other Vite plugins go into vite.plugins as usual — withOpenSpec appends to the array without replacing it:

import { defineConfig } from 'vitepress'
import { withOpenSpec } from '@stritti/vitepress-plugin-openspec'
import myOtherPlugin from 'vitepress-plugin-something'

export default defineConfig(
  withOpenSpec(
    {
      vite: { plugins: [myOtherPlugin()] }, // preserved alongside openspec
      themeConfig: { nav: [], sidebar: {} },
    },
    { specDir: '../openspec', outDir: 'openspec' } // options (all optional)
  )
)

Options

| Option | Type | Default | Description | | --- | --- | --- | --- | | specDir | string | './openspec' | Path to your project's openspec/ directory. Can be an absolute path or relative to the working directory — use path.resolve(__dirname, '../../openspec') when config.ts lives in docs/.vitepress/. | | outDir | string | 'openspec' | Output directory relative to VitePress srcDir | | srcDir | string | process.cwd() | VitePress source directory (the docs/ folder) | | nav | boolean | true | Whether to prepend an openspec entry to themeConfig.nav | | sidebar | boolean | true | Whether to inject the openspec sidebar section into themeConfig.sidebar |

Missing directory — if specDir does not exist the plugin emits a console.warn and skips page generation, nav, and sidebar. No error is thrown and your VitePress build continues normally. This is intentional for projects that haven't set up an openspec/ folder yet.


Advanced / manual setup

If you need full control over each integration point, you can wire up the lower-level APIs individually:

import { defineConfig } from 'vitepress'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import openspec, {
  generateOpenSpecPages,
  generateOpenSpecSidebar,
  openspecNav,
} from '@stritti/vitepress-plugin-openspec'

const __dirname = path.dirname(fileURLToPath(import.meta.url))
const specDir = path.resolve(__dirname, '../openspec')

// Must be called before defineConfig so pages exist when VitePress scans for routes.
generateOpenSpecPages({
  specDir,
  outDir: 'openspec',
  srcDir: path.resolve(__dirname, '..'),
})

export default defineConfig({
  vite: {
    plugins: [openspec({ specDir, outDir: 'openspec' })],
  },
  themeConfig: {
    nav: [openspecNav(specDir, { outDir: 'openspec', text: 'Docs' })],
    sidebar: {
      '/openspec/': generateOpenSpecSidebar(specDir, { outDir: 'openspec' }),
    },
  },
})

Output Structure

The plugin reads your openspec/ folder and generates:

openspec/                     ← your source (not committed if used as output)
├── specs/
│   └── <capability>/
│       └── spec.md
└── changes/
    ├── <change-name>/
    │   ├── .openspec.yaml
    │   ├── proposal.md
    │   ├── design.md
    │   └── tasks.md
    └── archive/
        └── YYYY-MM-DD-<change-name>/

docs/openspec/                ← generated by the plugin (automatically gitignored)
├── index.md
├── specs/
│   ├── index.md
│   └── <capability>/
│       └── index.md
└── changes/
    ├── index.md
    ├── <change-name>/
    │   ├── index.md
    │   ├── proposal.md
    │   └── tasks.md
    └── archive/
        └── YYYY-MM-DD-<change-name>/
            └── ...

The plugin automatically writes a .gitignore into the output directory that excludes all generated files from version control. No manual .gitignore entry is needed.


How It Works

VitePress scans srcDir for .md files before any Vite plugin hooks run. The plugin solves this with two complementary mechanisms:

  1. generateOpenSpecPages() — called synchronously at the top of config.ts, before defineConfig(). Ensures all pages exist when VitePress scans for routes (critical for first builds and CI).
  2. openspec() Vite plugin — calls generateOpenSpecPages() again on every config reload during vitepress dev, keeping pages in sync with your source files.

Development

bun install       # Install dependencies
bun run build     # Build the plugin
bun run dev       # Watch mode
bun test          # Run tests
bun run lint      # Type check

License

MIT