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

@karaoke-cms/astro

v0.18.1

Published

Core Astro integration for karaoke-cms — virtual config, wikilinks, handbook routes

Readme

@karaoke-cms/astro

Core Astro integration for karaoke-cms. Wires up themes, modules, collections, menus, Obsidian embed handling, and the virtual config module at build time. Every karaoke-cms project depends on this package.

Installation

npm install @karaoke-cms/astro

Usage

// astro.config.mjs
import { defineConfig } from 'astro/config';
import karaoke from '@karaoke-cms/astro';
import karaokeConfig from './karaoke.config.ts';

export default defineConfig({
  site: 'https://your-site.pages.dev',
  integrations: [karaoke(karaokeConfig)],
});
// karaoke.config.ts
import { defineConfig } from '@karaoke-cms/astro';
import { loadEnv } from '@karaoke-cms/astro/env';
import { blog } from '@karaoke-cms/module-blog';
import { docs } from '@karaoke-cms/module-docs';
import { themeDefault } from '@karaoke-cms/theme-default';

const env = loadEnv(new URL('.', import.meta.url));

export default defineConfig({
  vault: env.KARAOKE_VAULT,
  title: 'My Site',
  description: 'What this site is about.',
  theme: themeDefault(),
  modules: [blog({ mount: '/blog' }), docs({ mount: '/docs' })],
});

Configuration

All fields are optional. Defaults produce a working site with no content.

| Field | Type | Default | Description | |-------|------|---------|-------------| | vault | string | project root | Path to the Obsidian vault directory (absolute or relative) | | title | string | 'Karaoke' | Site title for browser tab and nav | | description | string | '' | Site description for RSS and OG tags | | theme | ThemeInstance | — | Theme from themeDefault() or similar | | modules | ModuleInstance[] | [] | Additional modules not covered by the theme | | comments | CommentsConfig | — | Giscus comments config | | collections | Record<string, CollectionConfig> | — | Per-collection mode overrides | | layout.regions | { top, left, right, bottom } | — | Region component lists |

Obsidian embed syntax

Markdown files can use Obsidian's ![[file]] embed syntax. The integration handles it automatically:

Image embeds

![[photo.jpg]]           — embedded image (Astro-optimized)
![[photo.jpg|300]]       — image with width hint → <img width="300">
![[photo.jpg|300x200]]   — image with width and height → <img width="300" height="200">
![[photo.jpg|alt text]]  — image with alt text

Image files are resolved in this order:

  1. Same folder as the note
  2. Vault attachmentFolderPath from .obsidian/app.json
  3. Vault root

Resolved images go through Astro's image optimisation pipeline.

Audio and video embeds

![[recording.mp3]]   — → <audio controls>
![[clip.mp4]]        — → <video controls>

Audio and video files are served from /media/ in dev and copied to dist/media/ at build time.

Wiki links in featured_image frontmatter

featured_image: "[[hero.jpg]]"

The wiki link is resolved using the same vault path lookup as inline embeds and rewritten to /media/hero.jpg. Use resolveWikiImage() in your templates — see below.

resolveWikiImage(value)

A utility for templates that render featured_image. Call it on the raw frontmatter value — it rewrites [[file.jpg]] to /media/file.jpg and passes regular paths and URLs through unchanged.

import { resolveWikiImage } from '@karaoke-cms/astro';

// In an Astro template:
<img src={resolveWikiImage(entry.data.featured_image)} alt={entry.data.title} />

This is necessary because Astro sets entry.data from validated frontmatter at collection-load time, before the remark plugin runs. Templates must call resolveWikiImage() to get the resolved URL.

Exports

@karaoke-cms/astro — main integration

  • karaoke(config) — Astro integration (default export)
  • defineConfig(config) — identity wrapper for type inference
  • defineModule(def) — create a module factory
  • defineTheme(def) — create a theme factory
  • resolveWikiImage(value) — resolve [[wiki link]] to /media/ URL for use in templates

@karaoke-cms/astro/env

  • loadEnv(dir) — reads .env.default and .env from dir, returns merged record

@karaoke-cms/astro/collections

  • makeCollections(root, vault?, collections?) — creates Astro content collections from the vault

virtual:karaoke-cms/config

Available in any page or component at build time:

import {
  siteTitle,           // string
  siteDescription,     // string
  resolvedCollections, // Record<string, { modes, label, enabled }>
  resolvedMenus,       // Record<string, { name, orientation, entries }>
  resolvedLayout,      // { regions: { top, left, right, bottom } }
  resolvedModules,     // { comments: { enabled, repo, repoId, category, categoryId } }
  blogMount,           // string — the blog module's mount path
} from 'virtual:karaoke-cms/config';

Add to src/env.d.ts for TypeScript types:

/// <reference types="@karaoke-cms/astro/client" />

Menus

Define menus in {vault}/_website/menus.yaml. When absent, defaults are generated: a main menu with Blog/Docs/Tags and a footer menu with the RSS link. Entries support when: collection:name to hide automatically when a collection is empty.

