Welcome to VibeJS

Vibe is a small component based library for composing user interfaces and building apps or as a general purpose JQuery like library for getting work done.

Get the code for VibeJS from GitHub here: VibeJS

Not sure if Vibe is for you? Hit me up, maybe I can help you decide if Vibe is right for your project.

Contact me: vibejs


  • Small - currently under ~22KB minified (smaller if gzipped).
  • Create self contained components for composing larger components and apps.
  • Optional external access to the component.
  • Rendered components receive built-in methods (the Vibe).
  • Reactive {{template}} templating.
  • Two forms of syntax that can be combined - a familiar JQuery style syntax with built-in chainable DOM manipulation methods and composeable component form.
  • Pass in external functions or plugin functions to your rendered components, (Example: Mimic HanddlebarsJS )
  • Built-in Drag and Drop.
  • Ability to set up custom observers on rendered components.
  • Convert any element or HTML string to a Vibe'd element.
  • NEW:
  • Lots of goodies like delay, queue and pipe functions.
  • And more ...

Basic Usage

  • Basic usage for manually adding and using VibeJS to a web page. (see Bundle with Webpack below for alternate method of use with a bundler)

Add Vibe to your page before the closing body tag :

<script src='https://yoururl.com/vibe.min.js'></script>

A basic component function that doesn't do much would look like this:

  • These would go in a script tag or external.js/bundle.js file

