diff --git a/frontend/src/metabase/components/CreateDashboardModal.jsx b/frontend/src/metabase/components/CreateDashboardModal.jsx
index 113e24d99005b8b94ae13ec97781891facd15c06..1f04716e053838f6a08eb875dca2f2f7ff121846 100644
--- a/frontend/src/metabase/components/CreateDashboardModal.jsx
+++ b/frontend/src/metabase/components/CreateDashboardModal.jsx
@@ -34,7 +34,7 @@ export default class CreateDashboardModal extends Component {
 
   onSaved = dashboard => {
     const { onClose, onChangeLocation } = this.props;
-    onChangeLocation(Urls.dashboard(dashboard));
+    onChangeLocation(Urls.dashboard(dashboard, { editMode: true }));
     if (onClose) {
       onClose();
     }
diff --git a/frontend/src/metabase/containers/AddToDashSelectDashModal.jsx b/frontend/src/metabase/containers/AddToDashSelectDashModal.jsx
index 9cbc8730fad71036422c568f20604a9e4b98d615..4c6cf8c0ec0c385af3fe2c627b9546e29a44659d 100644
--- a/frontend/src/metabase/containers/AddToDashSelectDashModal.jsx
+++ b/frontend/src/metabase/containers/AddToDashSelectDashModal.jsx
@@ -35,8 +35,13 @@ export default class AddToDashSelectDashModal extends Component {
   };
 
   navigateToDashboard = dashboard => {
-    this.props.onChangeLocation(
-      Urls.dashboard(dashboard, { addCardWithId: this.props.card.id }),
+    const { card, onChangeLocation } = this.props;
+
+    onChangeLocation(
+      Urls.dashboard(dashboard, {
+        editMode: true,
+        addCardWithId: card.id,
+      }),
     );
   };
 
diff --git a/frontend/src/metabase/dashboard/components/Dashboard/Dashboard.jsx b/frontend/src/metabase/dashboard/components/Dashboard/Dashboard.jsx
index 4539e610e4be779a41c7bbc83e4928e9fa8cba7e..c469fb78b9cb9cbdfdaa40146d6c58a12066858c 100644
--- a/frontend/src/metabase/dashboard/components/Dashboard/Dashboard.jsx
+++ b/frontend/src/metabase/dashboard/components/Dashboard/Dashboard.jsx
@@ -49,7 +49,8 @@ export default class Dashboard extends Component {
     parameterValues: PropTypes.object,
     editingParameter: PropTypes.object,
 
-    addCardOnLoad: PropTypes.func,
+    editingOnLoad: PropTypes.bool,
+    addCardOnLoad: PropTypes.number,
     addCardToDashboard: PropTypes.func.isRequired,
     addParameter: PropTypes.func,
     archiveDashboard: PropTypes.func.isRequired,
@@ -131,6 +132,7 @@ export default class Dashboard extends Component {
 
   async loadDashboard(dashboardId) {
     const {
+      editingOnLoad,
       addCardOnLoad,
       addCardToDashboard,
       fetchDashboard,
@@ -146,10 +148,10 @@ export default class Dashboard extends Component {
 
     try {
       await fetchDashboard(dashboardId, location.query);
-      if (addCardOnLoad != null) {
-        // if we destructure this.props.dashboard, for some reason
-        // if will render dashboards as empty
+      if (editingOnLoad) {
         this.setEditing(this.props.dashboard);
+      }
+      if (addCardOnLoad != null) {
         addCardToDashboard({ dashId: dashboardId, cardId: addCardOnLoad });
       }
     } catch (error) {
diff --git a/frontend/src/metabase/dashboard/containers/DashboardApp.jsx b/frontend/src/metabase/dashboard/containers/DashboardApp.jsx
index ccf05bac6c9712ed450e31fd151359df8ca21f38..641a70530960e95b63aebd90737586b88fa42bc7 100644
--- a/frontend/src/metabase/dashboard/containers/DashboardApp.jsx
+++ b/frontend/src/metabase/dashboard/containers/DashboardApp.jsx
@@ -91,15 +91,25 @@ export default class DashboardApp extends Component {
 
   UNSAFE_componentWillMount() {
     const options = parseHashOptions(window.location.hash);
-    if (options.add) {
-      this.setState({ addCardOnLoad: parseInt(options.add) });
+
+    if (options) {
+      this.setState({
+        editingOnLoad: options.edit,
+        addCardOnLoad: options.add && parseInt(options.add),
+      });
     }
   }
 
   render() {
+    const { editingOnLoad, addCardOnLoad } = this.state;
+
     return (
       <div className="shrink-below-content-size full-height">
-        <Dashboard addCardOnLoad={this.state.addCardOnLoad} {...this.props} />
+        <Dashboard
+          editingOnLoad={editingOnLoad}
+          addCardOnLoad={addCardOnLoad}
+          {...this.props}
+        />
         {/* For rendering modal urls */}
         {this.props.children}
       </div>
diff --git a/frontend/src/metabase/dashboard/hoc/DashboardControls.jsx b/frontend/src/metabase/dashboard/hoc/DashboardControls.jsx
index 886b70fed4e737be662e510a0aa0b290942f9563..05e8b0b3cb8695728008fcf084f40e086c7ea415 100644
--- a/frontend/src/metabase/dashboard/hoc/DashboardControls.jsx
+++ b/frontend/src/metabase/dashboard/hoc/DashboardControls.jsx
@@ -114,10 +114,12 @@ export default (ComposedComponent: React.Class) =>
 
         delete options.night; // DEPRECATED: options.night
 
-        // Delete the "add card to dashboard" parameter if it's present because we don't
-        // want to add the card again on page refresh. The `add` parameter is already handled in
-        // DashboardApp before this method is called.
+        // Delete the "add card to dashboard" and "editing mode" parameters
+        // if they are present because we do not want to add the card again on
+        // page refresh. The parameters are already handled in DashboardApp
+        // before this method is called.
         delete options.add;
+        delete options.edit;
 
         let hash = stringifyHashOptions(options);
         hash = hash ? "#" + hash : "";
diff --git a/frontend/src/metabase/lib/urls.js b/frontend/src/metabase/lib/urls.js
index b563d606bc18949efd6e6ba29e0f11183d077bd2..66125c63a1b47f35a507485d16bae7b11cd7ee0c 100644
--- a/frontend/src/metabase/lib/urls.js
+++ b/frontend/src/metabase/lib/urls.js
@@ -3,6 +3,7 @@ import { serializeCardForUrl } from "metabase/lib/card";
 import { SAVED_QUESTIONS_VIRTUAL_DB_ID } from "metabase/lib/saved-questions";
 import MetabaseSettings from "metabase/lib/settings";
 import Question from "metabase-lib/lib/Question";
+import { stringifyHashOptions } from "metabase/lib/browser";
 
 function appendSlug(path, slug) {
   return slug ? `${path}-${slug}` : path;
@@ -97,13 +98,15 @@ export function newQuestion({ mode, ...options } = {}) {
   }
 }
 
-export function dashboard(dashboard, { addCardWithId } = {}) {
+export function dashboard(dashboard, { addCardWithId, editMode } = {}) {
+  const options = {
+    ...(addCardWithId ? { add: addCardWithId } : {}),
+    ...(editMode ? { edit: editMode } : {}),
+  };
+
   const path = appendSlug(dashboard.id, slugg(dashboard.name));
-  return addCardWithId != null
-    ? // NOTE: no-color-literals rule thinks #add is a color, oops
-      // eslint-disable-next-line no-color-literals
-      `/dashboard/${path}#add=${addCardWithId}`
-    : `/dashboard/${path}`;
+  const hash = stringifyHashOptions(options);
+  return hash ? `/dashboard/${path}#${hash}` : `/dashboard/${path}`;
 }
 
 function prepareModel(item) {
diff --git a/frontend/test/metabase/scenarios/dashboard/dashboard.cy.spec.js b/frontend/test/metabase/scenarios/dashboard/dashboard.cy.spec.js
index a515640646ea28d0ac72faed261c1f795cb33be6..5f73c986482c54b5cde594c1630630f0e0cd5dfc 100644
--- a/frontend/test/metabase/scenarios/dashboard/dashboard.cy.spec.js
+++ b/frontend/test/metabase/scenarios/dashboard/dashboard.cy.spec.js
@@ -32,6 +32,7 @@ describe("scenarios > dashboard", () => {
     cy.findByLabelText("Description").type("Desc");
     cy.findByText("Create").click();
     cy.findByText("This dashboard is looking empty.");
+    cy.findByText("You're editing this dashboard.");
 
     // See it as a listed dashboard
     cy.visit("/collection/root?type=dashboard");