diff --git a/app/factory.py b/app/factory.py
index a3e2da70a261e6d1927ac5b8ac92be58fccd0666..dab36078edd83224fcbf8a29ed5f326f011009ab 100644
--- a/app/factory.py
+++ b/app/factory.py
@@ -17,6 +17,7 @@ from .extensions import (db, migrate, login_manager, ldap_manager, bootstrap,
                          admin, mail, jwt, toolbar, redis_store, fsession)
 from .admin.views import (AdminModelView, ItemAdmin, UserAdmin, GroupAdmin, TokenAdmin,
                           NetworkAdmin)
+from .main.views import bp as main
 from .inventory.views import bp as inventory
 from .networks.views import bp as networks
 from .users.views import bp as users
@@ -113,9 +114,10 @@ def create_app(config=None):
     admin.add_view(AdminModelView(models.Mac, db.session))
     admin.add_view(AdminModelView(models.Cname, db.session))
 
-    app.register_blueprint(inventory)
-    app.register_blueprint(networks)
-    app.register_blueprint(users)
+    app.register_blueprint(main)
+    app.register_blueprint(inventory, url_prefix='/inventory')
+    app.register_blueprint(networks, url_prefix='/networks')
+    app.register_blueprint(users, url_prefix='/users')
     app.register_blueprint(api, url_prefix='/api')
 
     app.wsgi_app = WhiteNoise(app.wsgi_app, root='static/')
diff --git a/app/inventory/views.py b/app/inventory/views.py
index 18f8b8b788780f6826342fce8804647579d087be..c87bb6997a640958686e198506dc1084d7eb5f13 100644
--- a/app/inventory/views.py
+++ b/app/inventory/views.py
@@ -21,24 +21,6 @@ from .. import utils, models
 bp = Blueprint('inventory', __name__)
 
 
-# Declare custom error handlers for all views
-@bp.app_errorhandler(404)
-def not_found_error(error):
-    return render_template('404.html'), 404
-
-
-@bp.app_errorhandler(500)
-def internal_error(error):
-    return render_template('500.html'), 500
-
-
-@bp.app_errorhandler(utils.CSEntryError)
-def handle_csentry_error(error):
-    response = jsonify(error.to_dict())
-    response.status_code = error.status_code
-    return response
-
-
 @bp.route('/_retrieve_items')
 @login_required
 def retrieve_items():
@@ -57,12 +39,6 @@ def retrieve_items():
     return jsonify(data=data)
 
 
-@bp.route('/')
-@login_required
-def index():
-    return render_template('index.html')
-
-
 @bp.route('/items')
 @login_required
 def list_items():