const aComponent = () => {

    const template = `<div> {{message}} I am a component!</div>`;

    return {
    template: template,
    className: 'myComponent',

And to render the component to a page that contains an element with an id of 'app' would look like this:

const aRef = $vibe.render(aComponent, {
    to: '#app',
    className: 'renderedComponent',
    // to set default vdata.message from template pass in vdata obj. Skip vdata property to auto parse for template strings     
    vdata: {
    message: 'Hello Vibe!'


// Reactive!
// The vdata object and {{ message }} in the template let you update {{ message }} to new values (even HTML)  with:
// ( i.e. from "Hello Vibe!" to "I am Vibed!")
aRef.message("I am Vibed");

// OR use "set"

aRef.set.message = "I am Vibed";

A Component That Does a Little More

The component above works but doesn't do a whole lot. Let us make another component that does do something (a click event to log a message to the console). Look at the additions in the code and read the code comments:

Make the component with a function (again in a script tag or external.js/bundle.js):

const myComponent = () => {

    const template = `<div>Hey, I am app!</div>`; // Your component's HTML as string template, can pass in variables or {{templates}} too;

   // Just an example function (optional)

    const func = function say() {
        console.log('I am app')

    // init runs automatically if it exists

    const init = function init(e) {
    console.log('I am an '+e)

    // You can chain built-in e.$fns methods but since "e" is a reference no DOM querying takes place!

    e.$css('cursor: pointer;').$text('I am new text'); 

   // Another function but this time we will pass it in as an event handler

    const click = function click(e) {
        console.log('clicked ' + e.target.tagName ); // target may or may not be "this" if template has nested elements
        this.$fn.func(this); // In an Event "this" refers to the component and you can access $fn.func()

   // A state object (optional, pass in anything you want).
   // After making changes to state, state can be reverted to original saved in component's $origState

    const state = {x:1};

   // Render uses this return object to add these to the component

   return {
        template: template,
        className: 'myComponent',
        init: init,
        fn: {
            func: func
        events: {
            click: click,
        state: state

Render the component to a DIV with an id of "app" and save a reference to it as "myRef"

  • In an html file:

// somewhere in your html

<div id='app'> </div>

  • In a script tag after vibe.min.js:

// className, state, events, plugins (like fn of component) etc. can be added here too

const myRef = $vibe.render(myComponent, {
    to: '#app',
    position: 'append',
    className: 'renderedComponent',

  • You can render a component as many times as you want using different reference names.
  • Components can render other components too (hint: modules/import/export within components).

The Vibe

You might be wondering what the Vibe is. Components can be completely self contained however, after rendering a component it becomes vibed.

A Vibed component exposes all it's built-in methods. You can interact with the component (inside the component itself or externally) and call these built-in methods using the reference ("myRef" in this case) like:

// Call built-in Vibe functions to change the css and the text etc. (chainable).

myRef.$css('display: inline-block').$text('Hey hey!');

// Call the internal function you declared in the component


// Tack on more events with $on

myRef.$on('click', function(){ console.log('my Text is: '+this.$text()) });

Vibe Any Element

You can also Vibe any existing element. Here is how you do that!

  • Use normal JavaScript OR Vibe to select an existing div with a class name ".divname"

const aDiv = document.querySelectorAll('.divname')[0];

// OR select with Vibe (using select not only auto renders existing elements but also lets you use reactive {{ templates }} 

const aDiv = $vibe.select('.divname'); // by default selects first occurrence of .divname. Select all with $vibe.select('.divname', {all: true} );

// OR 

// If your existing elements has {{ message }} templates

// pass in default value for message - if not passing in vdata object then elements will be auto parsed.
const  vdata = {
    message: "Hello Vibe!"

// select it and add the vdata object 
const aDiv = $vibe.select('.divname', {vdata: vdata});

// Now when new data comes in (i.e. from fetch or Ajax) reactively change {{ message }} in aDiv with:

aDiv.message('New Message')

// OR use "set"

aDiv.set.message = "New Message";

// OR ...

// with a new data object of:

const newobj = {
message: "I am  a new data msg",

// Use $templater with newobj to update aDiv {{ message }}


  • Vibe it via render. (no need to vibe if $vibe.select was used)

 // No need to render if $vibe.select was used.

const aDivRef = $vibe.render(aDiv);

// {{ templates }} are not automated on existing elements unless select method was used.
// Use aDivref.$templater method later if needed or use select method. 

// Use it!
console.log('div existing text is ' + aDivRef.$text());
aDivRef.$text('I am new text.');

// if $vibe.select was used just do aDiv.$text('I am new text.');

  • * Note that when vibing existing elements, since there is no "component function", properties for className, state, events and plugin (if any) must be passed in via this render object.

Bundle With Webpack

The examples above show you how to manually add components via script tags. This section shows you the basics for using a bundler, namely Webpack.

In dist/index.html:

<!DOCTYPE html>
    <meta charset="utf-8" />
      <div id='app'></div>
    <script src="https://cdn.jsdelivr.net/gh/bretgeek/VibeJS@main/vibe.min.js"></script>
    <script src="main.js"></script>

In /src/App.js:

    export const App = () => {

    const template = '<div>I am app!</div>';
    const func = function say() {
        console.log('I am app!')

    const init = function(e) {
    console.log('I am e '+e)
         e.$css('cursor: pointer;');
    }; // can add extras on e too a init time

    const click = function click(e) {
        console.log('clicked ' + e.target.tagName );
        this.$text('I was clicked!')
    const state = {x:1};
    return {
        template: template,
        className: 'webpacked',
        init: init,
        fn: {
            func: func
        events: {
            click: click,
        state: state

In /src/index.js:

import {App} from '/src/App.js';

function tip() { console.log('tip'); return this; };// plugin functions must return "this".

const Appref = $vibe.render(App, {
    to: '#app',
    position: 'append',
    plugin: {tip: tip} ,

Bundle it to dist/main.js with:

npx webpack

  • Visit dist/index.html to test!

Components That Render Components

In the previous bundling section you can see how imports are vital for Webpack to work.

If not using Webpack you still may need exports and imports to load in functionality from other files.

Components that render other components work the same way. You must export and import the assets you want to use.

  • If App1 is in in js/App1.js and is prefixed with export like:

export const App1 = () => {

    const template = `I am an App1 component!`;

    return {
    template: template,
    className: 'App1',

  • App2 can import and render App1 from a method like init or any other method with:

    import {App1} from '/js/App1.js';

    const App2 = () => {

    const template = `App2 rendered an App1 component!`;

    const init = function init(e) {  // "e" here is $self and you can also pass in $self here.

    // Render App1 to App2
    const App1Ref = $vibe.render(App1, {
    to: e,
    position: 'append',

    // change App1's text to show its working
    App1Ref.$text('App1 component imported to App2');

    };// End init

    return {
    template: template,
    init: init,
    className: 'App2',

In the example above App2 imports App1 and renders it via App2's init method. The real power of this comes when rendering components to other components via Events!   Which means you can render new components via click, touch etc. add infinity. Todo list anyone?

More examples here soon...

More coming soon...but until then here is a current list of methods that are exposed by Vibe via Vibe's return object: (Not all are chainable but the syntax should be familiar to you if you have ever worked with JQuery)

// Use with $vibe.select() or el.$select() or el.$methodname() from a vibed element (notice the $ on the method of the vibed element).
//  Look at the code to see what these do or contact me for help!
  const obj = {
    fn: fn,
    id: id,
    uuid: uuidv4,
    clone: clone,
    ready: ready,
    get: get,
    post: post,
    css: css,
    left: left,
    isTouch: isTouch,
    rpx: rpx,
    addClass: addClass,
    removeClass: removeClass,
    children: children,
    parents: parents,
    before: before,
    insertBefore: insertBefore,
    insertAfter: insertAfter,
    after: after,
    append: append,
    prepend: prepend,
    select: select,
    attr: attr,
    removeAttr: removeAttr,
    appendTo: appendTo,
    prependTo: prependTo,
    createNode: createNode,
    filterString: filterString,
    dataset: dataset,
    data: data,
    detach: detach,
    render: render,
    run: run,
    plugin: {},
    doc: document,
    rect: rect,
    mountedTo: false,
    cs: cs,
    ctx: ctx,
    on: on,
    observe: observe,
    observers: {},
    unobserve: unobserve,
    getobservers: getobservers,
    off: removeEvent,
    trigger: trigger,
    html: html,
    text: text,
    pager: pager,
    getState: getState,
    setState: setState,
    isFunction: isFunction,
    isObject: isObject,
    isElement: isElement,
    isArray: isArray,
    isString: isString,
    isNumber: isNumber,
    isInt: isInt,
    getAtPt: getAtPt,
    isTouching: isTouching,
    drag: drag,
    swipe: swipe,
    load: load,
    scroll: scroll,
    show: show,
    hide: hide,
    delay: delay,
    queue: queue,
    fadeIn: fadeIn,
    fadeOut: fadeOut,
    q: [],
    runq: runq,
    isrun: false,
    w: w,
    pipe: pipe,
    stream: [],
    each: each,
    stk: [],