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

@muze-labs/simplyflow

v0.10.2

Published

Reactive browser applications with signals, effects, data binding and an app layer.

Readme

SimplyFlow

SimplyFlow is an experimental browser library for building small reactive web applications with ordinary HTML and ordinary JavaScript data.

The intended beginner-facing API is:

import { app } from '@muze-labs/simplyflow'

const counter = app({
  container: document.getElementById('counter'),

  data: {
    count: 0
  },

  commands: {
    add1() {
      this.data.count++
    }
  }
})
<div id="counter">
  <button data-simply-command="add1">+</button>
  <span data-simply-field="count"></span>
</div>

For editable values, use data-simply-edit:

<input data-simply-edit="name">
<span data-simply-field="name"></span>

The page updates automatically whenever app.data changes. Use data-simply-edit on form fields when the user should be able to edit a value directly. Text inputs, textareas and selects edit string values; checkboxes edit booleans or toggle values in arrays; radio buttons edit the selected value.

Buttons inside list templates can pass the current item or one of its fields to a command:

<ul data-simply-list="todos">
  <template>
    <li>
      <button data-simply-command="removeTodo" data-simply-value=":value.id">Remove</button>
      <span data-simply-field="text"></span>
    </li>
  </template>
</ul>

Custom top-level options become app properties, so you can add services without extra ceremony:

const contacts = simply.app({
  data: { contacts: [] },
  api: metro.jsonApi('/api/'),
  actions: {
    async loadContacts() {
      this.data.contacts = await this.api.get('contacts.json')
    }
  }
})

If an unknown option looks like a typo of a built-in app option, SimplyFlow logs a warning, but still adds the option to the app.

Reusable element behavior can be attached with data-simply-behavior:

<div data-simply-behavior="tabs"></div>
const page = simply.app({
  data: {},
  behaviors: {
    tabs(element) {
      // Set up the tabs element.
    }
  }
})

HTML fragments can be included inside an app container without a build step:

<link rel="simply-include" href="header.html">

The include observer is scoped to the app and stops when app.destroy() is called.

Keyboard shortcuts can be added with the shortcuts option:

const notes = simply.app({
  data: {},
  shortcuts: {
    'Control+s'() {
      this.actions.save()
    }
  }
})

Install

npm install @muze-labs/simplyflow

or using Git:

git clone https://github.com/muze-labs/simplyflow.git

Browser bundle

<script src="https://cdn.jsdelivr.net/npm/@muze-labs/simplyflow/dist/simply.flow.js"></script>

Then use the beginner-facing simply.app() API:

const counter = simply.app({
  data: { count: 0 },
  commands: {
    add1() {
      this.data.count++
    }
  }
})

The tutorials focus on simply.app(), but the browser global also exposes the lower-level APIs directly for projects that use script tags and do not want a build step:

const data = simply.signal({ title: 'Hello' })
simply.bind({ root: data })

const table = simply.model({ data: [] })
table.addEffect(simply.model.sort({ property: 'title' }))

The browser bundle also intentionally provides global html and css template tags. They return strings, but many code editors recognize these tag names and provide syntax highlighting inside template literals:

const page = simply.app({
  templates: {
    card: html`<article data-simply-field=":value.title"></article>`
  },
  styles: {
    card: css`.selected { font-weight: bold; }`
  }
})

For no-build module examples that use an import map, prefer mapping the complete browser bundle instead of every split workspace package:

<script type="importmap">
{
  "imports": {
    "@muze-labs/simplyflow": "https://cdn.jsdelivr.net/npm/@muze-labs/simplyflow/dist/simply.flow.js",
    "@muze-nl/metro": "https://cdn.jsdelivr.net/npm/@muze-nl/[email protected]/src/everything.mjs"
  }
}
</script>
<script type="module">
import '@muze-labs/simplyflow'
import '@muze-nl/metro'

const hnpwa = simply.app({
  data: { items: [] }
})
</script>

This is the recommended beginner/example path: import the complete SimplyFlow bundle, plus any external library the example directly uses. Advanced users can still use the split packages or subpath imports below when they want smaller, tree-shakeable bundles with a build step.

Module imports are still available when you prefer explicit imports:

import { signal, effect, batch } from '@muze-labs/simplyflow/state'
import { bind } from '@muze-labs/simplyflow/bind'
import { model, paging, sort, filter, columns } from '@muze-labs/simplyflow/model'

const data = signal({ title: 'Hello' })
bind({ root: data })

Package structure and tree-shakeable imports

SimplyFlow is maintained as a small monorepo. The main @muze-labs/simplyflow package is a convenience package for beginners and script-tag users. The implementation is split into smaller ESM packages that can also be imported directly:

import { signal, effect } from '@muze-labs/simplyflow-state'
import { bind } from '@muze-labs/simplyflow-bind'
import { model } from '@muze-labs/simplyflow-model'
import { app } from '@muze-labs/simplyflow-app'

For projects that prefer one dependency, the main package keeps stable subpath exports:

import { signal, effect } from '@muze-labs/simplyflow/state'
import { bind } from '@muze-labs/simplyflow/bind'

The state, bind, model, and app packages are pure ESM and marked as side-effect-free so bundlers can tree-shake unused exports. The main @muze-labs/simplyflow entry point still intentionally initializes the browser global API and registers <simply-render>, so use subpath or direct package imports when minimum bundle size matters.

Documentation

Or check the examples for more information.

Development

This repository is a private npm workspace root. The published main package lives in packages/simplyflow; the smaller layer packages live in packages/state, packages/bind, packages/model, and packages/app.

npm install
npm test
npm run build

When publishing the split packages, publish the dependency packages first (state, then bind/model, then app, then simplyflow) so the main package can resolve its package dependencies.

License

MIT © Muze.nl

Contributions

Contributions are welcome, but make sure that all code is MIT licensed. If you want to send a merge request, please make sure that there is a ticket that shows the bug/feature and reference it. If you find any problem, please do file a ticket, but you should not expect a timely resolution. This project is still very experimental, don't use it in production unless you are ready to fix problems yourself.