Layout regions

Four regions (top, left, right, bottom) accept component lists from karaoke.config.ts:

layout: {
  regions: {
    top:    { components: ['header', 'main-menu'] },
    right:  { components: ['recent-posts'] },
    bottom: { components: ['footer'] },
  }
}

Available components: 'header', 'main-menu', 'search', 'recent-posts', 'footer'.

What's new in 0.18.1

  • menus.yaml location changed — the navigation config file moved from {vault}/karaoke-cms/config/menus.yaml to {vault}/_website/menus.yaml. If you have an existing menus.yaml, move it to _website/menus.yaml in your vault root.

What's new in 0.18.0

  • Nested docs routes — docs pages now use a [...slug] rest parameter instead of [slug], so subdirectories within a docs section resolve correctly. No config changes needed.
  • Section switcher everywhere — the styled nav showing all active docs sections now appears on doc pages, section home pages, and section list pages (previously doc pages only).
  • DocsTree sidebar cleanupindex.md leaf nodes are hidden from the sidebar and hoisted to their parent directory node, reducing visual clutter.
  • Wikilink resolution fix — relative links inside docs sections are now resolved against the module's mount path, so cross-page links work correctly in any docs section regardless of URL prefix.
  • Blog folder config in link normalization — relative link normalization now respects the blog module's configured folder, fixing broken links when the blog folder differs from the default.
  • modes on module instances — modules can now declare modes: ['dev'] or modes: ['dev', 'prod'] directly on the ModuleInstance, replacing the need for collections.yaml overrides.

What's new in 0.17.0

  • Submenu supportmenus.yaml entries now support parent: <id> to nest under a root entry as a hover/click submenu. Use static: "Label" for a non-interactive parent label. The Menu.astro component renders a toggle button for keyboard accessibility.
  • themeDefault() takes no arguments — modules are passed via modules: [] in defineConfig(), not via implements: [] inside the theme call. Update karaoke.config.ts if you were using the old pattern.
  • Per-module comments defaultblog() and docs() accept comments?: boolean. Blog defaults to true, docs defaults to false. Individual pages can still override via frontmatter comments: true/false.
  • Docs array formdocs([...]) now accepts a DocsSection[] array, returning one ModuleInstance per section. Each section can specify weight and parent for menu ordering and nesting.

What's new in 0.10.3

  • Vault path warning — if KARAOKE_VAULT points to a directory that doesn't exist, a clear warning is printed at startup instead of silently building a site with empty collections. The message shows the resolved path and points to .env / .env.default.
  • menus.yaml live reload — editing {vault}/_website/menus.yaml while the dev server is running now triggers an immediate full-page reload. No more restarting npm run dev after menu changes.
  • Security: path traversal guard hardened — the docs codegen path-traversal check now uses path.normalize() on both sides of the comparison, so the guard holds correctly on Windows and with symlinked paths.

What's new in 0.10.2

  • Multiple named docs sections — run docs({ mount: '/api-docs', folder: 'api-reference', label: 'API Reference' }) alongside docs({ mount: '/docs' }). Each section gets its own sidebar, URL space, and Astro content collection. Routes are code-generated per instance at build time.
  • Auto-registered docs collections — pass your full config to makeCollections({ config }) in content.config.ts and all docs instances register automatically. No manual sync required when adding a second section.
  • virtual:karaoke-cms/docs-sections — new Vite virtual module exporting all active docs section specs. Import it in any page to build section switchers or cross-section links.
  • Section switcher in doc pages — when two or more docs sections are active, a nav row lists them with the current one highlighted.
  • Tags and RSS are section-aware/tags, /tags/[tag], and /rss.xml now aggregate entries from every active docs section.
  • Fix: dev-only collection menu entries — entries with when: collection:name now correctly show in dev mode when the collection exists but has no published entries.

What's new in 0.10.0

  • Obsidian ![[image]] embed support![[photo.jpg]] in any markdown note is resolved via vault path lookup and goes through Astro's image optimisation pipeline
  • Size hints![[photo.jpg|300]] sets width="300"; ![[photo.jpg|300x200]] sets both width and height
  • Audio and video embeds![[recording.mp3]]<audio controls>, ![[clip.mp4]]<video controls>; files served from /media/ in dev, emitted to dist/media/ at build
  • featured_image wiki link supportfeatured_image: "[[hero.jpg]]" in frontmatter is resolved to /media/hero.jpg via vault path lookup
  • resolveWikiImage(value) export — utility for templates to rewrite [[file.jpg]] frontmatter values to the correct /media/ URL at render time

What's new in 0.9.5

  • isThemeInstance type-guard added — fixes a runtime crash in the astro:config:setup hook when a ThemeInstance was passed
  • Module array APImodules in config is now ModuleInstance[] (was a legacy object shape in some docs)
  • Tighter astro.config.mjs error handling — missing karaoke.config.ts is now distinguished from missing dependencies of that file; the latter now surfaces the real error instead of silently falling back to empty config