diff --git a/app/main/__init__.py b/app/main/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/app/main/views.py b/app/main/views.py
new file mode 100644
index 0000000000000000000000000000000000000000..7cdb4d60adb5049ed07b9be7947301e972f1fc4b
--- /dev/null
+++ b/app/main/views.py
@@ -0,0 +1,40 @@
+# -*- coding: utf-8 -*-
+"""
+app.main.views
+~~~~~~~~~~~~~~
+
+This module implements the main blueprint.
+
+:copyright: (c) 2017 European Spallation Source ERIC
+:license: BSD 2-Clause, see LICENSE for more details.
+
+"""
+from flask import Blueprint, render_template, jsonify
+from flask_login import login_required
+from .. import utils
+
+bp = Blueprint('main', __name__)
+
+
+# Declare custom error handlers for all views
+@bp.app_errorhandler(404)
+def not_found_error(error):
+    return render_template('404.html'), 404
+
+
+@bp.app_errorhandler(500)
+def internal_error(error):
+    return render_template('500.html'), 500
+
+
+@bp.app_errorhandler(utils.CSEntryError)
+def handle_csentry_error(error):
+    response = jsonify(error.to_dict())
+    response.status_code = error.status_code
+    return response
+
+
+@bp.route('/')
+@login_required
+def index():
+    return render_template('index.html')
diff --git a/app/static/js/attributes.js b/app/static/js/attributes.js
index 4d9be6e1590bf3db04fb43d814f20d6b7d8e365d..d2aadc073a1d6894c01b6a9cb0b08bff9211eeb9 100644
--- a/app/static/js/attributes.js
+++ b/app/static/js/attributes.js
@@ -4,7 +4,7 @@ $(document).ready(function() {
     "ajax": function(data, callback, settings) {
       var kind = $('li a.nav-link.active').text();
       $.getJSON(
-        $SCRIPT_ROOT + "/_retrieve_attributes_name/" + kind,
+        $SCRIPT_ROOT + "/inventory/_retrieve_attributes_name/" + kind,
         function(json) {
           callback(json);
         });
diff --git a/app/static/js/hosts.js b/app/static/js/hosts.js
index 38c7e994fa17adc41a2de729c78c42dbf2a63a40..8b455197e2de6691810e785f6a5c04d669cdf0b5 100644
--- a/app/static/js/hosts.js
+++ b/app/static/js/hosts.js
@@ -5,7 +5,7 @@ $(document).ready(function() {
     // and update the IP select field
     var network_id = $("#network_id").val();
     $.getJSON(
-      $SCRIPT_ROOT + "/_retrieve_available_ips/" + network_id,
+      $SCRIPT_ROOT + "/networks/_retrieve_available_ips/" + network_id,
       function(json) {
         var $ip = $("#ip");
         $ip.empty();
@@ -27,7 +27,7 @@ $(document).ready(function() {
   var hosts_table =  $("#hosts_table").DataTable({
     "ajax": function(data, callback, settings) {
       $.getJSON(
-        $SCRIPT_ROOT + "/_retrieve_hosts",
+        $SCRIPT_ROOT + "/networks/_retrieve_hosts",
         function(json) {
           callback(json);
         });
diff --git a/app/static/js/items.js b/app/static/js/items.js
index 6c29a673cd2b0e89d855eb181e513aa3054c7600..396f411cb53b4000db220f4700823d09ddd0a91a 100644
--- a/app/static/js/items.js
+++ b/app/static/js/items.js
@@ -8,7 +8,7 @@ $(document).ready(function() {
   var items_table =  $("#items_table").DataTable({
     "ajax": function(data, callback, settings) {
       $.getJSON(
-        $SCRIPT_ROOT + "/_retrieve_items",
+        $SCRIPT_ROOT + "/inventory/_retrieve_items",
         function(json) {
           callback(json);
         });
@@ -30,7 +30,7 @@ $(document).ready(function() {
           if ( data === null ) {
             return data;
           }
-          var url = $SCRIPT_ROOT + "/items/view/" + data;
+          var url = $SCRIPT_ROOT + "/inventory/items/view/" + data;
           return '<a href="'+ url + '">' + data + '</a>';
         }
       }
diff --git a/app/templates/admin/index.html b/app/templates/admin/index.html
index 03782d66c056dd3512e16ab7f1ec916fb290152f..996ac4028d56e285468aabe48fe91b15772ff991 100644
--- a/app/templates/admin/index.html
+++ b/app/templates/admin/index.html
@@ -6,5 +6,5 @@
 <h2>Use the admin interface with care</h2>
 
 <!-- flask-admin uses bootstrap 3 -->
-<a class="btn btn-primary" href="{{ url_for('inventory.index') }}">CSEntry</a>
+<a class="btn btn-primary" href="{{ url_for('main.index') }}">CSEntry</a>
 {% endblock %}
diff --git a/app/templates/base.html b/app/templates/base.html
index 038fc7ba44984cd2d3389b0bbdc384fe738bb7b1..0f8c49115632288a3d333432689399b1f8671b8d 100644
--- a/app/templates/base.html
+++ b/app/templates/base.html
@@ -14,7 +14,7 @@
 {% block navbar %}
   <!-- Fixed navbar -->
   <div class="navbar fixed-top navbar-expand-lg navbar-light bg-light" role="navigation">
-      <a class="navbar-brand" href="{{ url_for('inventory.index') }}">CSEntry</a>
+      <a class="navbar-brand" href="{{ url_for('main.index') }}">CSEntry</a>
       <button class="navbar-toggler" type="button" data-toggle="collapse"
               data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
               aria-expanded="false" aria-label="Toggle navigation">
@@ -24,17 +24,17 @@
       <div class="collapse navbar-collapse" id="navbarSupportedContent">
         <div class="navbar-nav mr-auto">
           {% set path = request.path %}
-          <a class="nav-item nav-link {{ is_active(path.startswith("/items")) }}" href="{{ url_for('inventory.list_items') }}">Items</a>
-          <a class="nav-item nav-link {{ is_active(path.startswith("/hosts")) }}" href="{{ url_for('networks.list_hosts') }}">Hosts</a>
-          <a class="nav-item nav-link {{ is_active(path.startswith("/attributes")) }}" href="{{ url_for('inventory.attributes', kind='Manufacturer') }}">Attributes</a>
-          <a class="nav-item nav-link {{ is_active(path.startswith("/qrcodes")) }}" href="{{ url_for('inventory.qrcodes', kind='Action') }}">QR Codes</a>
+          <a class="nav-item nav-link {{ is_active(path.startswith("/inventory/items")) }}" href="{{ url_for('inventory.list_items') }}">Items</a>
+          <a class="nav-item nav-link {{ is_active(path.startswith("/networks/hosts")) }}" href="{{ url_for('networks.list_hosts') }}">Hosts</a>
+          <a class="nav-item nav-link {{ is_active(path.startswith("/inventory/attributes")) }}" href="{{ url_for('inventory.attributes', kind='Manufacturer') }}">Attributes</a>
+          <a class="nav-item nav-link {{ is_active(path.startswith("/inventory/qrcodes")) }}" href="{{ url_for('inventory.qrcodes', kind='Action') }}">QR Codes</a>
           {% if current_user.is_authenticated and current_user.is_admin %}
             <a class="nav-item nav-link" href="{{ url_for('admin.index') }}">Admin</a>
           {% endif %}
         </div>
         <div class="navbar-nav">
           {% if current_user.is_authenticated %}
-          <div class="dropdown {{ is_active(path == "/profile") }}">
+          <div class="dropdown {{ is_active(path == "/users/profile") }}">
             <a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
               {{current_user}}
             </a>
diff --git a/app/templates/users/profile.html b/app/templates/users/profile.html
index ad6e279199d841619e43723a2af99b116b9b3081..58f2ac6df93e03184cf9f38d8277aa7010d9f97c 100644
--- a/app/templates/users/profile.html
+++ b/app/templates/users/profile.html
@@ -47,7 +47,7 @@
       {% for token in user.tokens %}
       <tr>
         <td>
-          <form method="POST" action="/tokens/revoke">
+          <form method="POST" action="/users/tokens/revoke">
             <input id="token_id" name="token_id" type="hidden" value="{{ token.id }}">
             <input id="jti" name="jti" type="hidden" value="{{ token.jti }}">
             <button type="submit" class="btn btn-danger">