{accountIds.map(id =>
diff --git a/app/javascript/mastodon/features/getting_started/index.js b/app/javascript/mastodon/features/getting_started/index.js
index f30dea446..a4549e609 100644
--- a/app/javascript/mastodon/features/getting_started/index.js
+++ b/app/javascript/mastodon/features/getting_started/index.js
@@ -2,7 +2,7 @@ import React from 'react';
 import Column from '../ui/components/column';
 import ColumnLink from '../ui/components/column_link';
 import ColumnSubheading from '../ui/components/column_subheading';
-import Link from 'react-router/lib/Link';
+import Link from 'react-router-dom/Link';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 import { connect } from 'react-redux';
 import PropTypes from 'prop-types';
diff --git a/app/javascript/mastodon/features/home_timeline/index.js b/app/javascript/mastodon/features/home_timeline/index.js
index 6d3968751..ddebf2379 100644
--- a/app/javascript/mastodon/features/home_timeline/index.js
+++ b/app/javascript/mastodon/features/home_timeline/index.js
@@ -8,7 +8,7 @@ import ColumnHeader from '../../components/column_header';
 import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
 import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 import ColumnSettingsContainer from './containers/column_settings_container';
-import Link from 'react-router/lib/Link';
+import Link from 'react-router-dom/Link';
 
 const messages = defineMessages({
   title: { id: 'column.home', defaultMessage: 'Home' },
diff --git a/app/javascript/mastodon/features/report/index.js b/app/javascript/mastodon/features/report/index.js
index 217802b5c..23aba39de 100644
--- a/app/javascript/mastodon/features/report/index.js
+++ b/app/javascript/mastodon/features/report/index.js
@@ -52,7 +52,7 @@ class Report extends React.PureComponent {
 
   componentWillMount () {
     if (!this.props.account) {
-      this.context.router.replace('/');
+      this.context.router.history.replace('/');
     }
   }
 
@@ -76,7 +76,7 @@ class Report extends React.PureComponent {
 
   handleSubmit = () => {
     this.props.dispatch(submitReport());
-    this.context.router.replace('/');
+    this.context.router.history.replace('/');
   }
 
   render () {
diff --git a/app/javascript/mastodon/features/status/components/action_bar.js b/app/javascript/mastodon/features/status/components/action_bar.js
index 16ea83e40..21c2fd682 100644
--- a/app/javascript/mastodon/features/status/components/action_bar.js
+++ b/app/javascript/mastodon/features/status/components/action_bar.js
@@ -50,12 +50,12 @@ class ActionBar extends React.PureComponent {
   }
 
   handleMentionClick = () => {
-    this.props.onMention(this.props.status.get('account'), this.context.router);
+    this.props.onMention(this.props.status.get('account'), this.context.router.history);
   }
 
   handleReport = () => {
     this.props.onReport(this.props.status);
-    this.context.router.push('/report');
+    this.context.router.history.push('/report');
   }
 
   render () {
diff --git a/app/javascript/mastodon/features/status/components/detailed_status.js b/app/javascript/mastodon/features/status/components/detailed_status.js
index 6bbb8ca33..a77c4f0bb 100644
--- a/app/javascript/mastodon/features/status/components/detailed_status.js
+++ b/app/javascript/mastodon/features/status/components/detailed_status.js
@@ -7,7 +7,7 @@ import StatusContent from '../../../components/status_content';
 import MediaGallery from '../../../components/media_gallery';
 import VideoPlayer from '../../../components/video_player';
 import AttachmentList from '../../../components/attachment_list';
-import Link from 'react-router/lib/Link';
+import Link from 'react-router-dom/Link';
 import { FormattedDate, FormattedNumber } from 'react-intl';
 import CardContainer from '../containers/card_container';
 import ImmutablePureComponent from 'react-immutable-pure-component';
@@ -28,7 +28,7 @@ class DetailedStatus extends ImmutablePureComponent {
   handleAccountClick = (e) => {
     if (e.button === 0) {
       e.preventDefault();
-      this.context.router.push(`/accounts/${this.props.status.getIn(['account', 'id'])}`);
+      this.context.router.history.push(`/accounts/${this.props.status.getIn(['account', 'id'])}`);
     }
 
     e.stopPropagation();
diff --git a/app/javascript/mastodon/features/status/index.js b/app/javascript/mastodon/features/status/index.js
index f8a87ccb1..19cee2435 100644
--- a/app/javascript/mastodon/features/status/index.js
+++ b/app/javascript/mastodon/features/status/index.js
@@ -93,7 +93,7 @@ class Status extends ImmutablePureComponent {
   }
 
   handleReplyClick = (status) => {
-    this.props.dispatch(replyCompose(status, this.context.router));
+    this.props.dispatch(replyCompose(status, this.context.router.history));
   }
 
   handleModalReblog = (status) => {
diff --git a/app/javascript/mastodon/features/ui/components/boost_modal.js b/app/javascript/mastodon/features/ui/components/boost_modal.js
index 9d99b5336..da2be5264 100644
--- a/app/javascript/mastodon/features/ui/components/boost_modal.js
+++ b/app/javascript/mastodon/features/ui/components/boost_modal.js
@@ -40,7 +40,7 @@ class BoostModal extends ImmutablePureComponent {
     if (e.button === 0) {
       e.preventDefault();
       this.props.onClose();
-      this.context.router.push(`/accounts/${this.props.status.getIn(['account', 'id'])}`);
+      this.context.router.history.push(`/accounts/${this.props.status.getIn(['account', 'id'])}`);
     }
   }
 
diff --git a/app/javascript/mastodon/features/ui/components/column_link.js b/app/javascript/mastodon/features/ui/components/column_link.js
index 24387af57..cbdb6534f 100644
--- a/app/javascript/mastodon/features/ui/components/column_link.js
+++ b/app/javascript/mastodon/features/ui/components/column_link.js
@@ -1,6 +1,6 @@
 import React from 'react';
 import PropTypes from 'prop-types';
-import Link from 'react-router/lib/Link';
+import Link from 'react-router-dom/Link';
 
 const ColumnLink = ({ icon, text, to, href, method, hideOnMobile }) => {
   if (href) {
diff --git a/app/javascript/mastodon/features/ui/components/tabs_bar.js b/app/javascript/mastodon/features/ui/components/tabs_bar.js
index b108e8244..265cb818b 100644
--- a/app/javascript/mastodon/features/ui/components/tabs_bar.js
+++ b/app/javascript/mastodon/features/ui/components/tabs_bar.js
@@ -1,5 +1,5 @@
 import React from 'react';
-import Link from 'react-router/lib/Link';
+import NavLink from 'react-router-dom/NavLink';
 import { FormattedMessage } from 'react-intl';
 
 class TabsBar extends React.Component {
@@ -7,14 +7,14 @@ class TabsBar extends React.Component {
   render () {
     return (
       
-        
-        
-        
+        
+        
+        
 
-        
-        
+        
+        
 
-        
+        
       
     );
   }
diff --git a/app/javascript/mastodon/features/ui/index.js b/app/javascript/mastodon/features/ui/index.js
index 9f31b5443..39600607f 100644
--- a/app/javascript/mastodon/features/ui/index.js
+++ b/app/javascript/mastodon/features/ui/index.js
@@ -1,4 +1,7 @@
 import React from 'react';
+import Switch from 'react-router-dom/Switch';
+import Route from 'react-router-dom/Route';
+import Redirect from 'react-router-dom/Redirect';
 import NotificationsContainer from './containers/notifications_container';
 import PropTypes from 'prop-types';
 import LoadingBarContainer from './containers/loading_bar_container';
@@ -13,6 +16,67 @@ import { refreshNotifications } from '../../actions/notifications';
 import UploadArea from './components/upload_area';
 import ColumnsAreaContainer from './containers/columns_area_container';
 
+import Status from '../../features/status';
+import GettingStarted from '../../features/getting_started';
+import PublicTimeline from '../../features/public_timeline';
+import CommunityTimeline from '../../features/community_timeline';
+import AccountTimeline from '../../features/account_timeline';
+import AccountGallery from '../../features/account_gallery';
+import HomeTimeline from '../../features/home_timeline';
+import Compose from '../../features/compose';
+import Followers from '../../features/followers';
+import Following from '../../features/following';
+import Reblogs from '../../features/reblogs';
+import Favourites from '../../features/favourites';
+import HashtagTimeline from '../../features/hashtag_timeline';
+import Notifications from '../../features/notifications';
+import FollowRequests from '../../features/follow_requests';
+import GenericNotFound from '../../features/generic_not_found';
+import FavouritedStatuses from '../../features/favourited_statuses';
+import Blocks from '../../features/blocks';
+import Mutes from '../../features/mutes';
+import Report from '../../features/report';
+
+// Small wrapper to pass multiColumn to the route components
+const WrappedSwitch = ({ multiColumn, children }) => (
+  
+    {React.Children.map(children, child => React.cloneElement(child, { multiColumn }))}
+  
+);
+
+WrappedSwitch.propTypes = {
+  multiColumn: PropTypes.bool,
+  children: PropTypes.node,
+};
+
+// Small Wraper to extract the params from the route and pass
+// them to the rendered component, together with the content to
+// be rendered inside (the children)
+class WrappedRoute extends React.Component {
+
+  static propTypes = {
+    component: PropTypes.func.isRequired,
+    content: PropTypes.node,
+    multiColumn: PropTypes.bool,
+  }
+
+  renderComponent = ({ match: { params } }) => {
+    const { component: Component, content, multiColumn } = this.props;
+
+    return 
{content};
+  }
+
+  render () {
+    const { component: Component, content, ...rest } = this.props;
+
+    return 
;
+  }
+
+}
+
+const noOp = () => false;
+
+
 class UI extends React.PureComponent {
 
   static propTypes = {
@@ -119,7 +183,36 @@ class UI extends React.PureComponent {
     return (
       
         
-        {children}
+        
+          
+            
+            
+            
+            
+            
+            
+
+            
+            
+
+            
+            
+            
+            
+
+            
+            
+            
+            
+
+            
+            
+            
+            
+
+            
+          
+        
         
         
         
diff --git a/package.json b/package.json
index 0abea3235..e6fc02bbb 100644
--- a/package.json
+++ b/package.json
@@ -52,7 +52,6 @@
     "file-loader": "^0.11.2",
     "font-awesome": "^4.7.0",
     "glob": "^7.1.1",
-    "history": "^3.3.0",
     "http-link-header": "^0.8.0",
     "immutable": "^3.8.1",
     "intersection-observer": "^0.3.0",
@@ -86,8 +85,8 @@
     "react-notification": "^6.7.0",
     "react-redux": "^5.0.4",
     "react-redux-loading-bar": "^2.9.2",
-    "react-router": "^3.0.5",
-    "react-router-scroll": "^0.4.2",
+    "react-router-dom": "^4.1.1",
+    "react-router-scroll": "ytase/react-router-scroll#build",
     "react-simple-dropdown": "^3.0.0",
     "react-textarea-autosize": "^5.0.6",
     "react-toggle": "^4.0.1",
diff --git a/yarn.lock b/yarn.lock
index 5532efa6b..26c6f7c7a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1906,7 +1906,7 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
     safe-buffer "^5.0.1"
     sha.js "^2.4.8"
 
-create-react-class@^15.5.1, create-react-class@^15.5.2, create-react-class@^15.5.3:
+create-react-class@^15.5.2, create-react-class@^15.5.3:
   version "15.5.3"
   resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.5.3.tgz#fb0f7cae79339e9a179e194ef466efa3923820fe"
   dependencies:
@@ -3244,13 +3244,14 @@ hawk@~3.1.3:
     hoek "2.x.x"
     sntp "1.x.x"
 
-history@^3.0.0, history@^3.3.0:
-  version "3.3.0"
-  resolved "https://registry.yarnpkg.com/history/-/history-3.3.0.tgz#fcedcce8f12975371545d735461033579a6dae9c"
+history@^4.5.1, history@^4.6.0:
+  version "4.6.1"
+  resolved "https://registry.yarnpkg.com/history/-/history-4.6.1.tgz#911cf8eb65728555a94f2b12780a0c531a14d2fd"
   dependencies:
     invariant "^2.2.1"
     loose-envify "^1.2.0"
-    query-string "^4.2.2"
+    resolve-pathname "^2.0.0"
+    value-equal "^0.2.0"
     warning "^3.0.0"
 
 hmac-drbg@^1.0.0:
@@ -4806,7 +4807,7 @@ path-to-regexp@0.1.7:
   version "0.1.7"
   resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
 
-path-to-regexp@^1.7.0:
+path-to-regexp@^1.5.3, path-to-regexp@^1.7.0:
   version "1.7.0"
   resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.7.0.tgz#59fde0f435badacba103a84e9d3bc64e96b9937d"
   dependencies:
@@ -5511,7 +5512,7 @@ qs@6.4.0, qs@^6.4.0, qs@~6.4.0:
   version "6.4.0"
   resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
 
-query-string@^4.1.0, query-string@^4.2.2:
+query-string@^4.1.0:
   version "4.3.4"
   resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb"
   dependencies:
@@ -5711,24 +5712,32 @@ react-redux@^5.0.4:
     loose-envify "^1.1.0"
     prop-types "^15.5.10"
 
-react-router-scroll@^0.4.2:
-  version "0.4.2"
-  resolved "https://registry.yarnpkg.com/react-router-scroll/-/react-router-scroll-0.4.2.tgz#4b90e8707edf96eba7f066d94c5b4338bd6848b7"
+react-router-dom@^4.1.1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.1.1.tgz#3021ade1f2c160af97cf94e25594c5f294583025"
   dependencies:
-    prop-types "^15.5.6"
-    scroll-behavior "^0.9.3"
+    history "^4.5.1"
+    loose-envify "^1.3.1"
+    prop-types "^15.5.4"
+    react-router "^4.1.1"
+
+react-router-scroll@ytase/react-router-scroll#build:
+  version "0.4.1"
+  resolved "https://codeload.github.com/ytase/react-router-scroll/tar.gz/991ecddb08885e1fb80ec1e9dbf3a35844b7d4cd"
+  dependencies:
+    scroll-behavior "^0.9.1"
     warning "^3.0.0"
 
-react-router@^3.0.5:
-  version "3.0.5"
-  resolved "https://registry.yarnpkg.com/react-router/-/react-router-3.0.5.tgz#c3b7873758045a8bbc9562aef4ff4bc8cce7c136"
+react-router@^4.1.1:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/react-router/-/react-router-4.1.1.tgz#d448f3b7c1b429a6fbb03395099949c606b1fe95"
   dependencies:
-    create-react-class "^15.5.1"
-    history "^3.0.0"
+    history "^4.6.0"
     hoist-non-react-statics "^1.2.0"
-    invariant "^2.2.1"
-    loose-envify "^1.2.0"
-    prop-types "^15.5.6"
+    invariant "^2.2.2"
+    loose-envify "^1.3.1"
+    path-to-regexp "^1.5.3"
+    prop-types "^15.5.4"
     warning "^3.0.0"
 
 react-simple-di@^1.2.0:
@@ -6085,9 +6094,13 @@ resolve-from@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226"
 
+resolve-pathname@^2.0.0:
+  version "2.1.0"
+  resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-2.1.0.tgz#e8358801b86b83b17560d4e3c382d7aef2100944"
+
 resolve-url-loader@^2.0.2:
-  version "2.0.2"
-  resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-2.0.2.tgz#c465e97ea0a4791f3961f766cea775ff2e3ceb8c"
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-2.0.3.tgz#f54cd1b040e8f0ab72b2cb32c9fbb8544152d9e9"
   dependencies:
     adjust-sourcemap-loader "^1.1.0"
     camelcase "^4.0.0"
@@ -6201,7 +6214,7 @@ schema-utils@^0.3.0, schema-utils@^0.x:
   dependencies:
     ajv "^5.0.0"
 
-scroll-behavior@^0.9.3:
+scroll-behavior@^0.9.1:
   version "0.9.3"
   resolved "https://registry.yarnpkg.com/scroll-behavior/-/scroll-behavior-0.9.3.tgz#e48bcc8af364f3f07176e8dbca3968bd5e71557b"
   dependencies:
@@ -6977,6 +6990,10 @@ validate-npm-package-license@^3.0.1:
     spdx-correct "~1.0.0"
     spdx-expression-parse "~1.0.0"
 
+value-equal@^0.2.0:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-0.2.1.tgz#c220a304361fce6994dbbedaa3c7e1a1b895871d"
+
 vary@~1.1.0, vary@~1.1.1:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37"