BoltJS: pure JavaScript, components, and zero compilation
When I started in web development, there was no division into frontend/backend/fullstack developers.
There was simply the web developer - one person doing everything. We built both frontend and backend, most often with PHP and jQuery, and it just worked.
Later came frontend frameworks introducing components, like React.
Then TypeScript entered the scene. And that’s when things started to get complicated. Too complicated.
Why BoltJS?
I had two options:
bend myself to the tools that slow down the path from idea to working code,
or build my own solution.
I chose the second.
The goal of BoltJS was to get closer to the ideal: from idea to result in the shortest possible time.
The better the tool, the simpler and more intuitive the interface should be.
BoltJS principles
Zero compilation - pure JS, ready right away
Single source - just plug it in from jsDelivr
Components - encapsulated, reusable functions
SSR + CSR - full support for hybrid rendering
Events - communication via an event subscription system
DOM manipulation - directly (querySelector) or through an abstraction layer
Two-way binding - works with input, checkbox, textarea, select
Loaders, conditions, classes - built-in mechanisms in the framework
Completeness - aiming for a self-contained ecosystem without extra libraries
Example - TODO list
Live demo
<x-todo-form>
<input type="text" placeholder="Your todo" x-enter-pressed="add" value="{{todo}}"/>
<button x-click="add">Add</button>
</x-todo-form>
<x-todo-list>
<div>Tasks todo: {{left}} of {{count}}</div>
<div x-list="items"></div>
</x-todo-list>
<script type="text/javascript">
function TodoForm(self) {
self.todo = "";
self.add = () => {
if (!self.todo) {
alert("TODO can not be empty.");
return;
}
self.emit("new-todo", self.todo);
self.todo = "";
}
}
function TodoList(self) {
self.items = new WatchList([$(TodoItem, "My first TODO")]);
self.left = 1;
self.count = 1;
self.countTasks = () => {
self.left = self.items.count(x => x.done == false);
self.count = self.items.count();
}
self.on('new-todo', todo => {
let item = $(TodoItem, todo);
self.items.add(item)
self.countTasks()
});
self.on('del-todo', todo => {
self.items.delete(x => x == todo)
self.countTasks()
});
self.on('task-changed', self.countTasks);
}
function TodoItem(self, name) {
self.name = name;
self.done = false;
self.delete = () => self.emit('del-todo', self);
self.changed = () => {
self.done = !self.done;
self.emit('task-changed');
}
self.template =
`<div class="todo-item">
<input type="checkbox" x-change="changed" />
<div x-class="done:done">{{name}}</div>
<div x-click="delete" class="del">delete</div>
</div>`;
}
$([TodoForm, TodoList, TodoItem]);
</script>
The whole thing fits in just a handful of lines - with events, binding, and rendering.
No build steps. No configuration. No extra libraries.
Result
I worked on this code after hours. In the end, I managed to keep it under 20KB.
GitHub repository
Documentation with examples
BoltJS on jsDelivr
Join me
BoltJS is just the beginning.
I’m building it to get closer to the ideal: from thought to working code in the shortest possible time.
If this goal resonates with you - check out the repo, play with the code, and share your thoughts.
Your feedback, issues, or pull requests would mean a lot to me.