diff --git a/Changelog.md b/Changelog.md
index d9bf1968a56ba03e30f692c2652fda807e6ed410..473067b36ab21dbb7db7e1f4272d639d3fbc733f 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -6,6 +6,7 @@
 * Display @ before mentions [#7324](https://github.com/diaspora/diaspora/pull/7324)
 * Simplify mentions in the publisher [#7302](https://github.com/diaspora/diaspora/pull/7302)
 * Remove chartbeat and mixpanel support [#7280](https://github.com/diaspora/diaspora/pull/7280)
+* Upgrade to jQuery 3 [#7303](https://github.com/diaspora/diaspora/pull/7303)
 
 ## Bug fixes
 
diff --git a/Gemfile b/Gemfile
index 84e2256a2fc5c60c6e55a3e4f07ff2f8bb2a986f..997615e350bd5bc2205ef9081525de9cc28ce0fd 100644
--- a/Gemfile
+++ b/Gemfile
@@ -86,13 +86,13 @@ gem "entypo-rails", "3.0.0"
 # JavaScript
 
 gem "handlebars_assets", "0.23.1"
-gem "jquery-rails",      "4.2.1"
+gem "jquery-rails",      "4.2.2"
 gem "jquery-ui-rails",   "5.0.5"
 gem "js-routes",         "1.3.3"
 gem "js_image_paths",    "0.1.0"
 
 source "https://rails-assets.org" do
-  gem "rails-assets-jquery",                              "2.2.4" # Should be kept in sync with jquery-rails
+  gem "rails-assets-jquery",                              "3.1.1" # Should be kept in sync with jquery-rails
 
   gem "rails-assets-highlightjs",                         "9.9.0"
   gem "rails-assets-markdown-it",                         "8.3.0"
diff --git a/Gemfile.lock b/Gemfile.lock
index 9b35f67914fdd65aa4c382bf8f978e907ee81693..17ef3130e55aa849699423e191be6956d6bbf1b8 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -324,7 +324,7 @@ GEM
       rake
     jasmine-core (2.5.2)
     jasmine-jquery-rails (2.0.3)
-    jquery-rails (4.2.1)
+    jquery-rails (4.2.2)
       rails-dom-testing (>= 1, < 3)
       railties (>= 4.2.0)
       thor (>= 0.14, < 2.0)
@@ -540,7 +540,7 @@ GEM
     rails-assets-jasmine (2.5.2)
     rails-assets-jasmine-ajax (3.3.1)
       rails-assets-jasmine (~> 2)
-    rails-assets-jquery (2.2.4)
+    rails-assets-jquery (3.1.1)
     rails-assets-jquery-colorbox (1.6.4)
       rails-assets-jquery (>= 1.3.2)
     rails-assets-jquery-fullscreen-plugin (0.5.0)
@@ -831,7 +831,7 @@ DEPENDENCIES
   i18n-inflector-rails (= 1.0.7)
   jasmine (= 2.5.2)
   jasmine-jquery-rails (= 2.0.3)
-  jquery-rails (= 4.2.1)
+  jquery-rails (= 4.2.2)
   jquery-ui-rails (= 5.0.5)
   js-routes (= 1.3.3)
   js_image_paths (= 0.1.0)
@@ -878,7 +878,7 @@ DEPENDENCIES
   rails-assets-fine-uploader (= 5.13.0)!
   rails-assets-highlightjs (= 9.9.0)!
   rails-assets-jasmine-ajax (= 3.3.1)!
-  rails-assets-jquery (= 2.2.4)!
+  rails-assets-jquery (= 3.1.1)!
   rails-assets-jquery-placeholder (= 2.3.1)!
   rails-assets-jquery-textchange (= 0.2.3)!
   rails-assets-markdown-it (= 8.3.0)!
@@ -928,4 +928,4 @@ DEPENDENCIES
   will_paginate (= 3.1.5)
 
 BUNDLED WITH
-   1.14.5
+   1.14.6
diff --git a/app/assets/javascripts/jasmine-load-all.js b/app/assets/javascripts/jasmine-load-all.js
index be83acdec81d26ab189a926544666065bd2cae20..b465abdadc974384948bbbf12eb1e463cdb1d669 100644
--- a/app/assets/javascripts/jasmine-load-all.js
+++ b/app/assets/javascripts/jasmine-load-all.js
@@ -1,4 +1,4 @@
-//= require jquery2
+//= require jquery3
 //= require handlebars.runtime
 //= require templates
 //= require main
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 3a89c597db50c0eb9744b07d260989ead75bf37c..b46b272034d75981ed71b8c28bc26d909e3b44b7 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -52,11 +52,13 @@ module ApplicationHelper
   def jquery_include_tag
     buf = []
     if AppConfig.privacy.jquery_cdn?
-      version = Jquery::Rails::JQUERY_2_VERSION
+      version = Jquery::Rails::JQUERY_3_VERSION
       buf << [javascript_include_tag("//code.jquery.com/jquery-#{version}.min.js")]
-      buf << [nonced_javascript_tag("!window.jQuery && document.write(unescape('#{j javascript_include_tag('jquery2')}'));")]
+      buf << [
+        nonced_javascript_tag("!window.jQuery && document.write(unescape('#{j javascript_include_tag('jquery3')}'));")
+      ]
     else
-      buf << [javascript_include_tag("jquery2")]
+      buf << [javascript_include_tag("jquery3")]
     end
     buf << [javascript_include_tag("jquery_ujs")]
     buf << [nonced_javascript_tag("jQuery.ajaxSetup({'cache': false});")]
diff --git a/config/application.rb b/config/application.rb
index 98bf0609fe936cc9e9a25efeb82e2a1823d9bceb..dd9ca5adfd4303890ebe894635e9a7709247f318 100644
--- a/config/application.rb
+++ b/config/application.rb
@@ -68,7 +68,7 @@ module Diaspora
     config.assets.precompile += %w(
       contact-list.js
       ie.js
-      jquery2.js
+      jquery3.js
       jquery_ujs.js
       main.js
       jsxc.js
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index 8a277d41a44db392ea454645d9c58e9f2ea3781f..1109c2a4c0d49ac5eef1cac9832c29ec892a05fa 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -54,7 +54,7 @@ describe ApplicationHelper, :type => :helper do
       end
 
       it 'includes jquery.js from asset pipeline' do
-        expect(helper.jquery_include_tag).to match(/jquery2\.js/)
+        expect(helper.jquery_include_tag).to match(/jquery3\.js/)
         expect(helper.jquery_include_tag).not_to match(/jquery\.com/)
       end
     end
diff --git a/spec/javascripts/app/app_spec.js b/spec/javascripts/app/app_spec.js
index 1ade3b556056c83689ba0ec7628f800c0a151292..01e49e5f3b160fe10949963fdd91a33e14f342d6 100644
--- a/spec/javascripts/app/app_spec.js
+++ b/spec/javascripts/app/app_spec.js
@@ -62,6 +62,10 @@ describe("app", function() {
   });
 
   describe("setupAjaxErrorRedirect", function() {
+    beforeEach(function() {
+      app.setupAjaxErrorRedirect();
+    });
+
     it("redirects to /users/sign_in on 401 ajax responses", function() {
       spyOn(app, "_changeLocation");
       $.ajax("/test");
@@ -115,7 +119,6 @@ describe("app", function() {
       beforeEach(function() {
         app.stream = {basePath: function() { return "/stream"; }};
         app.notificationsCollection = {fetch: $.noop};
-        spyOn(Backbone.history, "start");
         this.link = $("<a href='/backbone-link' rel='backbone'>");
         spec.content().append(this.link);
         app.setupBackboneLinks();
@@ -123,6 +126,7 @@ describe("app", function() {
 
       afterEach(function() {
         app.stream = undefined;
+        Backbone.history.stop();
       });
 
       it("calls Backbone.history.navigate", function() {