SPA Routing Example

Written by Backbone Tutorials Team

Last updated: June 2026 · 9 min read

A real single page application does more than match URLs: it manages which view is on screen, cleans up the previous one, and renders the next into a shared layout. This example builds that small but complete structure with a router, a layout region, and two views that swap without reloading. It uses Backbone.js 1.6.0.

For the architecture behind it, see single page application architecture and client-side routing. The router basics are in the Backbone router example.

How the SPA routing example swaps viewsA route change tells a layout to dispose the current view and show a new one in the same container. route change layout dispose old view show new view

What this example builds

The result is a two-page application where navigating between routes replaces the active view inside a single content region, cleaning up the old view each time.

The behaviour you will see

Visiting #home or #list renders the matching view into one shared region. Before the new view appears, the previous one is removed so its event listeners do not pile up. This dispose step is what separates a real SPA from a demo that slowly leaks memory.

The layout region

A small layout object tracks the current view and knows how to swap it.

The region helper

var layout = {
  current: null,
  show: function (view) {
    if (this.current) { this.current.remove(); }
    this.current = view;
    $("#main").html(view.render().el);
  }
};

The page views

Each page is an ordinary Backbone view that renders some markup.

Two simple views

var HomeView = Backbone.View.extend({
  render: function () { this.$el.html("<h1>Home</h1>"); return this; }
});
var ListView = Backbone.View.extend({
  render: function () { this.$el.html("<h1>List</h1>"); return this; }
});

In a larger app these would bind to models, exactly as in the Backbone view example.

The router that swaps them

The router maps each route to a handler that hands a fresh view to the layout.

Routing to views

var Router = Backbone.Router.extend({
  routes: { "home": "home", "list": "list", "*default": "home" },
  home: function () { layout.show(new HomeView()); },
  list: function () { layout.show(new ListView()); }
});

new Router();
Backbone.history.start();

Disposing the old view

The single most important line is the one that removes the previous view before showing the next.

Why cleanup matters

Calling view.remove() detaches the element and, when the view used listenTo, stops its listeners. Without this, every navigation creates a new view whose listeners keep firing against models that are still around, which slowly degrades performance and causes duplicate updates. Disposing on each swap keeps memory flat no matter how long the user navigates, a concern explored in client-side architecture.

Common pitfalls

SPAs fail in predictable ways once they grow.

What usually goes wrong

The most common is never removing old views, the leak described above. The second is rendering each view into a new element rather than a single region, which leaves stale markup on the page. The third is starting Backbone.history more than once, which double-fires routes. Keeping one region, one history start, and a dispose on every swap avoids all three. The broader patterns are in SPA architecture.

Frequently Asked Questions

How does a single page application swap views?

A layout region tracks the current view and replaces it on each route change. The router hands a new view to the region, which removes the old one and renders the new one into the same container.

Why must I remove old views in a SPA?

Calling view.remove detaches the element and stops listeners bound with listenTo. Skipping it leaves listeners firing against live models, which leaks memory and causes duplicate updates as the user navigates.

Where should routing logic live in a SPA?

In the router. Each route maps to a handler that decides which view to show, while the views themselves stay focused on rendering. This keeps navigation separate from presentation.

Why do my routes fire twice?

You are probably calling Backbone.history.start more than once. Start it a single time after the router is created, and every route will dispatch exactly once.

Read next: the state management example, or back to the Examples hub.

Want the architecture behind it?

The SPA architecture guide covers routing, view lifecycle, and structure.

Read: SPA Architecture →