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

@zshoham/teaman

v1.3.0

Published

Static site generator for Obsidian vaults (Astro engine).

Readme

teaman

A static site generator for Obsidian vaults. teaman is an installable Astro engine; your vault stays pure data — content plus a teaman.config.js — and you build it with one command:

npx @zshoham/teaman build ~/vaults/my-notes      # → ~/vaults/my-notes/dist
npx @zshoham/teaman dev   ~/vaults/my-notes      # live preview

Published to the public npm registry as @zshoham/teaman — no auth needed to install. Tagged releases ship as latest; every main commit also publishes a prerelease under the dev tag (npx @zshoham/teaman@dev).

The vault never contains engine source, only:

my-vault/
  teaman.config.js     # site identity + theme (see below)
  notes/    *.md        # evergreen notes (wiki-links, callouts, mermaid, plantuml, tikz, typst)
  guides/   <slug>/SUMMARY.md + chapters
  slides/   *.md        # Slidev decks
  dailies/  YYYY-MM-DD.md
  decisions/ adr-NNNN.md # architecture decision records (timeline at /decisions/)
  public/   …           # optional static passthrough (logo, images)

Run npx @zshoham/teaman init my-vault to scaffold the config and content dirs.

Each decisions/adr-NNNN.md is one Architecture Decision Record: frontmatter carries title, date, status (accepted | proposed | superseded), optional tags, a one-line summary, and optional supersedes / supersededBy (the NNNN of a related ADR); the body holds the prose (Context / Decision / Consequences). They render as a filterable timeline at /decisions/ and also appear in the home feed.

SVG images are inlined and theme-aware. A markdown image pointing at a local .svg (![alt](attachments/diagram.svg)) is inlined into the page at build time, so currentColor and theme tokens like var(--primary) resolve against the site theme and the graphic follows the light/dark toggle. Give tokens fallbacks (fill="var(--primary, #a4551c)") so the file still renders on its own. The file can live anywhere in the vault: relative paths resolve against the note's directory first, then the vault root, then public/. Remote URLs and other image formats stay plain <img> (put those in public/). The alt text renders as a visible caption under a standalone image (and as the hover tooltip + accessible name); an empty alt marks the graphic decorative.

