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

@xanots/onboard

v0.1.0-beta.1

Published

Visual onboarding for XanoTS — configure your theme and pick backend modules in the browser, then get the scaffolded project back in your terminal.

Readme

@xanots/onboard

Visual onboarding for XanoTS. Pick your framework, theme, fonts, icons and backend modules in a browser; get the scaffolded project back in your terminal.

npx @xanots/onboard my-app

It opens a local page, waits for one answer, and finishes in the shell you ran it from.

What it is not

It is not a second scaffolder. Everything it can produce, xanots init can produce from flags — and onboarding prints the equivalent command when it is done:

The same project, from flags:
  npx xanots init my-app --framework react --theme mist-teal --radius 1rem \
    --dark toggle --icons tabler --font geist --font-heading instrument-serif --ai codex

That constraint is deliberate. A configuration you cannot express as a command is one you cannot put in a script, a README, or a bug report. The browser is a nicer way to arrive at those flags, not a different way to build a project.

xanots init keeps working exactly as it did, prompts included.

How it works

npx @xanots/onboard
  │
  ├─ fetch the module catalogue          (public, unauthenticated)
  ├─ start a loopback server on 127.0.0.1:<ephemeral>
  ├─ open the browser at /?token=<per-run secret>
  │     …you configure…
  ├─ POST /api/create  →  server closes
  └─ run(["init", …, "--marketplace", "@xanots/auth,…"])   via @xanots/sdk/node

The scaffold itself comes from the SDK's own CLI dispatcher, so everything init guarantees — the lock file, the agent briefs, the contract between xano/ and frontend/ — holds here without being reimplemented, and a change to init reaches onboarding with no release of onboarding.

The theme travels the same way. xanots init --theme accepts a path to a shadcn registry item, so a palette edited token-by-token in the browser needs no new SDK surface: it is written to a temp file and passed by path. A preset pair (zinc-blue) is forwarded by NAME instead, so the generated README and agent brief can record which theme you picked.

Style presets

The style step opens on six finished looks rather than on an empty grid — Xano Blue (the default), Graphite, Terracotta, Meadow, Orchid and Lagoon. Each one sets the palette, the corner radius, the typeface pairing and the icon set together, so one click lands on something coherent; every control below stays live, and changing anything simply puts you on your own palette.

Xano is a base colour in that step, sitting alongside shadcn's seven: its own brand palette (#0b5aff on blue-tinted paper, navy in the dark), and an accent composes over it exactly as it does over stone or mist. The base swatches show each base carrying your current accent, in whichever mode the light/dark switch above them is set to — shadcn's bases are a few thousandths of chroma apart in light and clearly different in dark, so that switch is part of the chooser rather than a preview convenience.

Five of the six presets name one of the SDK's own base×accent pairs and travel to the CLI by name, so the generated README still records which theme you picked. Xano Blue is on a base the SDK has never heard of, so it travels as a token map instead. The table lives in app/src/lib/presets.ts, the composition in app/src/lib/theme.ts.

One session, running through the wizard

Three of the four steps share a surface: Xano's own palette, the mono voice of the terminal you launched this from, and a terminal that follows you and grows as you go — the command starts on step one, gains an install line as you pick modules, and is the whole sequence about to run by the time you reach Review. Everything it shows is built by src/init-args.ts, the one module both halves import, so the command on screen and the command the CLI runs cannot drift.

The style step is deliberately exempt. The chrome there is plain because it frames a preview of someone else's theme, and a frame with opinions competes with the thing being judged — but that argument only ever applied to the screen with a preview on it. The other three have nothing to compete with.

There is no webfont anywhere. This page is served from a loopback port with no network guarantee, which is also why the framework logos are inlined.

The plugins step is a marketplace

Modules come from GET /api:marketplace/plugins, never from a list baked into this package — one published tomorrow appears without a release of onboarding. That is also why the step is built for a catalogue far larger than today's: cards three to a row rather than full-width rows, search across everything a module says about itself (not just its title), tag filters derived from the catalogue itself, a pinned record of what you have picked, and long-form detail in a modal so a card never expands and tears a hole in the grid.

The preview is a working app

The right-hand pane of the style step is not a screenshot. The dashboard navigates, the table sorts and selects, the forms take input, the charts answer the pointer, and the header's theme switch flips the pane between light and dark. That is deliberate: hover, focus-visible, checked, selected and disabled are half of what a palette gets wrong, and none of them exist in a page made of <span>s.

The rule it keeps is that nothing you would otherwise never see is hidden behind a click — the dropdown and the command palette render open, the focus ring is pinned on one input, and the email field starts invalid — so a state you did not think to go looking for is still on screen. Nothing in the pane leaves the browser; "deploying" is a timer.

Security

The server binds to 127.0.0.1 only, and every /api/* request carries a per-run UUID that the CLI puts in the URL it opens. Without it, any page in any tab could POST a config to that port while onboarding is running and have a project scaffolded — and npm install run — at a path of its choosing. Static file paths are resolved and then checked to be inside the app directory, so a request cannot escape it. The server is shut down before any scaffolding begins.

Development

npm install
npm run build          # client into dist/app, CLI into dist/
npm test
npm run dev            # UI with hot reload…
npm run dev:cli -- --port 7777 --no-open   # …and the API it proxies to

The client lives in app/, the Node half in src/, and src/protocol.ts is the wire contract both import — so a drift between them is a compile error rather than a runtime surprise.

Working against a local SDK

@xanots/sdk is a published range in package.json. To develop against a checkout instead, link it rather than editing the manifest — an absolute file: path committed to the repo breaks the install for everyone else:

npm install --no-save /path/to/sdk

Modules are the CLI's job now

Onboarding used to install each selected module itself and compose xano/index.ts by parsing the catalogue's register_snippet for each one. That was 425 lines of heuristics, and it existed because the snippets could not be pasted: each is a whole file with its own export default and a hardcoded workspace("my-app"), two of them import @xanots/core (the SDK's former name, still on npm, deprecated), and they come in three shapes that nothing but usage distinguishes.

The fix this README used to ask for — "publishing the registration as structured data would make this parsing unnecessary" — is what xanots init --marketplace <a,b> now does. A module declares how it registers in its own package.json:

"xanots": { "register": "registerAuth", "returns": "workspace" }

and the CLI reads that off the installed package instead of reading prose about it. A module that has not adopted the field still works: its installed entry is imported and read for a single register* export — real exports, not prose.

The three shapes stopped mattering along the way. Registration MUTATES the workspace (registerAuth returns the same object it was handed; registerVector returns a handle, having already registered onto that instance), so the generated file calls each one as a statement and exports the workspace. Nothing is ever chained, which is what made registerChatbot's non-workspace return type dangerous before.

What stays here is the one thing the CLI cannot know: the catalogue's requirements — the API keys and accounts a module needs before it will deploy. Those describe the world outside the project, so they are not in the package.

Requires an @xanots/sdk with the flag. An older CLI rejects unknown flags outright, which is the right failure: loud, at the first create, rather than a silent scaffold missing every module.

Adding a module to the picker

Nothing here. The picker renders whatever GET /api:marketplace/plugins returns, so a newly published module appears without a release of this package. Point it at a different catalogue with XANOTS_MARKETPLACE_URL, the same variable the SDK's marketplace commands read.

License

MIT