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

@bjro/spriggan

v1.0.0

Published

A minimal TEA (The Elm Architecture) framework for the browser — no build tools, pure functions

Readme

🌿 Spriggan

A tiny, elegant framework inspired by The Elm Architecture—no build tools, pure functions, built for humans and LLMs alike.

GitHub | Live Demo

<div id="app"></div>
<script type="module">
  import createSpriggan, { html } from './src/spriggan.js';

  const { app } = createSpriggan();

  const Msg = { Inc: 'Inc' };

  const appInstance = app('#app', {
    init: { count: 0 },
    update: (state, msg) => (msg.type === Msg.Inc ? { count: state.count + 1 } : state),
    view: (state) => html`<div><h1>${state.count}</h1><button data-msg=${{type: Msg.Inc}}>+</button></div>`,
  });

  // Programmatic dispatch (use the same Msg enum)
  // appInstance.dispatch({ type: Msg.Inc });
</script>

That's it. No compilation. No configuration. Just functions and data.


Elevator Pitch

Spriggan is a 750-line core framework that brings The Elm Architecture to vanilla JavaScript. It's designed for:

  • Prototyping – Drop src/spriggan.js into a page and start building
  • Teaching – Three concepts: Model, Update, View
  • AI pair programming – LLMs understand it instantly (no JSX, no hooks, no magic)
  • Maintainability – Pure functions, unidirectional data flow, zero surprises

If you've ever felt that modern frontend development has too many moving parts, Spriggan is for you.


Quick Start

Use as an ES module (recommended)

This repository ships the source module at src/spriggan.js. The examples and the live demo import it directly as an ES module.

  • Open index.html in this repository with a static server (recommended for module imports):

    • python -m http.server 8000
    • or npx http-server .
    • Then open http://localhost:8000.
  • Or import directly from the file in a module script (see examples):

<script type="module">
  import createSpriggan, { html } from './src/spriggan.js';
  const { app } = createSpriggan();
  // ...
</script>

CDN / npm usage (note)

The README historically showed a CDN snippet (e.g. https://unpkg.com/spriggan/dist/spriggan.min.js). This repository currently contains the source module only and does not include a prebuilt dist/ bundle or published npm package. The CDN snippet in older docs is an example of what consumers could use after publishing — not a shipped artifact in this repo.

If you want a UMD/Browser bundle for CDN use, build and publish first. Example (esbuild):

npx esbuild src/spriggan.js --bundle --minify --format=umd --global-name=Spriggan --outfile=dist/spriggan.min.js

Representative Patterns (with links to examples)

Below are concise, representative patterns you will encounter in real apps. Full working examples live in the examples/ directory — open them with a static server.

  1. Counter (simple state + events)
// examples/basic counter
const init = { count: 0 };
function update(state, msg) {
  if (msg.type === 'Inc') return { count: state.count + 1 };
  return state;
}
function view(state) {
  return html`<div><h1>${state.count}</h1><button data-msg='{"type":"Inc"}'>+</button></div>`;
}
app('#app', { init, update, view });

See: examples/slideshow and examples/tea-walkthrough for counters used in demos.

  1. Todo app (add/toggle/delete + persistence)
  • Pattern: keep all state in model, return effects to persist.
  • Example: examples/todo.js demonstrates storage effects and list rendering with stable ids.

Key parts:

case 'AddTodo':
  return {
    ...state,
    todos: [...state.todos, { id: state.nextId, text: state.input, done: false }],
    input: '', nextId: state.nextId + 1
  };

case 'SaveTodos':
  return [state, { type: 'storage', action: 'set', key: 'spriggan-todos', value: state.todos }];
  1. HTTP effect (async requests)
case 'FetchUsers':
  return [
    { ...state, loading: true },
    { type: 'http', url: '/api/users', onSuccess: 'UsersLoaded', onError: 'UsersFailed' }
  ];

case 'UsersLoaded':
  return { ...state, loading: false, users: msg.data };

See: examples/tea-walkthrough for an HTTP demo.

  1. Delay / notifications (debounce, timeouts)
case 'ShowToast':
  return [
    { ...state, toast: msg.text },
    { type: 'delay', ms: 3000, msg: { type: 'HideToast' } }
  ];
  1. DOM effects (focus, add/remove class)
return [state, { type: 'dom', action: 'focus', selector: '#name-input' }];

See dom effect tests in __tests__/spriggan-dom.test.js and examples/components.html.

  1. Subscriptions (external events)
subscriptions: (dispatch) => {
  const onKey = (e) => {
    if (e.key === 's' && (e.ctrlKey || e.metaKey)) {
      e.preventDefault();
      dispatch({ type: 'Save' });
    }
  };
  document.addEventListener('keydown', onKey);
  return () => document.removeEventListener('keydown', onKey);
}
  1. Components as functions
function Button({ text, msg }) {
  return html`<button data-msg=${msg}>${text}</button>`;
}

function view(state) {
  return html`<div>${Button({ text: 'Save', msg: { type: 'Save' } })}</div>`;
}
  1. List rendering with stable IDs
${items.map(item => html`<div id="item-${item.id}">${item.name}</div>`) }

This enables Idiomorph morphing to preserve focus/selection.


Core Concepts (short)

  • Model: the application state (plain JS objects)
  • Messages: plain objects describing events: {type: 'AddTodo'}
  • Update: pure function (state, msg) => newState | [newState, effect1, ...]
  • View: view(state, dispatch) => html (returns an HTML string or Node)
  • Effects: describe side effects (http, storage, dom, fn, delay) handled by effect handlers

For the full API, inspect src/spriggan.js — JSDoc comments document types and behavior.


Testing & Development

  • Install dev dependencies: npm install
  • Run tests: npx vitest or npm exec vitest (there is no test script in package.json)
  • Run checks/lint: npm run check (this repository includes a check script)

Unit tests for DOM behavior live in __tests__/spriggan-dom.test.js and exercise event delegation and built-in effects.


Contributing

  1. Fork the repo.
  2. Create a branch: git checkout -b feature/thing.
  3. Run linters and tests: npm install && npm run check && npx vitest.
  4. Open a PR describing the change.

If you plan to maintain a published package, consider adding a build step and CI that runs tests and publishes artifacts.


Roadmap (potential)

  • Optional build output and published package
  • TypeScript declaration files (.d.ts) for consumers
  • Official DevTools integration for time-travel debugging
  • Router and form utilities

License

Apache License 2.0 — see LICENSE