Negligible Participation Metric


    2.1.0 • Public • Published

    Comfey 2

    Comfey is a tiny javascript state management library inspired by React hook useState.Comfey provides a simple data binding library to update your HTML using simple valid HTML data attributes.

    Read more in Comfey Wiki


    • 0 dependencies / Lightweight v1.0.0 is 35 lines of code
    • Looks like react hook useState
    • No loops, event driven
    • (Optional) Simple HTML5 data attributes to bind the html elements to the states
    • Finite State Machine as a plugin

    Table of content


    Using NPM

    npm install comfey

    Using Yarn

    yarn add comfey

    Initialize component

    Instantiate Comfey - optionally passing in a ViewUpdater.

    import Comfey from 'comfey';
    const myComponent = new Comfey();

    Initialize state

    Use .useState() method to initialize a state, useState() accepts 3 parameters. Returns getter and setter functions

     * @param {string} state name of the state
     * @param {any} initialVal initial value
     * @param {function} watcher watcher function that will be called everytime the value of the state changes
     * @returns {Array<[function, function]>} getterFunction and SetterFunction


    const [count, setCount] = app.useState('count', 3, countWatcher);


    Watch gets newValue, oldValue and name of the state and is invoked everytime the state changes.

    function countWatcher(newVal, oldVal, stateName) {
      // Do something when value of count state changes


    Comfey offers a DOM updater as a separate library. Which will let you use simple HTML data attributes to bind your state data to your DOM.

    Create a new Instance of ComfeyDom by

    import Comfey, { ComfeyDom } from 'comfey';
    const viewUpdater = new ComfeyDom(document.getElementById('app'), DEBUG);
    // Now pass in the viewUpdater (ComfeyDom instance) to Comfey's constructor
    const app = new Comfey(viewUpdater);

    Bind state value to an element

    Use data-bind attribute with stateName as its value to bind the innerHTML of the element to the state's value.


    • data-bind-visible
    • data-bind-hidden

    Bind visible and hidden accepts value to compare.



    means the element will be visible if the state numberStatus is set to medium value.


    • data-bind-class

    Bind class accepts value to compare, but will not interpolate the bound value as a classname.



    means the element will get active class if the state currentPage is set to home value.

    More bind-class DEMOs

    Bind attributes

    You can bind an attribute to a state's value w/ data-bind-attr. Data bind attributes can take values delimited by :: which will make each delimited string an argument. The argument pattern looks like



    data-bind-attr="count::style::font-size: $rem"

    means, a dynamic attribute will be added to the HTML element when the state count has a value, the attribute added will be style attribute and the value for the style attribute will be

    font-size: <StateValue>rem

    Multi Apps

    You can have any number of applications on a page. Instanciate a new Comfey whenever you need.

    • Multiple apps can use duplicate state names
    • they will be scoped within each app
    • You will have to scope your javascript as well
    • Just avoid declaring getters and setters globally


    import Comfey, { ComfeyDom } from 'comfey';
    // scoped code blocks can use same getters / setters, etc names if desired.
    // name uniquely if needs to be in the same scope
    (() => {
      const view = new ComfeyDom(document.getElementById('app1'), COMFEY_DEBUG);
      const app = new Comfey(view, COMFEY_DEBUG);
      const [, setActive] = app.useState('stateActive', false);
      setInterval(() => {
        setActive(Math.random() > 0.5);
      }, 1000);
    (() => {
      const view = new ComfeyDom(document.getElementById('app2'), COMFEY_DEBUG);
      const app = new Comfey(view, COMFEY_DEBUG);
      const [, setActive] = app.useState('stateActive', false);
      setInterval(() => {
        setActive(Math.random() > 0.5);
      }, 1000);

    More Multi App DEMOs


    Counter Example


    <div id="my-component">
        <span data-bind="count">
          <!--   This placeholder will be updated with value of count state -->
      <div>Show plus: <span data-bind="showPlus">x</span></div>
      <div>Hide minus: <span data-bind="hideMinus">x</span></div>
      <div class="buttons">
        <!--   Increment button will be visible if showPlus state is set to true   -->
        <button id="increment" data-bind-visible="showPlus">+</button>
        <button id="decrement" data-bind-hidden="hideMinus">-</button>
        <!-- Bind attribute, state :: attr :: value, $ for stateValue placeholder -->
        <button id="increment" data-bind-attr="disablePlus::disabled::">+</button>
            data-bind-attr="count::style::font-size: $rem"
          <span data-bind-visible="numberStatus::medium">Medium</span>
          <span data-bind-visible="numberStatus::max">Max</span>
          <span data-bind-visible="numberStatus::min">Min</span>
    import Comfey, { ComfeyDom } from 'comfey';
    const app = new Comfey(new ComfeyDom(document.getElementById('app')));
    // Select buttons
    const btnIncrement = document.getElementById('increment');
    const btnDecrement = document.getElementById('decrement');
    // Initialize states
    const [, setShowPlus] = app.useState('showPlus', true);
    const [, setHideMinus] = app.useState('hideMinus', false);
    const [count, setCount] = app.useState('count', 3, countWatcher);
    function countWatcher(newVal) {
      if (newVal > 4) {
      } else {
        if (newVal < 1) {
        } else {
    // Button behaviours
    btnIncrement.addEventListener('click', () => {
      setCount(count() + 1);
    btnDecrement.addEventListener('click', () => {
      setCount(count() - 1);

    Comfey - Pokemon buddy game


    Multi level navigation


    Change log


    • ViewUpdater abstracted, no more DOM manipulation code in main library.
    • Empty instantiation of Comfey will ignore view update (Headless Mode) as opposed to falling back to document
    • ComfeyDom introduced to support DOM manipulation, which can be optionally passed in to Comfey constructor. See examples above or in /demo/ directory.
    • Comfey is an ESM module


    npm i comfey

    DownloadsWeekly Downloads






    Unpacked Size

    28.5 kB

    Total Files


    Last publish


    • dejavu1987