JSFiddle - React, Tailwind, and code Playground

HTML

<!doctype html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>My todos</title>
    </head>
    <body>
        <form id="inputform">
            <input type="text" placeholder="Add a new todo..." />
        </form>

        <h1>my todos</h1>
        <div id="todos">
            <ul></ul>
        </div>

        <script type="text/html" id="template">
            <ul>
            {{#todos}}
                <li data-id="{{id}}">
                    <input type="checkbox" class="remove" />
                    {{text}}
                </li>
            {{/todos}}
            </ul>

            <p>{{size}} todos left</p>
        </script>

        <script src="http://cloud.github.com/downloads/wycats/handlebars.js/handlebars-1.0.rc.1.js"></script>

        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
        <script src="http://hay.github.com/stapes/stapes.min.js"></script>
        <script src="app.js"></script>
    </body>
</html>

JavaScript

var listTemplate = Handlebars.compile( $("#template").html() );

var TodosModel = Stapes.subclass({
    constructor : function() {
        var todos = JSON.parse( window.localStorage.todos );
        this.set( todos );
    },

    save : function() {
        window.localStorage.todos = JSON.stringify( this.getAll() );
    }
});

var InputView = Stapes.subclass({
    constructor : function( model ) {
        this.model = model;
        this.$el = $("#inputform");
        this.$input = this.$el.find("input");
        this.bindEventHandlers();
    },

    bindEventHandlers : function() {
        this.$el.on('submit', function(e) {
            e.preventDefault();

            this.model.push({
                "text" : this.$input.val()
            });

            this.$input.val('');
        }.bind(this));
    }
});

var ListView = Stapes.subclass({
    constructor : function( model ) {
        this.model = model;
        this.$el = $("#todos");
        this.template = listTemplate;
        this.bindEventHandlers();
    },

    bindEventHandlers : function() {
        this.$el.on('click', '.remove', function(e) {
            var id = $(e.target).parents("li").data('id');
            this.model.remove(id);
        }.bind(this));
    },

    render : function() {
        var html = this.template({
            size : this.model.size(),
            todos : this.model.getAllAsArray()
        });

        this.$el.html( html );
    }
});

var TodosController = Stapes.subclass({
    constructor : function() {
        this.model = new TodosModel();
        this.listView = new ListView( this.model )
        this.inputView = new InputView( this.model );

        this.model.on('change', function() {
            this.listView.render();
            this.model.save();
        }, this);

        this.listView.render();
    }
});

var controller = new TodosController();