A modern reimagining of Backbone.js — same proven MVC patterns, no jQuery, no Underscore, ships as a native ES module.
- Zero hard dependencies (includes a minimal built-in utility layer)
- Native ES module — works in browsers and any bundler (Vite, Rollup, webpack 5+)
- Full TypeScript types included
- Familiar Backbone API — drop-in for most use cases
npm install ostovjsOr grab the file directly:
- ostov.js — development build
- ostov.min.js — production build
import { Model, Collection, View, Router, Events } from 'ostovjs';Or import the full namespace:
import Ostov from 'ostovjs';<script type="module">
import { Model, Collection } from './ostov.js';
</script><script src="ostov.js"></script>
<!-- Ostov is now available as a global variable -->Backbone had a great core idea:
- explicit state (models)
- event-driven updates
- separation of concerns
Ostov keeps that — but removes legacy baggage:
- ❌ no jQuery
- ❌ no Underscore
- ✅ ES modules
- ✅ ES classes
- ✅ TypeScript generics
import { Model } from 'ostovjs';
interface TodoAttrs {
title: string;
completed: boolean;
}
export class Todo extends Model<TodoAttrs> {
defaults() {
return {
title: '',
completed: false,
};
}
toggle() {
this.set('completed', !this.get('completed'));
}
}import { Collection } from 'ostovjs';
import { Todo } from './Todo';
export class TodoList extends Collection<Todo> {
model = Todo;
completed() {
return this.where({ completed: true });
}
}import { View } from 'ostovjs';
import { Todo } from './Todo';
export class TodoView extends View<Todo> {
events() {
return {
'click [data-action="toggle"]': 'onToggle',
};
}
initialize() {
this.listenTo(this.model, 'change', this.render);
}
render() {
this.el.innerHTML = `
<button data-action="toggle">Toggle</button>
<span>${this.model.get('title')}</span>
`;
return this;
}
onToggle() {
this.model.toggle();
}
}Ostov does not force a templating system — you can plug in anything.
Example with Handlebars:
import Handlebars from 'handlebars';
import { View } from 'ostovjs';
const template = Handlebars.compile(`
<div>
<h3>{{title}}</h3>
<button data-action="toggle">
{{#if completed}}Undo{{else}}Complete{{/if}}
</button>
</div>
`);
export class TodoView extends View {
initialize() {
this.listenTo(this.model, 'change', this.render);
}
render() {
this.el.innerHTML = template(this.model.toJSON());
return this;
}
}👉 You can use any templating engine:
- Handlebars
- Mustache
- JSX (custom)
- plain strings
Ostov still supports classic Backbone patterns:
import { Model, View } from 'ostovjs';
const Todo = Model.extend({
defaults: {
title: '',
completed: false,
},
toggle() {
this.set('completed', !this.get('completed'));
},
});
const TodoView = View.extend({
events: {
'click button': 'toggle',
},
initialize() {
this.listenTo(this.model, 'change', this.render);
},
render() {
this.el.innerHTML = this.model.get('title');
return this;
},
toggle() {
this.model.toggle();
},
});👉 This is useful if:
- you're migrating from Backbone
- you prefer prototype-style inheritance
| Style | Use |
|---|---|
| Classes + TS | ✅ recommended |
.extend(...) |
✅ supported |
| Templates | any (no lock-in) |
Ostov gives you primitives:
- Model
- Collection
- View
- Router
- Events
No magic. Just structure.
- small / medium apps
- dashboards
- internal tools
- apps where React feels like overkill
- heavy ecosystem requirements
- large teams needing strict conventions
If you like Backbone-style architecture with modern TypeScript —
drop a star ⭐
Less framework. More control.
TLDR extension for google chrome — Get a TLDR summary of any page using OpenAI. Ask follow-up questions in a dedicated tab.