TikZ and Typst compile to SVG at build time. A ```tikz fence runs through a WASM TeX engine (the same one the Obsidian TikZJax plugin uses — no local LaTeX install needed; write what goes between the document tags, usually just the tikzpicture environment) and a ```typst fence through the native Typst compiler (the page auto-sizes to the content unless you #set page(...) yourself). Both render as inline SVG with black ink rewritten to currentColor, so they follow the light/dark toggle like mermaid and plantuml do. Renders are cached by content hash (.diagram-cache/ in the engine — disposable), so only new or edited diagrams pay the compiler; a fence that fails to compile shows a quiet error notice in place and warns during the build instead of failing it.

Commands

| Command | What it does | |---|---| | teaman build [vault] | Build to <vault>/dist (or --out DIR). Runs Astro + Slidev + Pagefind. | | teaman dev [vault] | Live Astro dev server. | | teaman preview [vault] | Serve a previously built site. | | teaman init [vault] | Scaffold teaman.config.js + content dirs. | | teaman doctor [vault] | Validate config and lint content without building. Exits non-zero on problems — gate CI with it. | | teaman sync-confluence | Publish vault markdown to Confluence Server/Data Center. Dry-run by default; pass --apply to write. |

Options: --out <dir>, --base <path> (e.g. /my-site/ for sub-path hosting), --port <n> (dev). [vault] defaults to the current directory.

sync-confluence takes its own flags (run teaman sync-confluence --help); the essentials are --content-dir <vault>, --base-url, credentials (--user/--token or --pat), and --roots folder=pageId,…. Each can also come from a CONFLUENCE_* env var. Local .svg images resolve the same way the site build does (note's directory, then the vault root, then public/) and upload as attachments; since Confluence Server/DC won't preview those inline, --svg-macro <name> (e.g. the stock html macro) inlines the svg markup into that macro instead. ```tikz/```typst fences compile to svg during the sync (sharing the site build's diagram cache) and then sync the same way; a fence that fails to compile syncs as a labeled source block.

Config — teaman.config.js

Pure data, default-exported (the CLI serializes it). All fields are optional except brand; omitted fields fall back to engine defaults. The hero block is no longer rendered (the home page starts directly at the feed) but is kept for backwards compatibility — new vaults can omit it.

export default {
  engine: '^1.0',               // engine semver range this vault targets
  brand: 'my.vault',
  tagline: 'a working garden',
  logo: 'assets/logo.svg',      // relative to vault, then vault/public, then engine default
  hero: {
    eyebrow: 'an open notebook',
    title: 'Notes & slides<br/><em>from a working vault.</em>',  // inline HTML ok
    description: 'A thin public window onto an Obsidian vault.',
  },
  footerNote: 'made slowly',
  links: [                       // quick-link tiles, bento grid above the home feed
    { label: 'Obsidian', url: 'https://obsidian.md', description: 'The app this vault lives in.', icon: 'book' },
    { label: 'repo', url: 'https://github.com/me/vault', icon: 'github' },
  ],                             // `icon`: curated lucide set or any string (emoji ok).
                                 // tile sizes are auto-computed from content + count.
  theme: {                      // CSS-var overrides (the entire styling surface)
    '--primary': 'oklch(0.67 0.14 48)',
    '--radius': '0.5rem',
  },
  slides: {                     // project-wide Slidev styling (all optional)
    logo: 'assets/logo.svg',    // shown on the footer strip of every slide
    primary: 'oklch(0.62 0.15 48)',
    secondary: 'oklch(0.58 0.05 196)',
    footer: true,               // show the footer strip (default true)
  },
};

Theming

theme is the only per-vault styling surface — a map of CSS custom properties layered onto :root. There are no per-vault component or CSS files, which is what lets engine upgrades land without a merge. Token names mirror :root in src/styles/global.css (e.g. --primary, --background, --foreground, --border, --radius, --accent). Unknown tokens are simply unused; teaman doctor flags them.

Slides

Every Slidev deck in slides/ is built with the engine's bundled theme (slidev-theme-teaman) — Source Serif 4 display, Inter body, JetBrains Mono code, one warm accent, matching the site. You don't set a theme: in any deck; the build applies it to all of them. The only knobs are project-wide, under slides:

  • logo — a mark shown on the footer strip of every slide (resolved like logo: vault public/, then the vault root). Omit for none.
  • primary / secondary — accent colors (any CSS color). Defaults match the site's warm accent. secondary also paints the footer strip, giving the logo one fixed backdrop regardless of the light/dark slide theme.
  • footer — show the footer strip carrying the logo (default true); set false to hide it (and its logo).

These flow into the theme at build time, so decks stay pure content.

Versioning & upgrades

Because the vault is pure data, upgrading the engine is changing one number.

  • Pin via engine. Put a semver range ('^1.0', '~1.0.2') in your config. Every teaman run compares it to the running engine and warns on mismatch. With the npx model there's no lockfile, so pin tightly for byte-stable rebuilds (e.g. CI: npx @zshoham/[email protected] build). Built pages carry <meta name="generator" content="teaman X.Y.Z"> for after-the-fact debugging.
  • Semver contractpatch: fixes/dep bumps, always safe. minor: new optional config keys, content types, theme tokens — old configs keep working. major: a config key removed/renamed, frontmatter schema tightened, or URL structure changed — see MIGRATING.md.
  • teaman doctor after any bump validates your config against the engine's schema and lints content, so you get a warn-then-fix path instead of a broken build.

Developing the engine

This repo is the engine: the Astro app, CLI, and build scripts live at the repo root, plus a bundled example vault in example/. Work from the repo root:

npm install
npm run dev      # serves the bundled example/ vault (no CLI needed)
npm run build    # writes ./public
npm test         # vitest unit suite

The engine reads the vault, output, base, config, and static dir from TEAMAN_VAULT / TEAMAN_OUT / TEAMAN_BASE / TEAMAN_CONFIG / TEAMAN_PUBLIC; when unset it falls back to the bundled example/public/, which is why the plain npm scripts and tests work in place.

Building & previewing the current vault

The npm run dev above serves example/ straight through Astro, which is the fastest inner loop. To exercise the full CLI path — config serialization, Slidev, Pagefind, the engine version check — against the bundled vault before publishing or cutting a release, drive the local bin directly:

The bundled vault lives at the repo root (example/). Pass the wrong path and the CLI warns no content dirs found but still builds — you get the home page with zero notes, which is the usual cause of an empty preview.

npm install
node bin/teaman.mjs build ./example      # → example/dist (Astro + Slidev + Pagefind)
node bin/teaman.mjs preview ./example     # serve example/dist as it'll ship

node bin/teaman.mjs dev ./example is the CLI equivalent of npm run dev, and node bin/teaman.mjs doctor ./example validates example/teaman.config.js and lints the notes without building. Add --out <dir>, --base /sub-path/, or --port <n> to mirror a specific deploy target. example/dist is throwaway — delete it between runs if you want a clean build.

To test the CLI exactly as a consumer would get it (from the packaged tarball rather than the working tree), pack and run it against any vault:

npm pack                                     # → zshoham-teaman-<version>.tgz
npx ./zshoham-teaman-1.0.0.tgz build ./example   # same as a published `npx @zshoham/teaman`

npm run test:integration automates exactly this — pack, install the tarball into a throwaway project outside the repo, build the example/ vault, and assert the output. It's the only check that catches packaging bugs (an incomplete files list, a runtime dep stranded in devDependencies), so it runs as its own CI job.