Nomplate
(pronounced, Gnome-plate)
Nomplate is a microscopic (< 6kb), insanely fast (<30ms to interaction) client and server side template engine and component system that makes it dead simple to create, compose, test and deploy visual components using Plain Old JavaScript wherever it runs.

What does it look like?
/src/key_presses.js
const dom = require('nomplate').dom;
const keysPressed = [];
function keyPresses() {
return dom.div((update) => {
function onKeyUp(event) {
console.log('onKeyUp with:', event.keyCode);
keysPressed.push(event.keyCode);
update();
}
dom.input({type: 'text', onkeyup: onKeyUp});
dom.ul({className: 'my-list'}, () => {
keysPressed.forEach((keyCode) => {
dom.li(keyCode);
});
});
})
}
module.exports = keyPresses;
Every HTML node name is available on the dom object as a method (e.g., div, span, li, ul, section, header, footer, etc.).
The method signature can accept attributes, text content or a handler that itself calls more methods on dom. These arguments are optional, starting on the left in order to make callers more succinct.
If nested handlers declare a parameter, they will be sent a method that, when called will schedule a re-render of the associated component and it's children.
dom.div({className: 'abcd'}, () => {
dom.div('Some Text Content');
dom.div({className: 'fake-attr'});
dom.div((update) => {
dom.span('Now: ' + Date.now());
setTimeout(update, 1000);
});
});
Configure your Express server:
const express = require('express');
const nomplateExpress = require('nomplate/express');
const app = express();
app.use('/static', express.static('dist'));
app.engine('.js', nomplateExpress);
app.set('view engine', 'js');
app.set('view options', {layout: 'main', pretty: process.env.NODE_ENV !== 'production'});
app.set('views', path.resolve(__dirname + '/views'));
app.get('/', (req, res) => {
res.render('app');
});
app.listen(8080, () => {
console.log('Listening on localhost:8080');
});
The /views/main.js layout:
const dom = require('nomplate').dom;
function main(options, renderView) {
return dom.html({lang: 'en'}, () => {
dom.head(() => {
dom.meta({charset: 'utf8'});
dom.title('Nomplate Test');
dom.link({rel: 'stylesheet', href: 'static/some-styles.css'});
dom.script({src: '/static/some-bundle.js', type: 'text/javascript'});
});
dom.body(() => {
renderView();
});
});
}
module.exports = main;
The /views/app.js template
const dom = require('nomplate').dom;
function app(options) {
return dom.section({id: 'my-app'});
}
module.exports = app;
Configure the client
const keyPresses = require('./src/key_presses');
const ready = require('nomplate').ready;
const renderElement = require('nomplate').renderElement;
const element = renderElement(keyPresses(), document);
ready(document, () => {
const parent = document.getElementById('my-app');
parent.appendChild(element);
});
TODO MVC?
Here's an early prototype of the famous TODOMVC application implemented as a fully client side Nomplate application.
Get a reference to a real DOM element
const dom = require('nomplate').dom;
function myView(options) {
function onHeaderRendered(elem) {
console.log('header elem:', elem);
elem.textContent = 'Hello World';
}
return dom.div({id: 'my-view'}, () => {
dom.h1({onRender: onHeaderRendered});
});
}
module.exports = myView;
Here are some highlights:
- 6kb minified and gzipped for the entire library AND application
- < 80ms time to fully rendered and interactive application
- Fully unit tested with tests that finish in around 100ms
- Components are composable and easily comprehensible
Contributing
The build system is only proven to work on Linux and OS X, though it may work on Windows if your path and Node are configured properly.
mkdir nomplate
cd nomplate
git clone https://github.com/lukebayes/nomplate.git .
source setup-env.sh
make dev-install
source setup-env.sh
make test
Watch files for changes and run tests on change:
make test-w
Lint all files:
make lint
Build a distributable library into "dist" folder:
make build
Remove all artifacts
make clean