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

create-viteframe

v1.0.1

Published

Create a new ViteFrame app — file-based routing, reactive state, dynamic components

Readme

create-viteframe

Scaffold a new ViteFrame app — a lightweight SPA framework built on Vite with file-based routing, reactive state, and dynamic HTML components. No external JS dependencies.

Quick start

npm create viteframe@latest my-app
cd my-app
npm install
npm run dev

Or with pnpm / yarn:

pnpm create viteframe my-app
yarn create viteframe my-app

What you get

src/
├── core/
│   ├── router.js       # File-based SPA router (~180 lines)
│   ├── state.js        # Reactive state store (~100 lines)
│   └── components.js   # Dynamic component loader (~120 lines)
├── pages/
│   ├── landing.page.html          # → /
│   ├── about.page.html            # → /about
│   ├── docs.page.html             # → /docs
│   └── [id]post.page.html         # → /post/:id
├── components/
│   ├── header.comp.html
│   └── toast.comp.html
├── styles/
│   └── main.css        # Design tokens + utility classes
└── main.js             # Bootstrap

All framework code lives in your project — read it, modify it, own it.


Routing

File name determines the route. Drop files in src/pages/.

| File | Route | | ------------------------- | ----------------- | | landing.page.html | / | | about.page.html | /about | | [id]post.page.html | /post/:id | | [id-slug]post.page.html | /post/:id/:slug | | [lang-id]post.page.html | /post/:lang/:id |

Programmatic navigation

window.__vf.navigate("/about");
window.__vf.navigate("/post/42", { replace: true });

State

Global state

Shared across all pages. Persists during navigation.

const { globalState } = window.__vf;

globalState.set("user", { name: "Alice" });
globalState.get("user");
globalState.subscribe("user", (val) => console.log(val));

// Bind value → DOM (auto-updates when state changes)
globalState.bind("user", el, (u) => u?.name ?? "Guest");

// Two-way bind: input ↔ state
globalState.bindInput("search", inputEl);

// Partial merge
globalState.merge("settings", { darkMode: true });

Page state

Isolated to a single page visit. Created inside onMount, discarded on navigation.

export function onMount() {
  const { createPageState } = window.__vf;
  const state = createPageState({ count: 0, open: false });

  state.update("count", (n) => n + 1);
  state.bind("count", document.getElementById("counter"));
}

Computed values

const { computed, globalState } = window.__vf

const fullName = computed(
  ['firstName', 'lastName'],
  [globalState, globalState],
  (first, last) => `${first} ${last}`
)

fullName.get()              // 'Alice Smith'
fullName.subscribe(v => …)  // fires when either dep changes

Components

Components are .comp.html files in src/components/. They support scoped <style> and <script> blocks.

Use in HTML

<!-- Simple -->
<component src="header"></component>

<!-- With props via data-* attributes -->
<component src="card" data-title="Hello" data-body="World"></component>

Template syntax

<!-- src/components/card.comp.html -->
<div class="card">
  <h3>{{title}}</h3>
  <p>{{body}}</p>
</div>

Mount from JavaScript

const { mountComponent } = window.__vf;

await mountComponent("#target", "card", { title: "Hello", body: "World" });

Page lifecycle

Add <script data-lifecycle> to any page and export onMount:

<script data-lifecycle>
  export function onMount({ params, query, globalState }) {
    // params  → route params  e.g. { id: '42' }
    // query   → ?key=val      e.g. { tab: 'info' }
    // globalState → shared store

    console.log("id:", params.id);
    console.log("tab:", query.tab);

    const { createPageState } = window.__vf;
    const state = createPageState({ count: 0 });
  }
</script>

Navigation guards

In src/main.js:

router.beforeEach(({ pathname }) => {
  if (pathname.startsWith("/admin") && !globalState.get("user")) {
    router.navigate("/login");
    return false; // cancel navigation
  }
});

Toast notifications

Include <component src="toast"> on a page, then anywhere:

window.toast("Saved!", "success"); // green
window.toast("Something broke", "error"); // red
window.toast("FYI", "info", 5000); // purple, 5s

CSS design tokens

All colors, spacing, and radii are CSS variables in src/styles/main.css.

/* Override in your own CSS */
:root {
  --accent: #your-color;
  --radius: 12px;
}

Dark/light theme is toggled by setting data-theme="light" on <html>:

window.__vf.globalState.set("theme", "light");

License

MIT


Website

Github