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 🙏

© 2025 – Pkg Stats / Ryan Hefner

bendis

v1.1.6

Published

Bendis is minimalistic framework for rapid development of vanilla JavaScript web components and applications.

Readme

Bendis micro framework

Bendis is minimalistic framework for rapid development of vanilla JavaScript web components.

If you prefer to work in a dependency free vanilla JavaScript environment while solely focusing on the task at hand not having to worry about boilerplating and building - Bendis is what you need.

Creating Bendis based application

  • create your project using NPM: npm init
  • install bendis: npm install bendis --save-dev
  • create bendis app: npx bendis --create-application Sol
  • run dev server: npx bendis

That is it. You can start working on your web components right away. Let's see in more detail what these commands do:

npm init

This is a regular npm command which creates and configures the package.json file for your new project. You can check out NPM docs for the details.

npm install bendis --save-dev

This is how bendis is installed. Since bendis is development tool, it is recommended that it is installed as developer dependency.

Bendis CLI

Bendis CLI is usually invoked via npx bendis but it can be also installed globaly. Below is the output of npx bendis --help

**********
* BENDIS *
**********
BENDIS micro JavaScript framework. Web components + deep proxy + pure HTML = standard simplicity
When called with no arguments, the command will build the application in the development mode, include source maps, run the app on the development server and re-build whenever there is a change in the source code.

--create-application NAME PREFIX           Creates a new application with name NAME and optional prefix PREFIX (short prefix for the web component tags)
--create-page PATH                         Creates a new page with path PATH starting with slash (i.e. /contact). The route, the controller and page web component are created.
--create-component NAME                    New web component is created with name NAME, a html tag will be <PREFIX-NAME/>, also a html template is created in src/html folder.
--build                                    This switch will build the application in production mode and save in the dist fiolder
--html-only                                Builds a single html file in the dist folder which contains the javascript inside the script tag
--download-fonts                           Also download all fonts from Google fonts during production build
--build-file FILE_PATH                     Build specific file or files (comma delimited), by default it builds the entire application.
--dest-path                                Used in conjunction with --build-file, specifies path for the output files, defaults to dist folder.
--translation-strings                      Extracts all text strings for translation and saves them into src/assets/strings.json

npx bendis --create-application Sol

This is how bendis app is created. You only need to run it once on an empty project. It will create all the files necessary to support easy web component development and single page web application development. The argument value ("Sol") is the name of your new app, there is also optional second argument value for the app prefix. This prefix will be used for all your web component tags and class names.

Below is sample output of this command:

☛ About to create application named "Sol" with prefix sol
☛ Created router class SolRouter with tag sol-route in /Users/oxd/Projects/sol/src/js/sol-route.js
☛ Created base class SolBase in /Users/oxd/Projects/sol/src/js/sol-base.js
☛ Created web component class SolApp with HTML tag: <sol-app></sol-app> in /Users/oxd/Projects/sol/src/js/sol-app.js and HTML template in /Users/oxd/Projects/sol/src/html/sol-app.html
☛ Creating /Users/oxd/Projects/sol/src/html/index.html
☛ Created web component class SolIndexPage with HTML tag: <sol-index-page></sol-index-page> in /Users/oxd/Projects/sol/src/js/sol-index-page.js and HTML template in /Users/oxd/Projects/sol/src/html/sol-index-page.html
☛ Added route / in /Users/oxd/Projects/sol/src/html/sol-app.html
☛ Created page controller IndexController in /Users/oxd/Projects/sol/src/js/controllers/index.js

It created:

  • the application web component <sol-app></sol-app>
  • a route for / uri with index page <sol-index-page></sol-index-page>
  • a controller class for / route IndexController with onRoute() and onRouteDestroy() methods
  • html templates for these web components in src/html directory

npx bendis

This is the command you will be using the most during development. It will build your app and deploy it in the development web server. It will also watch for the changes on your files and rebuild whenever you change something. Below is a sample output:

npx bendis
Watching files... 

Built in 27ms. Now reloading...
The Sol development server is running on http://localhost:3434 serving from /Users/oxd/Projects/sol/dist directory.

Building your app for production

To build the application as a single javascript file in an optimized form that works on wide range of browsers while compressed and obfuscated use the following command:

npx bendis --build

The dist/ folder will now contain your production build.

Bendis web components

Bendis contains the most basic tools for building your web components in pure JavaScript. To create a new web component <sol-my-component> run:

npx bendis --create-component MyComponent

The Bendis way or recommended structure of your web component is to split it into two files: the JavaScript file and the pure HTML file. Note the "pure" in pure HTML, it means that HTML should only contain standard HTML (and CSS) and nothing else. The JavaScript file will contain a web component in a form of JavaScript class that extends HTMLElement. Note that it actualy extends from Bendis class which in turn extends from HTMLElement.

Bendis class

This is where all the power of Bendis lies, it is a web component with a deep JavaScript Proxy which you can bind to DOM elements. This in effect greatly simplifies app development. Let's explain the basics.


<h2></h2>
<ul>
    <li><strong></strong></li>
</li>

// data
this.state = {
    foo: {
        bar: 'Foo Bar!'
    },
    baz:[{
        title: 'First'
    }, {
    title: 'Second'
    }]
}

// bindings
this.bind('foo.bar', 'h2')
this.bind('baz.*', 'li', Array)
this.bind('baz.*.title', 'strong')

The result would look something like this:

Foo Bar!

  • First
  • Second

The bind function has the following signature:

bind(OBJECT_PATH, CSS_SELECTOR, CALLBACK) // binding a property or object to DOM node with optional callback

Since the state is a deep Proxy, it is simple to change the data as doing this.state.foo.bar = "New Title!!" In a same manner, you can also mutate the array, for example to add another list item just: this.state.baz.push({title: "New Item!"}) and immediately the DOM is modified and new list item is added.

Binding the deep Proxy to the DOM by default uses innerHTML but often you need to do something custom, like binding an event to the DOM element or doing something else to the DOM node. You can do that with callback functions:


this.bind('foo.bar', 'h2', (ctx)=>{
    let {el, val} = ctx // callback context contains the bound DOM element, the ound value and much more
    el.innerHTML = val
})

Effect of the above binding is the same as previous one except here you have the callback exposed. The callback is triggered each time the proxy value is modified or removed.

In scenarios where array of objects are bound to the DOM, the elements closely follow the structure of the array so any removing splicing, deleting and other mutations of the array will be applied to the DOM elements. Adding events to proxied DOM elements would be difficult because of all the mutations, this is why the bind context has ustility addEventListener and removeEventListener functions that do all the work for you. For example, adding a click event to each title element in the array would look like this:


this.bind('baz.*.title', 'strong', (ctx)=>{
    ctx.addEventListener('click', ()=>{
        console.log(`${ctx.el.nodeName} clicked`)
    })
})

This will ensure that this click event will trigger no matter what you do with the proxied array.