JSFiddle - React, Tailwind, and code Playground

HTML

<!doctype html>
<html lang="en" data-framework="javascript">
	<head>
		<meta charset="utf-8">
		<title>To-Do Mark</title>
		<link rel="stylesheet" href="css/app.css">
	</head>
	<body>
		<section id="todoapp">
			<header id="header">
				<h1>Todo</h1>
				<input id="new-todo" placeholder="What needs to be done?" autofocus>
			</header>
			<section id="main">
				<ul id="todo-list"><input id="checkBox" type="checkbox">Completed</ul>
			</section>
			<footer id="footer">
				<span id="todo-count"></span>
				<ul id="filters">
					<li>
						<a href="#/" class="selected">All</a>
					</li>
					<li>
						<a href="#/active">Active</a>
					</li>
				</ul>
				<button id="clear-completed">Clear completed</button>
			</footer>
		</section>
		</footer>
		<script src="js/config.js"></script>
		<script src="js/helpers.js"></script>
		<script src="js/store.js"></script>
		<script src="js/model.js"></script>
		<script src="js/template.js"></script>
		<script src="js/view.js"></script>
		<script src="js/controller.js"></script>
		<script src="js/app.js"></script>
	</body>
</html>

CSS

html,
body {
  margin: 0;
  padding: 0;
}

button {
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  font-size: 100%;
  vertical-align: baseline;
  font-family: inherit;
  color: inherit;
  -webkit-appearance: none;
  -ms-appearance: none;
  -o-appearance: none;
  appearance: none;
}

body {
  font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
  line-height: 1.4em;
  color: #4d4d4d;
  width: 550px;
  margin: 0 auto;
  -webkit-font-smoothing: antialiased;
  -moz-font-smoothing: antialiased;
  -ms-font-smoothing: antialiased;
  -o-font-smoothing: antialiased;
  font-smoothing: antialiased;
}

button,
input[type="checkbox"] {
  outline: none;
}

#todoapp {
  background: #fff;
  background: rgba(255, 255, 255, 0.9);
  margin: 130px 0 40px 0;
  border: 1px solid #ccc;
  position: relative;
  border-top-left-radius: 2px;
  border-top-right-radius: 2px;
  box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.2),
        0 25px 50px 0 rgba(0, 0, 0, 0.15);
}

#todoapp input::-webkit-input-placeholder {
  font-style: italic;
}

#todoapp input::-moz-placeholder {
  font-style: italic;
  color: #a9a9a9;
}

#todoapp h1 {
  position: absolute;
  top: -120px;
  width: 100%;
  font-size: 70px;
  font-weight: bold;
  text-align: center;
  color: #b3b3b3;
  color: rgba(255, 255, 255, 0.3);
  text-shadow: -1px -1px rgba(0, 0, 0, 0.2);
  -webkit-text-rendering: optimizeLegibility;
  -moz-text-rendering: optimizeLegibility;
  -ms-text-rendering: optimizeLegibility;
  -o-text-rendering: optimizeLegibility;
  text-rendering: optimizeLegibility;
}

#header {
  padding-top: 15px;
  border-radius: inherit;
}

#header:before {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  height: 15px;
  z-index: 2;
  border-bottom: 1px solid #6c615c;
  background: #8d7d77;
  background: -webkit-gradient(linear, left top, left bottom, from(rgba(132, 110, 100, 0.8)),to(rgba(101, 84, 76, 0.8)));
  background: -webkit-linear-gradient(top, rgba(132, 110, 100, 0.8), rgba(101,...

JavaScript

/*global app, $on */
(function () {
	'use strict';

	/**
	 * Sets up a brand new Todo list.
	 *
	 * @param {string} name The name of your new to do list.
	 */
	function Todo(name) {
		this.storage = new app.Store(name);
		this.model = new app.Model(this.storage);
		this.template = new app.Template();
		this.view = new app.View(this.template);
		this.controller = new app.Controller(this.model, this.view);
	}

	var todo = new Todo('todos');

	function setView() {
		todo.controller.setView(document.location.hash);
	}
	$on(window, 'load', setView);
	$on(window, 'hashchange', setView);
})();

(function () {
  'use strict';

  // Underscore's Template Module
  // Courtesy of underscorejs.org
  var _ = (function (_) {
    _.defaults = function (object) {
      if (!object) {
        return object;
      }
      for (var argsIndex = 1, argsLength = arguments.length; argsIndex < argsLength; argsIndex++) {
        var iterable = arguments[argsIndex];
        if (iterable) {
          for (var key in iterable) {
            if (object[key] == null) {
              object[key] = iterable[key];
            }
          }
        }
      }
      return object;
    }

    // By default, Underscore uses ERB-style template delimiters, change the
    // following template settings to use alternative delimiters.
    _.templateSettings = {
      evaluate    : /<%([\s\S]+?)%>/g,
      interpolate : /<%=([\s\S]+?)%>/g,
      escape      : /<%-([\s\S]+?)%>/g
    };

    // When customizing `templateSettings`, if you don't want to define an
    // interpolation, evaluation or escaping regex, we need one that is
    // guaranteed not to match.
    var noMatch = /(.)^/;

    // Certain characters need to be escaped so that they can be put into a
    // string literal.
    var escapes = {
      "'":      "'",
      '\\':     '\\',
      '\r':     'r',
      '\n':     'n',
      '\t':     't',
      '\u2028': 'u2028',
      '\u2029': 'u2029'
    };

    var escaper =...