diff --git a/frontend/src/metabase/admin/databases/components/CreatedDatabaseModal.jsx b/frontend/src/metabase/admin/databases/components/CreatedDatabaseModal.jsx
index 29c31dbd99275f2afc8c53df334af36ec1f78098..eb6788801c35d82b27302f4e64664f894a7ce076 100644
--- a/frontend/src/metabase/admin/databases/components/CreatedDatabaseModal.jsx
+++ b/frontend/src/metabase/admin/databases/components/CreatedDatabaseModal.jsx
@@ -3,6 +3,8 @@ import { Link } from "react-router";
 
 import ModalContent from "metabase/components/ModalContent.jsx";
 
+import * as Urls from "metabase/lib/urls";
+
 export default class CreatedDatabaseModal extends Component {
     static propTypes = {
         databaseId: PropTypes.number.isRequired,
@@ -22,7 +24,7 @@ export default class CreatedDatabaseModal extends Component {
                         We're analyzing its schema now to make some educated guesses about its
                         metadata. <Link to={"/admin/datamodel/database/"+databaseId}>View this
                         database</Link> in the Data Model section to see what we've found and to
-                        make edits, or <Link to={"/q#?db="+databaseId}>ask a question</Link> about
+                        make edits, or <Link to={Urls.question(null, `?db=${databaseId}`)}>ask a question</Link> about
                         this database.
                     </p>
                 </div>
diff --git a/frontend/src/metabase/admin/datamodel/components/PartialQueryBuilder.jsx b/frontend/src/metabase/admin/datamodel/components/PartialQueryBuilder.jsx
index 133fc5c27f05bcdf1b76aa478e0e8056e9cb8067..ea5abefc8c5f745bece440f429f9836f0d7dfd12 100644
--- a/frontend/src/metabase/admin/datamodel/components/PartialQueryBuilder.jsx
+++ b/frontend/src/metabase/admin/datamodel/components/PartialQueryBuilder.jsx
@@ -2,7 +2,7 @@ import React, { Component, PropTypes } from "react";
 
 import GuiQueryEditor from "metabase/query_builder/components/GuiQueryEditor.jsx";
 
-import { serializeCardForUrl } from "metabase/lib/card";
+import * as Urls from "metabase/lib/urls";
 
 import cx from "classnames";
 
@@ -56,7 +56,7 @@ export default class PartialQueryBuilder extends Component {
                 }
             }
         };
-        let previewUrl = "/q#" + serializeCardForUrl(previewCard);
+        let previewUrl = Urls.question(null, previewCard);
 
         const onChange = (query) => {
             this.props.onChange(query);
diff --git a/frontend/src/metabase/admin/settings/components/widgets/PublicLinksListing.jsx b/frontend/src/metabase/admin/settings/components/widgets/PublicLinksListing.jsx
index 109b043fa9f1bfe3e9a8295e6c5472340a6a0366..c2719ee5c9d4c6434c437efc1c6ff541036bc904 100644
--- a/frontend/src/metabase/admin/settings/components/widgets/PublicLinksListing.jsx
+++ b/frontend/src/metabase/admin/settings/components/widgets/PublicLinksListing.jsx
@@ -9,7 +9,7 @@ import Confirm from "metabase/components/Confirm";
 import LoadingAndErrorWrapper from "metabase/components/LoadingAndErrorWrapper";
 
 import { CardApi, DashboardApi } from "metabase/services";
-import Urls from "metabase/lib/urls";
+import * as Urls from "metabase/lib/urls";
 
 import MetabaseAnalytics from "metabase/lib/analytics";
 
@@ -161,7 +161,7 @@ export const PublicLinksQuestionListing = () =>
         load={CardApi.listPublic}
         revoke={CardApi.deletePublicLink}
         type='Public Card Listing'
-        getUrl={({ id }) => Urls.card(id)}
+        getUrl={({ id }) => Urls.question(id)}
         getPublicUrl={({ public_uuid }) => window.location.origin + Urls.publicCard(public_uuid)}
         noLinksMessage="No questions have been publicly shared yet."
     />;
@@ -177,7 +177,7 @@ export const EmbeddedDashboardListing = () =>
 export const EmbeddedQuestionListing = () =>
     <PublicLinksListing
         load={CardApi.listEmbeddable}
-        getUrl={({ id }) => Urls.card(id)}
+        getUrl={({ id }) => Urls.question(id)}
         type='Embedded Card Listing'
         noLinksMessage="No questions have been embedded yet."
     />;
diff --git a/frontend/src/metabase/components/AddToDashSelectDashModal.jsx b/frontend/src/metabase/components/AddToDashSelectDashModal.jsx
index 408cb5777523ee39bdb95e3a7bce27f553055a8e..0492804ed33e38179f64bd9d66b10f5a31fceb19 100644
--- a/frontend/src/metabase/components/AddToDashSelectDashModal.jsx
+++ b/frontend/src/metabase/components/AddToDashSelectDashModal.jsx
@@ -5,7 +5,7 @@ import Icon from 'metabase/components/Icon.jsx';
 import ModalContent from "metabase/components/ModalContent.jsx";
 import SortableItemList from 'metabase/components/SortableItemList.jsx';
 
-import Urls from "metabase/lib/urls";
+import * as Urls from "metabase/lib/urls";
 import { DashboardApi } from "metabase/services";
 
 import moment from 'moment';
diff --git a/frontend/src/metabase/components/NotFound.jsx b/frontend/src/metabase/components/NotFound.jsx
index 0eb16a19945a2dbe89ac36d3a778b913b0820d96..cdf98c4afcac3c1fccdfc438d34ca0e947f6344b 100644
--- a/frontend/src/metabase/components/NotFound.jsx
+++ b/frontend/src/metabase/components/NotFound.jsx
@@ -1,6 +1,8 @@
 import React, { Component, PropTypes } from "react";
 import { Link } from "react-router";
 
+import * as Urls from "metabase/lib/urls";
+
 export default class NotFound extends Component {
     render() {
         return (
@@ -11,7 +13,7 @@ export default class NotFound extends Component {
                     <p className="h4">You might've been tricked by a ninja, but in all likelihood, you were just given a bad link.</p>
                     <p className="h4 my4">You can always:</p>
                     <div className="flex align-center">
-                        <Link to="/q" className="Button Button--primary">
+                        <Link to={Urls.question()} className="Button Button--primary">
                             <div className="p1">Ask a new question.</div>
                         </Link>
                         <span className="mx2">or</span>
diff --git a/frontend/src/metabase/dashboard/containers/DashboardEmbedWidget.jsx b/frontend/src/metabase/dashboard/containers/DashboardEmbedWidget.jsx
index 6ff0deeb50520db60ecf107be57925c318123142..50ca40dee81a890a314713e9f0adac57686d7c9a 100644
--- a/frontend/src/metabase/dashboard/containers/DashboardEmbedWidget.jsx
+++ b/frontend/src/metabase/dashboard/containers/DashboardEmbedWidget.jsx
@@ -5,7 +5,7 @@ import { connect } from "react-redux";
 
 import EmbedWidget from "metabase/public/components/widgets/EmbedWidget";
 
-import Urls from "metabase/lib/urls";
+import * as Urls from "metabase/lib/urls";
 
 import { createPublicLink, deletePublicLink, updateEnableEmbedding, updateEmbeddingParams } from "../dashboard";
 
diff --git a/frontend/src/metabase/home/components/Activity.jsx b/frontend/src/metabase/home/components/Activity.jsx
index 69dcce269099d519495e83ac6a2ff91787aca92f..bc8d65ca2c60aab05fb1102ef878b4661f4c9731 100644
--- a/frontend/src/metabase/home/components/Activity.jsx
+++ b/frontend/src/metabase/home/components/Activity.jsx
@@ -6,7 +6,7 @@ import LoadingAndErrorWrapper from 'metabase/components/LoadingAndErrorWrapper.j
 import ActivityItem from './ActivityItem.jsx';
 import ActivityStory from './ActivityStory.jsx';
 
-import Urls from 'metabase/lib/urls';
+import * as Urls from "metabase/lib/urls";
 
 export default class Activity extends Component {
 
@@ -213,7 +213,7 @@ export default class Activity extends Component {
             case "dashboard-remove-cards":
                 description.body = item.details.dashcards[0].name;
                 if (item.details.dashcards[0].exists) {
-                    description.bodyLink = Urls.card(item.details.dashcards[0].card_id);
+                    description.bodyLink = Urls.question(item.details.dashcards[0].card_id);
                 }
                 break;
             case "metric-create":
diff --git a/frontend/src/metabase/home/components/NewUserOnboardingModal.jsx b/frontend/src/metabase/home/components/NewUserOnboardingModal.jsx
index 1de3e68b33880d05c0de16500768e7c36579329b..d58b1ff6912110f687a4df04804bae7e4fc7f8a5 100644
--- a/frontend/src/metabase/home/components/NewUserOnboardingModal.jsx
+++ b/frontend/src/metabase/home/components/NewUserOnboardingModal.jsx
@@ -2,6 +2,7 @@ import React, { Component, PropTypes } from "react";
 import { Link } from "react-router";
 
 import MetabaseSettings from "metabase/lib/settings";
+import * as Urls from "metabase/lib/urls";
 
 export default class NewUserOnboardingModal extends Component {
     constructor(props, context) {
@@ -84,7 +85,7 @@ export default class NewUserOnboardingModal extends Component {
                             {this.renderStep()}
                             <span className="flex-align-right">
                                 <a className="text-underline-hover cursor-pointer mr3" onClick={() => (this.closeModal())}>skip for now</a>
-                                <Link to="/q#?tutorial" className="Button Button--primary">Let's do it!</Link>
+                                <Link to={Urls.question(null, "?tutorial")} className="Button Button--primary">Let's do it!</Link>
                             </span>
                         </div>
                     </div>
diff --git a/frontend/src/metabase/home/components/RecentViews.jsx b/frontend/src/metabase/home/components/RecentViews.jsx
index f1146966a807b999db69613662d91df7f7d40d4f..9a967584956eed30780e4128ede71e705e7f7b1e 100644
--- a/frontend/src/metabase/home/components/RecentViews.jsx
+++ b/frontend/src/metabase/home/components/RecentViews.jsx
@@ -3,7 +3,7 @@ import { Link } from "react-router";
 
 import Icon from "metabase/components/Icon.jsx";
 import SidebarSection from "./SidebarSection.jsx";
-import Urls from "metabase/lib/urls";
+import * as Urls from "metabase/lib/urls";
 
 import { normal } from "metabase/lib/colors";
 
diff --git a/frontend/src/metabase/lib/card.js b/frontend/src/metabase/lib/card.js
index b53d09d1732ae751d2dcddc8f34f73d8986ac573..2b0ac9090b755dc86b2a981f6fdd1cb00de4faa3 100644
--- a/frontend/src/metabase/lib/card.js
+++ b/frontend/src/metabase/lib/card.js
@@ -1,6 +1,7 @@
 import _ from "underscore";
 import Query, { createQuery } from "metabase/lib/query";
 import Utils from "metabase/lib/utils";
+import * as Urls from "metabase/lib/urls";
 
 import { CardApi } from "metabase/services";
 
@@ -24,10 +25,10 @@ export function startNewCard(type, databaseId, tableId) {
 }
 
 // load a card either by ID or from a base64 serialization.  if both are present then they are merged, which the serialized version taking precedence
+// TODO: move to redux
 export async function loadCard(cardId) {
     try {
-        let card = await CardApi.get({ "cardId": cardId });
-        return card && cleanCopyCard(card);
+        return await CardApi.get({ "cardId": cardId });
     } catch (error) {
         console.log("error loading card", error);
         throw error;
@@ -111,16 +112,10 @@ export function b64url_to_utf8(b64url) {
 }
 
 export function urlForCardState(state, dirty) {
-    var url;
-    if (state.cardId) {
-        url = "/card/" + state.cardId;
-    } else {
-        url = "/q";
-    }
-    if (state.serializedCard && dirty) {
-        url += "#" + state.serializedCard;
-    }
-    return url;
+    return Urls.question(
+        state.cardId,
+        (state.serializedCard && dirty) ? state.serializedCard : ""
+    );
 }
 
 export function cleanCopyCard(card) {
diff --git a/frontend/src/metabase/lib/urls.js b/frontend/src/metabase/lib/urls.js
index ed11450f3b0fd4c68e1de077a1e29dc25ee491ea..7c2eba73166aeef3535ac9f4ee9e9f3b995fba8d 100644
--- a/frontend/src/metabase/lib/urls.js
+++ b/frontend/src/metabase/lib/urls.js
@@ -1,66 +1,71 @@
 import { serializeCardForUrl } from "metabase/lib/card";
 
 // provides functions for building urls to things we care about
-var Urls = {
-    q: function(card) {
-        return "/q#" + serializeCardForUrl(card);
-    },
 
-    card: function(card_id) {
-        // NOTE that this is for an ephemeral card link, not an editable card
-        return "/card/"+card_id;
-    },
-
-    dashboard: function(dashboard_id) {
-        return "/dash/"+dashboard_id;
-    },
+export function question(cardId, cardOrHash = "") {
+    if (cardOrHash && typeof cardOrHash === "object") {
+        cardOrHash = serializeCardForUrl(cardOrHash);
+    }
+    if (cardOrHash && cardOrHash.charAt(0) !== "#") {
+        cardOrHash = "#" + cardOrHash;
+    }
+    // NOTE that this is for an ephemeral card link, not an editable card
+    return cardId != null
+        ? `/question/${cardId}${cardOrHash}`
+        : `/question${cardOrHash}`;
+}
 
-    modelToUrl: function(model, model_id) {
-        switch (model) {
-            case "card":      return Urls.card(model_id);
-            case "dashboard": return Urls.dashboard(model_id);
-            case "pulse":     return Urls.pulse(model_id);
-            default:          return null;
-        }
-    },
+export function dashboard(dashboardId) {
+    return `/dashboard/${dashboardId}`;
+}
 
-    pulse: function(pulse_id) {
-        return "/pulse/#"+pulse_id;
-    },
+export function modelToUrl(model, modelId) {
+    switch (model) {
+        case "card":
+            return question(modelId);
+        case "dashboard":
+            return dashboard(modelId);
+        case "pulse":
+            return pulse(modelId);
+        default:
+            return null;
+    }
+}
 
-    tableRowsQuery: function(database_id, table_id, metric_id, segment_id) {
-        let url = "/q#?db="+database_id+"&table="+table_id;
+export function pulse(pulseId) {
+    return `/pulse/#${pulseId}`;
+}
 
-        if (metric_id) {
-            url = url + "&metric="+metric_id;
-        }
+export function tableRowsQuery(databaseId, tableId, metricId, segmentId) {
+    let query = `?db=${databaseId}&table=${tableId}`;
 
-        if (segment_id) {
-            url = url + "&segment="+segment_id;
-        }
+    if (metricId) {
+        query += `&metric=${metricId}`;
+    }
 
-        return url;
-    },
+    if (segmentId) {
+        query += `&segment=${segmentId}`;
+    }
 
-    collection(collection) {
-        return `/questions/collections/${encodeURIComponent(collection.slug)}`;
-    },
+    return question(null, query);
+}
 
-    label(label) {
-        return `/questions/search?label=${encodeURIComponent(label.slug)}`;
-    },
+export function collection(collection) {
+    return `/questions/collections/${encodeURIComponent(collection.slug)}`;
+}
 
-    publicCard(uuid, type = null) {
-        return `/public/question/${uuid}` + (type ? `.${type}` : ``);
-    },
+export function label(label) {
+    return `/questions/search?label=${encodeURIComponent(label.slug)}`;
+}
 
-    publicDashboard(uuid) {
-        return `/public/dashboard/${uuid}`;
-    },
+export function publicCard(uuid, type = null) {
+    return `/public/question/${uuid}` + (type ? `.${type}` : ``);
+}
 
-    embedCard(token, type = null) {
-        return `/embed/question/${token}` + (type ? `.${type}` : ``);
-    },
+export function publicDashboard(uuid) {
+    return `/public/dashboard/${uuid}`;
 }
 
-export default Urls;
+export function embedCard(token, type = null) {
+    return `/embed/question/${token}` + (type ? `.${type}` : ``);
+}
diff --git a/frontend/src/metabase/nav/containers/DashboardsDropdown.jsx b/frontend/src/metabase/nav/containers/DashboardsDropdown.jsx
index b902a25096e2c25ff4cdac9d6854c6b69643a88c..425c4d220862d0d318126d3c532ed7560f8ca26f 100644
--- a/frontend/src/metabase/nav/containers/DashboardsDropdown.jsx
+++ b/frontend/src/metabase/nav/containers/DashboardsDropdown.jsx
@@ -3,12 +3,13 @@ import { connect } from "react-redux";
 import { Link } from "react-router";
 
 import OnClickOutsideWrapper from 'metabase/components/OnClickOutsideWrapper.jsx';
-
-import MetabaseAnalytics from "metabase/lib/analytics";
 import CreateDashboardModal from "metabase/components/CreateDashboardModal.jsx";
 import Modal from "metabase/components/Modal.jsx";
 import ConstrainToScreen from "metabase/components/ConstrainToScreen";
 
+import MetabaseAnalytics from "metabase/lib/analytics";
+import * as Urls from "metabase/lib/urls";
+
 import _ from "underscore";
 import cx from "classnames";
 
@@ -62,7 +63,7 @@ export default class DashboardsDropdown extends Component {
         try {
             let action = await createDashboard(newDashboard, true);
             // FIXME: this doesn't feel right...
-            this.props.onChangeLocation(`/dash/${action.payload.id}`);
+            this.props.onChangeLocation(Urls.dashboard(action.payload.id));
         } catch (e) {
             console.log("createDashboard failed", e);
         }
@@ -137,7 +138,7 @@ export default class DashboardsDropdown extends Component {
                                     <ul className="NavDropdown-content-layer">
                                         { dashboards.map(dash =>
                                             <li key={dash.id} className="block">
-                                                <Link to={"/dash/"+dash.id} data-metabase-event={"Navbar;Dashboard Dropdown;Open Dashboard;"+dash.id} className="Dropdown-item block text-white no-decoration" onClick={this.closeDropdown}>
+                                                <Link to={Urls.dashboard(dash.id)} data-metabase-event={"Navbar;Dashboard Dropdown;Open Dashboard;"+dash.id} className="Dropdown-item block text-white no-decoration" onClick={this.closeDropdown}>
                                                     <div className="flex text-bold">
                                                         {dash.name}
                                                     </div>
diff --git a/frontend/src/metabase/nav/containers/Navbar.jsx b/frontend/src/metabase/nav/containers/Navbar.jsx
index 74520d03ff4d49a44a9bc1a91e2df4f3bf0ee24c..3dc5c7f4cef6f4ebf7bba46752d1e5fdf9baa5bb 100644
--- a/frontend/src/metabase/nav/containers/Navbar.jsx
+++ b/frontend/src/metabase/nav/containers/Navbar.jsx
@@ -11,6 +11,8 @@ import LogoIcon from "metabase/components/LogoIcon.jsx";
 import DashboardsDropdown from "metabase/nav/containers/DashboardsDropdown.jsx";
 import ProfileLink from "metabase/nav/components/ProfileLink.jsx";
 
+import * as Urls from "metabase/lib/urls";
+
 import { getPath, getContext, getUser } from "../selectors";
 
 const mapStateToProps = (state, props) => ({
@@ -115,7 +117,13 @@ export default class Navbar extends Component {
                     </li>
                     <li className="pl3">
                         <DashboardsDropdown {...this.props}>
-                            <a data-metabase-event={"Navbar;Dashboard Dropdown;Toggle"} style={this.styles.navButton} className={cx("NavDropdown-button NavItem text-white text-bold cursor-pointer px2 flex align-center transition-background", {"NavItem--selected": this.isActive("/dash/")})}>
+                            <a
+                                data-metabase-event={"Navbar;Dashboard Dropdown;Toggle"}
+                                style={this.styles.navButton}
+                                className={cx("NavDropdown-button NavItem text-white text-bold cursor-pointer px2 flex align-center transition-background", {
+                                    "NavItem--selected": this.isActive("/dashboard/")
+                                })}
+                            >
                                 <span className="NavDropdown-button-layer">
                                     Dashboards
                                     <Icon className="ml1" name={'chevrondown'} size={8}></Icon>
@@ -133,7 +141,7 @@ export default class Navbar extends Component {
                         <Link to="/reference/guide" data-metabase-event={"Navbar;DataReference"} style={this.styles.navButton} className={cx("NavItem cursor-pointer text-white text-bold no-decoration flex align-center px2 transition-background")} activeClassName="NavItem--selected">Data Reference</Link>
                     </li>
                     <li className="pl3">
-                        <Link to="/q" data-metabase-event={"Navbar;New Question"} style={this.styles.newQuestion} className="NavNewQuestion rounded inline-block bg-white text-brand text-bold cursor-pointer px2 no-decoration transition-all">New <span className="hide sm-show">Question</span></Link>
+                        <Link to={Urls.question()} data-metabase-event={"Navbar;New Question"} style={this.styles.newQuestion} className="NavNewQuestion rounded inline-block bg-white text-brand text-bold cursor-pointer px2 no-decoration transition-all">New <span className="hide sm-show">Question</span></Link>
                     </li>
                     <li className="flex-align-right transition-background">
                         <div className="inline-block text-white"><ProfileLink {...this.props}></ProfileLink></div>
diff --git a/frontend/src/metabase/pulse/components/PulseListItem.jsx b/frontend/src/metabase/pulse/components/PulseListItem.jsx
index 7429928e757872a2c685fb3d3549fe073191833a..47c0e3b7e2c6468f17cdcef9b4fda291c0572723 100644
--- a/frontend/src/metabase/pulse/components/PulseListItem.jsx
+++ b/frontend/src/metabase/pulse/components/PulseListItem.jsx
@@ -5,7 +5,7 @@ import { Link } from "react-router";
 
 import cx from "classnames";
 
-import Urls from "metabase/lib/urls";
+import * as Urls from "metabase/lib/urls";
 import PulseListChannel from "./PulseListChannel.jsx";
 
 export default class PulseListItem extends Component {
@@ -43,7 +43,7 @@ export default class PulseListItem extends Component {
                 <ol className="mb2 px4 flex flex-wrap">
                     { pulse.cards.map((card, index) =>
                         <li key={index} className="mr1 mb1">
-                            <Link to={Urls.card(card.id)} className="Button">
+                            <Link to={Urls.question(card.id)} className="Button">
                                 {card.name}
                             </Link>
                         </li>
diff --git a/frontend/src/metabase/query_builder/components/QueryDownloadWidget.jsx b/frontend/src/metabase/query_builder/components/QueryDownloadWidget.jsx
index 58ead4423d3d5bfc1e7931c0bb4b6f11bb1d2664..337b5ac6b1f0c91c5523244ba746833e0b63483e 100644
--- a/frontend/src/metabase/query_builder/components/QueryDownloadWidget.jsx
+++ b/frontend/src/metabase/query_builder/components/QueryDownloadWidget.jsx
@@ -7,7 +7,7 @@ import Tooltip from "metabase/components/Tooltip.jsx";
 
 import FieldSet from "metabase/components/FieldSet.jsx";
 
-import Urls from "metabase/lib/urls";
+import * as Urls from "metabase/lib/urls";
 
 import _ from "underscore";
 import cx from "classnames";
diff --git a/frontend/src/metabase/query_builder/components/QueryHeader.jsx b/frontend/src/metabase/query_builder/components/QueryHeader.jsx
index 2e61da66556b74a6600bced942a4b3457a78ee0d..ff451023ecaa2485dfb2044d9a0cb93533fdc446 100644
--- a/frontend/src/metabase/query_builder/components/QueryHeader.jsx
+++ b/frontend/src/metabase/query_builder/components/QueryHeader.jsx
@@ -23,7 +23,7 @@ import { CardApi, RevisionApi } from "metabase/services";
 import MetabaseAnalytics from "metabase/lib/analytics";
 import Query from "metabase/lib/query";
 import { cancelable } from "metabase/lib/promise";
-import Urls from "metabase/lib/urls";
+import * as Urls from "metabase/lib/urls";
 
 import cx from "classnames";
 import _ from "underscore";
diff --git a/frontend/src/metabase/query_builder/components/QueryVisualization.jsx b/frontend/src/metabase/query_builder/components/QueryVisualization.jsx
index c236ebd05c6a7eca95310cfbf2ae8f178ae4a85a..b83c10c334110d563ed19da32b8065fe63ad9520 100644
--- a/frontend/src/metabase/query_builder/components/QueryVisualization.jsx
+++ b/frontend/src/metabase/query_builder/components/QueryVisualization.jsx
@@ -15,6 +15,7 @@ import QuestionEmbedWidget from "../containers/QuestionEmbedWidget";
 import { formatNumber, inflect } from "metabase/lib/formatting";
 import Utils from "metabase/lib/utils";
 import MetabaseSettings from "metabase/lib/settings";
+import * as Urls from "metabase/lib/urls";
 
 import cx from "classnames";
 import _ from "underscore";
@@ -188,5 +189,5 @@ export default class QueryVisualization extends Component {
 const VisualizationEmptyState = ({showTutorialLink}) =>
     <div className="flex full layout-centered text-grey-1 flex-column">
         <h1>If you give me some data I can show you something cool. Run a Query!</h1>
-        { showTutorialLink && <Link to="/q#?tutorial" className="link cursor-pointer my2">How do I use this thing?</Link> }
+        { showTutorialLink && <Link to={Urls.question(null, "?tutorial")} className="link cursor-pointer my2">How do I use this thing?</Link> }
     </div>
diff --git a/frontend/src/metabase/query_builder/containers/QueryBuilder.jsx b/frontend/src/metabase/query_builder/containers/QueryBuilder.jsx
index 95f367df9fa450f25cb94ddc88ed670c35a0138b..e0fddf9f11224e94198af92083e27dd7dae97aee 100644
--- a/frontend/src/metabase/query_builder/containers/QueryBuilder.jsx
+++ b/frontend/src/metabase/query_builder/containers/QueryBuilder.jsx
@@ -154,9 +154,9 @@ export default class QueryBuilder extends Component {
 
         if (nextProps.location.action === "POP" && getURL(nextProps.location) !== getURL(this.props.location)) {
             this.props.popState(nextProps.location);
-        } else if (this.props.location.query.tutorial === undefined && nextProps.location.query.tutorial !== undefined) {
+        } else if (this.props.location.hash !== "#?tutorial" && nextProps.location.hash === "#?tutorial") {
             this.props.initializeQB(nextProps.location, nextProps.params);
-        } else if (getURL(nextProps.location) === "/q" && getURL(this.props.location) !== "/q") {
+        } else if (getURL(nextProps.location) === "/question" && getURL(this.props.location) !== "/question") {
             this.props.initializeQB(nextProps.location, nextProps.params);
         }
     }
diff --git a/frontend/src/metabase/query_builder/containers/QuestionEmbedWidget.jsx b/frontend/src/metabase/query_builder/containers/QuestionEmbedWidget.jsx
index d285d4c94d8dc3c1d6b1402e76bbc91ca5a3f36c..faf973c0dcde01a03a5344df4eacb9b05aad9e71 100644
--- a/frontend/src/metabase/query_builder/containers/QuestionEmbedWidget.jsx
+++ b/frontend/src/metabase/query_builder/containers/QuestionEmbedWidget.jsx
@@ -5,7 +5,7 @@ import { connect } from "react-redux";
 
 import EmbedWidget from "metabase/public/components/widgets/EmbedWidget";
 
-import Urls from "metabase/lib/urls";
+import * as Urls from "metabase/lib/urls";
 
 import { getParameters } from "metabase/meta/Card";
 import { createPublicLink, deletePublicLink, updateEnableEmbedding, updateEmbeddingParams, } from "../actions";
diff --git a/frontend/src/metabase/questions/collections.js b/frontend/src/metabase/questions/collections.js
index 98ffd30aa0967674657997ae18af6a66f19d9069..592417105a325b7ba5ad1890a68ff19bc568216d 100644
--- a/frontend/src/metabase/questions/collections.js
+++ b/frontend/src/metabase/questions/collections.js
@@ -2,7 +2,7 @@
 import { createAction, createThunkAction, handleActions, combineReducers } from "metabase/lib/redux";
 import { reset } from 'redux-form';
 import { replace } from "react-router-redux";
-import Urls from "metabase/lib/urls";
+import * as Urls from "metabase/lib/urls";
 
 import _ from "underscore";
 
diff --git a/frontend/src/metabase/questions/components/CollectionBadge.jsx b/frontend/src/metabase/questions/components/CollectionBadge.jsx
index 143520b64333f5aa63cb28db9bc50eef5d7dfa91..17cb724c593c6a9675ae80f29e048a7d60b49483 100644
--- a/frontend/src/metabase/questions/components/CollectionBadge.jsx
+++ b/frontend/src/metabase/questions/components/CollectionBadge.jsx
@@ -1,7 +1,7 @@
 import React, { Component, PropTypes } from "react";
 import { Link } from "react-router";
 
-import Urls from "metabase/lib/urls";
+import * as Urls from "metabase/lib/urls";
 
 import Color from "color";
 import cx from "classnames";
diff --git a/frontend/src/metabase/questions/components/Item.jsx b/frontend/src/metabase/questions/components/Item.jsx
index b8f5003d4fd7c20809de6f5504c96cc032442fd3..0f24593d33436ab5a8f50609763634927756e878 100644
--- a/frontend/src/metabase/questions/components/Item.jsx
+++ b/frontend/src/metabase/questions/components/Item.jsx
@@ -14,7 +14,7 @@ import MoveToCollection from "../containers/MoveToCollection.jsx";
 import Labels from "./Labels.jsx";
 import CollectionBadge from "./CollectionBadge.jsx";
 
-import Urls from "metabase/lib/urls";
+import * as Urls from "metabase/lib/urls";
 
 const ITEM_ICON_SIZE = 20;
 
@@ -122,7 +122,7 @@ Item.propTypes = {
 const ItemBody = pure(({ entity, id, name, description, labels, favorite, collection, setFavorited, onEntityClick }) =>
     <div className={S.itemBody}>
         <div className={cx('flex', S.itemTitle)}>
-            <Link to={Urls.card(id)} className={cx(S.itemName)} onClick={onEntityClick && ((e) => { e.preventDefault(); onEntityClick(entity); })}>
+            <Link to={Urls.question(id)} className={cx(S.itemName)} onClick={onEntityClick && ((e) => { e.preventDefault(); onEntityClick(entity); })}>
                 {name}
             </Link>
             { collection &&
diff --git a/frontend/src/metabase/questions/components/Labels.jsx b/frontend/src/metabase/questions/components/Labels.jsx
index cadf7680243fc2acd3dc436d3c45eac04b524f1f..dabc0137ce8a198158efdd891d5a8ebef9123e32 100644
--- a/frontend/src/metabase/questions/components/Labels.jsx
+++ b/frontend/src/metabase/questions/components/Labels.jsx
@@ -3,7 +3,7 @@ import React, { Component, PropTypes } from "react";
 import { Link } from "react-router";
 import S from "./Labels.css";
 import color from 'color'
-import Urls from "metabase/lib/urls";
+import * as Urls from "metabase/lib/urls";
 
 import EmojiIcon from "metabase/components/EmojiIcon.jsx"
 
diff --git a/frontend/src/metabase/questions/questions.js b/frontend/src/metabase/questions/questions.js
index 9d1970c246abe09a32a35cda55ae91100af7ecfe..056815d94ee2c1828401aafc862f112d7af16502 100644
--- a/frontend/src/metabase/questions/questions.js
+++ b/frontend/src/metabase/questions/questions.js
@@ -7,7 +7,7 @@ import _ from "underscore";
 
 import { inflect } from "metabase/lib/formatting";
 import MetabaseAnalytics from "metabase/lib/analytics";
-import Urls from "metabase/lib/urls";
+import * as Urls from "metabase/lib/urls";
 
 import { push, replace } from "react-router-redux";
 import { setRequestState } from "metabase/redux/requests";
diff --git a/frontend/src/metabase/reference/components/GuideDetail.jsx b/frontend/src/metabase/reference/components/GuideDetail.jsx
index bbb27cc09b74ceff2c85ff22c45cd4925aa6add1..faf42ad83f95d13464616e6e2b550c21fc823ad3 100644
--- a/frontend/src/metabase/reference/components/GuideDetail.jsx
+++ b/frontend/src/metabase/reference/components/GuideDetail.jsx
@@ -2,7 +2,9 @@ import React, { Component, PropTypes } from "react";
 import { Link } from "react-router";
 import pure from "recompose/pure";
 import cx from "classnames";
+
 import Icon from "metabase/components/Icon"
+import * as Urls from "metabase/lib/urls";
 
 import {
     getQuestionUrl,
@@ -21,7 +23,7 @@ const GuideDetail = ({
     const title = entity.display_name || entity.name;
     const { caveats, points_of_interest } = entity;
     const typeToLink = {
-        dashboard: `/dash/${entity.id}`,
+        dashboard: Urls.dashboard(entity.id),
         metric: getQuestionUrl({
             dbId: tables[entity.table_id] && tables[entity.table_id].db_id,
             tableId: entity.table_id,
diff --git a/frontend/src/metabase/reference/containers/ReferenceEntityList.jsx b/frontend/src/metabase/reference/containers/ReferenceEntityList.jsx
index daf3818bd173b97955d390ef587e863b4299d9a7..9f821341533866af791d903eec787c720cec6106 100644
--- a/frontend/src/metabase/reference/containers/ReferenceEntityList.jsx
+++ b/frontend/src/metabase/reference/containers/ReferenceEntityList.jsx
@@ -5,6 +5,7 @@ import moment from "moment";
 
 import visualizations from "metabase/visualizations";
 import { isQueryable } from "metabase/lib/table";
+import * as Urls from "metabase/lib/urls";
 
 import S from "metabase/components/List.css";
 import R from "metabase/reference/Reference.css";
@@ -57,7 +58,7 @@ const createListItem = (entity, index, section) =>
             }
             url={section.type !== 'questions' ?
                 `${section.id}/${entity.id}` :
-                `/card/${entity.id}`
+                Urls.question(entity.id)
             }
             icon={section.type === 'questions' ?
                 visualizations.get(entity.display).iconName :
diff --git a/frontend/src/metabase/reference/containers/ReferenceGettingStartedGuide.jsx b/frontend/src/metabase/reference/containers/ReferenceGettingStartedGuide.jsx
index a5640fb8d7295fb1b3d616207ce54a3a38edbcef..b34c861b019d881c0797b701c203b252bc49b08f 100644
--- a/frontend/src/metabase/reference/containers/ReferenceGettingStartedGuide.jsx
+++ b/frontend/src/metabase/reference/containers/ReferenceGettingStartedGuide.jsx
@@ -4,10 +4,12 @@ import { Link } from "react-router";
 import { connect } from 'react-redux';
 import { push } from 'react-router-redux';
 import { reduxForm } from "redux-form";
+
 import { assoc } from "icepick";
 import cx from "classnames";
 
 import MetabaseAnalytics from "metabase/lib/analytics";
+import * as Urls from "metabase/lib/urls";
 
 import LoadingAndErrorWrapper from "metabase/components/LoadingAndErrorWrapper.jsx";
 import CreateDashboardModal from 'metabase/components/CreateDashboardModal.jsx';
@@ -225,7 +227,7 @@ export default class ReferenceGettingStartedGuide extends Component {
                             createDashboardFn={async (newDashboard) => {
                                 try {
                                     const action = await createDashboard(newDashboard, true);
-                                    push(`/dash/${action.payload.id}`);
+                                    push(Urls.dashboard(action.payload.id));
                                 }
                                 catch(error) {
                                     console.error(error);
@@ -632,4 +634,4 @@ const AdminInstructions = ({ children }) => // eslint-disable-line react/prop-ty
     </div>
 
 const SectionHeader = ({ trim, children }) => // eslint-disable-line react/prop-types
-    <h2 className={cx('text-dark text-measure', {  "mb0" : trim }, { "mb4" : !trim })}>{children}</h2> 
+    <h2 className={cx('text-dark text-measure', {  "mb0" : trim }, { "mb4" : !trim })}>{children}</h2>
diff --git a/frontend/src/metabase/reference/utils.js b/frontend/src/metabase/reference/utils.js
index e22840da4f48bf99e05eb563c75c6951927bee43..0a85e12cc89dcc5ec8ef40b417179cc031cae011 100644
--- a/frontend/src/metabase/reference/utils.js
+++ b/frontend/src/metabase/reference/utils.js
@@ -2,8 +2,9 @@ import { assoc, assocIn, chain } from "icepick";
 import _ from "underscore";
 
 import { titleize, humanize } from "metabase/lib/formatting";
-import { startNewCard, serializeCardForUrl } from "metabase/lib/card";
+import { startNewCard } from "metabase/lib/card";
 import { isPK } from "metabase/lib/types";
+import * as Urls from "metabase/lib/urls";
 
 export const idsToObjectMap = (ids, objects) => ids
     .map(id => objects[id])
@@ -76,11 +77,10 @@ export const tryUpdateData = async (fields, props) => {
                 const importantFieldIds = fields.important_fields.map(field => field.id);
                 const existingImportantFieldIds = guide.metric_important_fields && guide.metric_important_fields[entity.id];
 
-                const areFieldIdsIdentitical = existingImportantFieldIds && 
+                const areFieldIdsIdentitical = existingImportantFieldIds &&
                     existingImportantFieldIds.length === importantFieldIds.length &&
                     existingImportantFieldIds.every(id => importantFieldIds.includes(id));
-                
-                console.log(areFieldIdsIdentitical);
+
                 if (!areFieldIdsIdentitical) {
                     await updateMetricImportantFields(entity.id, importantFieldIds);
                     tryFetchData(props);
@@ -156,8 +156,8 @@ export const tryUpdateGuide = async (formFields, props) => {
     startLoading();
     try {
         const updateNewEntities = ({
-            entities, 
-            formFields, 
+            entities,
+            formFields,
             updateEntity
         }) => formFields.map(formField => {
             if (!formField.id) {
@@ -175,7 +175,7 @@ export const tryUpdateGuide = async (formFields, props) => {
 
             const newEntity = entities[formField.id];
             const updatedNewEntity = {
-                ...newEntity, 
+                ...newEntity,
                 ...editedEntity
             };
 
@@ -185,9 +185,9 @@ export const tryUpdateGuide = async (formFields, props) => {
         });
 
         const updateOldEntities = ({
-            newEntityIds, 
-            oldEntityIds, 
-            entities, 
+            newEntityIds,
+            oldEntityIds,
+            entities,
             updateEntity
         }) => oldEntityIds
             .filter(oldEntityId => !newEntityIds.includes(oldEntityId))
@@ -201,14 +201,14 @@ export const tryUpdateGuide = async (formFields, props) => {
                 );
 
                 const updatingOldEntity = updateEntity(updatedOldEntity);
-                
+
                 return [updatingOldEntity];
             });
         //FIXME: necessary because revision_message is a mandatory field
         // even though we don't actually keep track of changes to caveats/points_of_interest yet
         const updateWithRevisionMessage = updateEntity => entity => updateEntity(assoc(
             entity,
-            'revision_message', 
+            'revision_message',
             'Updated in Getting Started guide.'
         ));
 
@@ -218,9 +218,9 @@ export const tryUpdateGuide = async (formFields, props) => {
                 updateEntity: updateDashboard
             })
             .concat(updateOldEntities({
-                newEntityIds: formFields.most_important_dashboard ? 
+                newEntityIds: formFields.most_important_dashboard ?
                     [formFields.most_important_dashboard.id] : [],
-                oldEntityIds: guide.most_important_dashboard ? 
+                oldEntityIds: guide.most_important_dashboard ?
                     [guide.most_important_dashboard] :
                     [],
                 entities: dashboards,
@@ -239,7 +239,7 @@ export const tryUpdateGuide = async (formFields, props) => {
                 entities: metrics,
                 updateEntity: updateWithRevisionMessage(updateMetric)
             }));
-        
+
         const updatingMetricImportantFields = formFields.important_metrics
             .map(metricFormField => {
                 if (!metricFormField.id || !metricFormField.important_fields) {
@@ -248,17 +248,17 @@ export const tryUpdateGuide = async (formFields, props) => {
                 const importantFieldIds = metricFormField.important_fields
                     .map(field => field.id);
                 const existingImportantFieldIds = guide.metric_important_fields[metricFormField.id];
-                
-                const areFieldIdsIdentitical = existingImportantFieldIds && 
+
+                const areFieldIdsIdentitical = existingImportantFieldIds &&
                     existingImportantFieldIds.length === importantFieldIds.length &&
                     existingImportantFieldIds.every(id => importantFieldIds.includes(id));
                 if (areFieldIdsIdentitical) {
                     return [];
                 }
-                
+
                 return [updateMetricImportantFields(metricFormField.id, importantFieldIds)];
             });
-        
+
         const segmentFields = formFields.important_segments_and_tables
             .filter(field => field.type === 'segment');
 
@@ -299,7 +299,7 @@ export const tryUpdateGuide = async (formFields, props) => {
             guide.contact.name !== formFields.contact.name ?
                 [updateSetting({key: 'getting-started-contact-name', value: formFields.contact.name })] :
                 [];
-        
+
         const updatingContactEmail = guide.contact && formFields.contact &&
             guide.contact.email !== formFields.contact.email ?
                 [updateSetting({key: 'getting-started-contact-email', value: formFields.contact.email })] :
@@ -318,7 +318,7 @@ export const tryUpdateGuide = async (formFields, props) => {
 
         if (updatingData.length > 0) {
             await Promise.all(updatingData);
-            
+
             clearRequestState({statePath: ['reference', 'guide']});
 
             await fetchGuide();
@@ -431,7 +431,7 @@ export const getQuestion = ({dbId, tableId, fieldId, metricId, segmentId, getCou
     return question;
 };
 
-export const getQuestionUrl = getQuestionArgs => `/q#${serializeCardForUrl(getQuestion(getQuestionArgs))}`;
+export const getQuestionUrl = getQuestionArgs => Urls.question(null, getQuestion(getQuestionArgs));
 
 export const isGuideEmpty = ({
     things_to_know,
@@ -446,7 +446,7 @@ export const isGuideEmpty = ({
     most_important_dashboard ? false :
     important_metrics && important_metrics.length !== 0 ? false :
     important_segments && important_segments.length !== 0 ? false :
-    important_tables && important_tables.length !== 0 ? false : 
+    important_tables && important_tables.length !== 0 ? false :
     true;
 
 export const typeToLinkClass = {
diff --git a/frontend/src/metabase/routes.jsx b/frontend/src/metabase/routes.jsx
index 26285e188981bda6c8cadddadaa8053905382c08..1be0d20d54d4ef1eafad19b5edd4864de11cb470 100644
--- a/frontend/src/metabase/routes.jsx
+++ b/frontend/src/metabase/routes.jsx
@@ -151,11 +151,11 @@ export const getRoutes = (store) =>
                 <Route path="/" component={HomepageApp} />
 
                 {/* DASHBOARD */}
-                <Route path="/dash/:dashboardId" component={DashboardApp} />
+                <Route path="/dashboard/:dashboardId" component={DashboardApp} />
 
                 {/* QUERY BUILDER */}
-                <Route path="/card/:cardId" component={QueryBuilder} />
-                <Route path="/q" component={QueryBuilder} />
+                <Route path="/question" component={QueryBuilder} />
+                <Route path="/question/:cardId" component={QueryBuilder} />
 
                 {/* QUESTIONS */}
                 <Route path="/questions">
@@ -262,13 +262,13 @@ export const getRoutes = (store) =>
                 <IndexRedirect to="/_internal/list" />
             </Route>
 
+            {/* DEPRECATED */}
+            <Redirect from="/q" to="/question" />
+            <Redirect from="/card/:cardId" to="/question/:cardId" />
+            <Redirect from="/dash/:dashboardId" to="/dashboard/:dashboardId" />
+
             {/* MISC */}
             <Route path="/unauthorized" component={Unauthorized} />
             <Route path="/*" component={NotFound} />
-
-            {/* LEGACY */}
-            <Redirect from="/card" to="/questions" />
-            <Redirect from="/card/:cardId/:serializedCard" to="/questions/:cardId#:serializedCard" />
-            <Redirect from="/q/:serializedCard" to="/q#:serializedCard" />
         </Route>
     </Route>
diff --git a/frontend/src/metabase/visualizations/components/LegendHeader.jsx b/frontend/src/metabase/visualizations/components/LegendHeader.jsx
index 0d29843b595d4362aef8c5523adc295b86978fbe..3574ac8732835fdb54eeb4788714f09b12e5fef5 100644
--- a/frontend/src/metabase/visualizations/components/LegendHeader.jsx
+++ b/frontend/src/metabase/visualizations/components/LegendHeader.jsx
@@ -5,7 +5,7 @@ import styles from "./Legend.css";
 import Icon from "metabase/components/Icon.jsx";
 import LegendItem from "./LegendItem.jsx";
 
-import Urls from "metabase/lib/urls";
+import * as Urls from "metabase/lib/urls";
 
 import cx from "classnames";
 
@@ -65,7 +65,7 @@ export default class LegendHeader extends Component {
                         key={index}
                         title={s.card.name}
                         description={description}
-                        href={linkToCard && s.card.id && Urls.card(s.card.id)}
+                        href={linkToCard && s.card.id && Urls.question(s.card.id)}
                         color={colors[index % colors.length]}
                         showDot={showDots}
                         showTitle={showTitles}
diff --git a/frontend/src/metabase/visualizations/visualizations/Scalar.jsx b/frontend/src/metabase/visualizations/visualizations/Scalar.jsx
index 33dda37c911ae1e6c651788909cefd9e5ad26151..0109394d22e216b61bba2ae5395b0ce4892f1645 100644
--- a/frontend/src/metabase/visualizations/visualizations/Scalar.jsx
+++ b/frontend/src/metabase/visualizations/visualizations/Scalar.jsx
@@ -8,7 +8,7 @@ import Icon from "metabase/components/Icon.jsx";
 import Tooltip from "metabase/components/Tooltip.jsx";
 import Ellipsified from "metabase/components/Ellipsified.jsx";
 
-import Urls from "metabase/lib/urls";
+import * as Urls from "metabase/lib/urls";
 import { formatValue } from "metabase/lib/formatting";
 import { TYPE } from "metabase/lib/types";
 import { isNumber } from "metabase/lib/schema_metadata";
@@ -195,7 +195,7 @@ export default class Scalar extends Component<*, VisualizationProps, *> {
                 <div className={styles.Title + " flex align-center"}>
                     <Ellipsified tooltip={card.name}>
                         { linkToCard ?
-                          <Link to={Urls.card(card.id)} className="no-decoration fullscreen-normal-text fullscreen-night-text">{settings["card.title"]}</Link>
+                          <Link to={Urls.question(card.id)} className="no-decoration fullscreen-normal-text fullscreen-night-text">{settings["card.title"]}</Link>
                           :
                           <span className="fullscreen-normal-text fullscreen-night-text">{settings["card.title"]}</span>
                         }
diff --git a/frontend/test/e2e/auth/login.spec.js b/frontend/test/e2e/auth/login.spec.js
index d67f0476d4aff0f55317f1b3a5c71743fda8e77e..fe191cebf9c5107762286b3346a5890b20aed86a 100644
--- a/frontend/test/e2e/auth/login.spec.js
+++ b/frontend/test/e2e/auth/login.spec.js
@@ -55,8 +55,8 @@ describeE2E("auth/login", () => {
         });
 
         it("loads the qb", async () => {
-            await driver.get(`${server.host}/q#eyJuYW1lIjpudWxsLCJkYXRhc2V0X3F1ZXJ5Ijp7ImRhdGFiYXNlIjoxLCJ0eXBlIjoibmF0aXZlIiwibmF0aXZlIjp7InF1ZXJ5Ijoic2VsZWN0ICdvaCBoYWkgZ3Vpc2Ug8J-QsScifSwicGFyYW1ldGVycyI6W119LCJkaXNwbGF5Ijoic2NhbGFyIiwidmlzdWFsaXphdGlvbl9zZXR0aW5ncyI6e319`);
-            await waitForUrl(driver, `${server.host}/q#eyJuYW1lIjpudWxsLCJkYXRhc2V0X3F1ZXJ5Ijp7ImRhdGFiYXNlIjoxLCJ0eXBlIjoibmF0aXZlIiwibmF0aXZlIjp7InF1ZXJ5Ijoic2VsZWN0ICdvaCBoYWkgZ3Vpc2Ug8J-QsScifSwicGFyYW1ldGVycyI6W119LCJkaXNwbGF5Ijoic2NhbGFyIiwidmlzdWFsaXphdGlvbl9zZXR0aW5ncyI6e319`);
+            await driver.get(`${server.host}/question#eyJuYW1lIjpudWxsLCJkYXRhc2V0X3F1ZXJ5Ijp7ImRhdGFiYXNlIjoxLCJ0eXBlIjoibmF0aXZlIiwibmF0aXZlIjp7InF1ZXJ5Ijoic2VsZWN0ICdvaCBoYWkgZ3Vpc2Ug8J-QsScifSwicGFyYW1ldGVycyI6W119LCJkaXNwbGF5Ijoic2NhbGFyIiwidmlzdWFsaXphdGlvbl9zZXR0aW5ncyI6e319`);
+            await waitForUrl(driver, `${server.host}/question#eyJuYW1lIjpudWxsLCJkYXRhc2V0X3F1ZXJ5Ijp7ImRhdGFiYXNlIjoxLCJ0eXBlIjoibmF0aXZlIiwibmF0aXZlIjp7InF1ZXJ5Ijoic2VsZWN0ICdvaCBoYWkgZ3Vpc2Ug8J-QsScifSwicGFyYW1ldGVycyI6W119LCJkaXNwbGF5Ijoic2NhbGFyIiwidmlzdWFsaXphdGlvbl9zZXR0aW5ncyI6e319`);
             await screenshot(driver, "screenshots/qb.png");
         });
     });
diff --git a/frontend/test/e2e/query_builder/query_builder.spec.js b/frontend/test/e2e/query_builder/query_builder.spec.js
index 6e4106bd8722b4ed842020f59468a80d715e3e2a..9eb6aa8d69d39a6dc0d9d572ca0f2113db7db8ee 100644
--- a/frontend/test/e2e/query_builder/query_builder.spec.js
+++ b/frontend/test/e2e/query_builder/query_builder.spec.js
@@ -15,7 +15,7 @@ describeE2E("query_builder", () => {
     describe("tables", () => {
         it("should allow users to create pivot tables", async () => {
             // load the query builder and screenshot blank
-            await d.get("/q");
+            await d.get("/question");
             await d.screenshot("screenshots/qb-initial.png");
 
             // pick the orders table (assumes database is already selected, i.e. there's only 1 database)
@@ -56,7 +56,7 @@ describeE2E("query_builder", () => {
 
     describe("charts", () => {
         xit("should allow users to create line charts", async () => {
-            await d.get("/q");
+            await d.get("/question");
 
             // select orders table
             await d.select("#TablePicker .List-item:first-child>a").wait().click();
@@ -106,7 +106,7 @@ describeE2E("query_builder", () => {
 
         xit("should allow users to create bar charts", async () => {
             // load line chart
-            await d.get("/card/2");
+            await d.get("/question/2");
 
             // dismiss saved questions modal
             await d.select(".Modal .Button.Button--primary").wait().click();
diff --git a/frontend/test/e2e/query_builder/tutorial.spec.js b/frontend/test/e2e/query_builder/tutorial.spec.js
index 8b6b31f589a2becb8170a0bac563025c3ad08501..9298adaf0a18211a64e7647e82286bf14ddf5504 100644
--- a/frontend/test/e2e/query_builder/tutorial.spec.js
+++ b/frontend/test/e2e/query_builder/tutorial.spec.js
@@ -24,7 +24,7 @@ describeE2E("tutorial", () => {
         await waitForElementAndClick(driver, ".Modal .Button.Button--primary");
         await waitForElementAndClick(driver, ".Modal .Button.Button--primary");
 
-        await waitForUrl(driver, `${server.host}/q`);
+        await waitForUrl(driver, `${server.host}/question`);
         await waitForElement(driver, ".Modal .Button.Button--primary");
         await screenshot(driver, "screenshots/setup-tutorial-qb.png");
         await waitForElementAndClick(driver, ".Modal .Button.Button--primary");
diff --git a/src/metabase/util/urls.clj b/src/metabase/util/urls.clj
index db1c2948f50289fd71a4222729b61d59259f920c..3c27b5ee2033afecfc12bad23d45101565f0e1e0 100644
--- a/src/metabase/util/urls.clj
+++ b/src/metabase/util/urls.clj
@@ -18,16 +18,16 @@
 (defn dashboard-url
   "Return an appropriate URL for a `Dashboard` with ID.
 
-     (dashboard-url 10) -> \"http://localhost:3000/dash/10\""
+     (dashboard-url 10) -> \"http://localhost:3000/dashboard/10\""
   [^Integer id]
-  (format "%s/dash/%d" (public-settings/site-url) id))
+  (format "%s/dashboard/%d" (public-settings/site-url) id))
 
 (defn card-url
   "Return an appropriate URL for a `Card` with ID.
 
-     (card-url 10) -> \"http://localhost:3000/card/10\""
+     (card-url 10) -> \"http://localhost:3000/question/10\""
   [^Integer id]
-  (format "%s/card/%d" (public-settings/site-url) id))
+  (format "%s/question/%d" (public-settings/site-url) id))
 
 (defn segment-url
   "Return an appropriate URL for a `Segment` with ID.