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

codetour-builder

v0.4.1

Published

Build CodeTour .tour files from a JS manifest — resolves tree-sitter anchors, fills step numbers, auto-generates appendix back-links, validates, and emits .tour JSON.

Readme

codetour-builder

Build CodeTour .tour files from a JS manifest.

You write a manifest (markdown + tree-sitter queries); the builder:

  • resolves each step's CSS selector (tree-sitter based) to a line / selection
  • assigns step numbers (1-based, manifest order)
  • fills [@id] step refs and [@tourId] tour refs (hub/spoke)
  • auto-discovers ↩ back-links — any step referenced via [@stepId] from another step's desc (same tour) gets a "Back to" link, deduped + ordered by step number
  • validates (ids unique, refs resolve, files exist, selectors resolve)
  • JSON.stringifys everything — no manual escaping

CSS/query steps are emitted with both a top-level line and a selection: line drives CodeTour's gutter markers + reveal target, selection drives the precise text highlight. Pattern/line steps emit line only.

Supports JS / TS / JSX / TSX for queries.

Install

npm install -g codetour-builder    # global command
# or
npm install codetour-builder       # local devDep, use npx

Usage

codetour-builder <manifest.mjs>        # build + write .tour files into cwd
codetour-builder <manifest.mjs> --dry  # validate only, write nothing
codetour-builder <manifest.mjs> --out .tours/<topic>/   # write .tour files into a folder
codetour-test-query <file> ".css.selector[text=...]"   # debug a CSS selector (default)

Run from the project root. Step file: paths resolve against the current working directory and pass through into the .tour files verbatim — CodeTour resolves them against the workspace root, so both the build and playback need the same base. Use workspace-root-relative paths like src/index.ts. Emitted .tour files land in --out <dir> (default: current directory), and --out directories are created if missing. Exit 0 = success; non-zero prints an ERRORS: list.

Testing queries before writing the manifest

Iterate on a query against a real file before committing it to a manifest step:

codetour-test-query src/index.ts ".method_definition .identifier[text=x]"

It prints every match with capture name, node type, 1-based line range, and a code snippet — so you can see exactly where the pattern hits.

Try the package in 30 seconds

cd examples
codetour-builder example-manifest.mjs       # writes example-quick.tour
codetour-builder example-manifest.mjs --dry
codetour-test-query sample-source.js ".method_definition"

The manifest

ES module, default export = array of tours (one manifest can emit many tours — e.g. hub + quick + detailed).

export default [{
  id: "hub",                       // tour id (slug), unique
  title: "Example: Pipeline",
  isPrimary: true,                 // optional — present on first open
  filename: "hub",                 // optional — output name, default slug(title)
  steps: [
    { id: "choose", title: "Choose a tour",
      desc: `Pick: [quick][@quick] or [detailed][@detailed]` },  // content-only step
  ],
}, {
  id: "quick",
  title: "Pipeline quick",
  steps: [
    { id: "overview", title: "1 · Overview",
      file: "sample.js",                        // relative to project root (cwd)
      selector: { kind: "css", selector: ".function_declaration" },
      desc: `**\`buildPipeline\`** is the entry point.` },
  ],
}, {
  id: "detailed",
  title: "Pipeline detailed",
  steps: [
    { id: "root", title: "0 · Start here",
      file: "sample.js",
      selector: { kind: "css", selector: ".function_declaration" },
      desc: `The [appendix][@compute-total] holds each file.` },
    { id: "compute-total", title: "A1 · computeTotal",
      file: "sample.js",
      selector: { kind: "css", selector: ".function_declaration" },
      desc: `Sums items. Refers back to [the root][@root].` },
  ],
}]

compute-total is referenced by root ([appendix][@compute-total]) and references root in its own desc — so the builder auto-appends ↩ back-links on both steps, deduped and ordered by step number.

Tour fields

| field | required | meaning | |---|---|---| | id | yes | slug, unique across the manifest | | title | yes | display name; also the CodeTour tour-ref target | | isPrimary | no | present this tour on first open | | filename | no | .tour output name (default: slug of title) | | steps | yes | ordered step objects |

Step fields

| field | required | meaning | |---|---|---| | id | yes | unique within the tour; used in [@id] refs | | title | yes | display title | | desc | yes | markdown body — template literal | | file | with selector | path relative to the project root (cwd the builder runs from) | | selector | no | locate the position (below) |

Steps with no file/selector = content-only (intro, choice page, hub splash).

Auto ↩ back-links

Back-links are not declared — the builder discovers them. For each step, it reverse-indexes same-tour [@stepId] refs written in other steps' desc and appends a ↩️ [Back to <step>][#N] link to every referenced step, deduped and ordered by the referencing step's number. Cross-tour refs ([@tourId]) never produce back-links.

So to give an appendix step a back-link, just reference it from the main flow (via [@stepId]), and optionally reference the main flow from the appendix.

Selectors

Exactly one of three kinds per step:

selector: { kind: "css",     selector: ".method_definition .identifier[text=x]" }  // preferred
selector: { kind: "pattern", pattern: "^export function\*" }                              // regex on a line
selector: { kind: "line",    line: 169 }                                                    // explicit 1-based line
  • css — CSS-style selector over the tree-sitter parse tree. Descendant combinator (A B) skips intermediate nodes; attribute selectors ([text=x], [text*=y]) filter by content. See references/selectors.md in the skill for the full reference. (Legacy kind: "query" S-expressions still work but are not recommended — no level-skipping, no text filtering.)
  • pattern — JS regex matched per line; first match → single line.
  • line — explicit 1-based line. Last resort.

Selectors work on .js .jsx .mjs .cjs (tree-sitter-javascript) and .ts .tsx .mts .cts (tree-sitter-typescript). Other extensions fail css — use pattern/line.

Refs between steps and tours

Write these in markdown; the builder replaces them:

  • [label][@stepId] — same-tour step ref → [label][#N]
  • [label][@tourId] — whole-tour ref → [label][Tour Title] (hub/spoke)

The builder matches only the [@id] marker (not the whole [label][@id]), so the label keeps its authored markdown — labels containing inline code or emphasis work fine: [`hello`][@stepId] → [`hello`][#N]. Every authored [@id] must resolve to a step or tour id; an unknown ref is a build error (never silently left in the output).

Same-tour [@stepId] refs also drive the auto ↩ back-links (see above). Never write [#N] by hand — numbers shift when steps reorder.

Hub / quick / detailed

One manifest, array of 3 tours:

  • hub — isPrimary, content-only "choose a mode" step with [@quick] + [@detailed]
  • quick — 5-7 skim steps
  • detailed — numbered main flow + appendix (appendix steps get ↩ back-links automatically when the main flow references them via [@stepId])

Builder emits one .tour per tour into the --out folder (default: current directory).

Markdown rules

  • desc is a template literal.
  • Code blocks: use HTML <pre><code>...</code></pre>, not triple-backtick fences (fences trigger CodeTour's "Insert Code" button + need backtick escaping). Escape </> as &lt;/&gt;.
  • Inline code `x` in a template literal — escape: \`x\`.
  • Placeholders replaced only in plain text (remark AST) — never inside code blocks/inline code.

Publishing

Update the changelog

Add the changes for the new version to CHANGELOG.md.

Verify the release

node bin/build-tour.mjs --help

Publish the release

npm version minor -m "chore: release v%s"
git push origin main --follow-tags
VERSION="$(node -p "require('./package.json').version")"
gh release create "v$VERSION" --generate-notes
npm publish

Use npm version patch or npm version major when appropriate.

License

MIT