diff --git a/frontend/src/metabase-types/api/dataset.ts b/frontend/src/metabase-types/api/dataset.ts
index 08bc5955c1d27303a8967733fa81366333bc29a3..ec4fb810c9b88281d5bc09615753bd6e87e4c04c 100644
--- a/frontend/src/metabase-types/api/dataset.ts
+++ b/frontend/src/metabase-types/api/dataset.ts
@@ -1,3 +1,4 @@
+import { DatabaseId } from "./database";
 import { DownloadPermission } from "./permissions";
 
 export interface DatasetColumn {
@@ -6,14 +7,16 @@ export interface DatasetColumn {
   name: string;
 }
 
+export interface DatasetData {
+  rows: any[][];
+  cols: DatasetColumn[];
+  rows_truncated: number;
+  download_perms?: DownloadPermission;
+}
+
 export interface Dataset {
-  data: {
-    rows: any[][];
-    cols: DatasetColumn[];
-    rows_truncated: number;
-    download_perms?: DownloadPermission;
-  };
-  database_id: number;
+  data: DatasetData;
+  database_id: DatabaseId;
   row_count: number;
   running_time: number;
 }
diff --git a/frontend/src/metabase-types/api/mocks/dataset.ts b/frontend/src/metabase-types/api/mocks/dataset.ts
new file mode 100644
index 0000000000000000000000000000000000000000..fabdfbf120a334a4c6a9369b312614385165f523
--- /dev/null
+++ b/frontend/src/metabase-types/api/mocks/dataset.ts
@@ -0,0 +1,18 @@
+import { Dataset, DatasetData } from "metabase-types/api/dataset";
+
+type MockDatasetOpts = Partial<Omit<Dataset, "data">> & {
+  data?: Partial<DatasetData>;
+};
+
+export const createMockDataset = ({ data = {}, ...opts }: MockDatasetOpts) => ({
+  data: {
+    rows: [],
+    cols: [{ display_name: "NAME", source: "native", name: "NAME" }],
+    rows_truncated: 0,
+    ...data,
+  },
+  database_id: 1,
+  row_count: 0,
+  running_time: 1000,
+  ...opts,
+});
diff --git a/frontend/src/metabase-types/api/mocks/index.ts b/frontend/src/metabase-types/api/mocks/index.ts
index 59a16978f931001b037628249706b72d3f375d51..e26e0e465d8751da547af1e13406b95ad72c6906 100644
--- a/frontend/src/metabase-types/api/mocks/index.ts
+++ b/frontend/src/metabase-types/api/mocks/index.ts
@@ -3,6 +3,7 @@ export * from "./automagic-dashboards";
 export * from "./collection";
 export * from "./dashboard";
 export * from "./database";
+export * from "./dataset";
 export * from "./timeline";
 export * from "./settings";
 export * from "./user";
diff --git a/frontend/src/metabase-types/store/index.ts b/frontend/src/metabase-types/store/index.ts
index 8400f5f703ad039d4bdd5c317e5e190ee23e1391..9a4bd5500d0cde49c26b971dd497a45f18de2b7c 100644
--- a/frontend/src/metabase-types/store/index.ts
+++ b/frontend/src/metabase-types/store/index.ts
@@ -3,5 +3,6 @@ export * from "./app";
 export * from "./entities";
 export * from "./forms";
 export * from "./settings";
+export * from "./qb";
 export * from "./setup";
 export * from "./state";
diff --git a/frontend/src/metabase-types/store/mocks/index.ts b/frontend/src/metabase-types/store/mocks/index.ts
index 8400f5f703ad039d4bdd5c317e5e190ee23e1391..01343301932b7d843cfb485b29abf48a74c3de80 100644
--- a/frontend/src/metabase-types/store/mocks/index.ts
+++ b/frontend/src/metabase-types/store/mocks/index.ts
@@ -2,6 +2,7 @@ export * from "./admin";
 export * from "./app";
 export * from "./entities";
 export * from "./forms";
+export * from "./qb";
 export * from "./settings";
 export * from "./setup";
 export * from "./state";
diff --git a/frontend/src/metabase-types/store/mocks/qb.ts b/frontend/src/metabase-types/store/mocks/qb.ts
new file mode 100644
index 0000000000000000000000000000000000000000..656a09562c76ee6f1b86fa1db1a0efcfedc7f970
--- /dev/null
+++ b/frontend/src/metabase-types/store/mocks/qb.ts
@@ -0,0 +1,63 @@
+import {
+  QueryBuilderState,
+  QueryBuilderUIControls,
+} from "metabase-types/store";
+
+export const createMockQueryBuilderUIControlsState = (
+  opts?: Partial<QueryBuilderUIControls>,
+): QueryBuilderUIControls => ({
+  isShowingDataReference: false,
+  isShowingTemplateTagsEditor: false,
+  isShowingNewbModal: false,
+  isEditing: false,
+  isRunning: false,
+  isQueryComplete: false,
+  isShowingSummarySidebar: false,
+  isShowingFilterSidebar: false,
+  isShowingChartTypeSidebar: false,
+  isShowingChartSettingsSidebar: false,
+  isShowingQuestionDetailsSidebar: false,
+  isShowingTimelineSidebar: false,
+  initialChartSetting: null,
+  isPreviewing: true,
+  isShowingRawTable: false,
+  queryBuilderMode: "view",
+  previousQueryBuilderMode: false,
+  snippetCollectionId: null,
+  datasetEditorTab: "query",
+  ...opts,
+});
+
+export const createMockQueryBuilderState = (
+  opts?: Partial<QueryBuilderState>,
+): QueryBuilderState => ({
+  uiControls: createMockQueryBuilderUIControlsState(),
+  loadingControls: {
+    showLoadCompleteFavicon: false,
+    documentTitle: "",
+    timeoutId: "",
+  },
+
+  queryStatus: "complete",
+  queryResults: null,
+  queryStartTime: null,
+  cancelQueryDeferred: null,
+
+  card: null,
+  originalCard: null,
+  lastRunCard: null,
+
+  parameterValues: {},
+
+  zoomedRowObjectId: null,
+  tableForeignKeyReferences: null,
+
+  visibleTimelineIds: [],
+  selectedTimelineEventIds: [],
+
+  metadataDiff: {},
+
+  currentState: null,
+
+  ...opts,
+});
diff --git a/frontend/src/metabase-types/store/mocks/state.ts b/frontend/src/metabase-types/store/mocks/state.ts
index 73746b2db73e25613d93518add0d072a13f01018..5b80c6d644c2c6d826beda278fc5004c52262d59 100644
--- a/frontend/src/metabase-types/store/mocks/state.ts
+++ b/frontend/src/metabase-types/store/mocks/state.ts
@@ -5,6 +5,7 @@ import {
   createMockAppState,
   createMockSettingsState,
   createMockEntitiesState,
+  createMockQueryBuilderState,
   createMockSetupState,
   createMockFormState,
 } from "metabase-types/store/mocks";
@@ -15,6 +16,7 @@ export const createMockState = (opts?: Partial<State>): State => ({
   currentUser: createMockUser(),
   entities: createMockEntitiesState(),
   form: createMockFormState(),
+  qb: createMockQueryBuilderState(),
   settings: createMockSettingsState(),
   setup: createMockSetupState(),
   ...opts,
diff --git a/frontend/src/metabase-types/store/qb.ts b/frontend/src/metabase-types/store/qb.ts
new file mode 100644
index 0000000000000000000000000000000000000000..739d63f3f70130d3c8e9ee914693d05c748f7dfa
--- /dev/null
+++ b/frontend/src/metabase-types/store/qb.ts
@@ -0,0 +1,72 @@
+import { Dataset } from "metabase-types/api/dataset";
+
+import { Card } from "metabase-types/types/Card";
+import { Field } from "metabase-types/types/Field";
+import { ParameterValueOrArray } from "metabase-types/types/Parameter";
+
+export type QueryBuilderMode = "view" | "notebook" | "dataset";
+export type DatasetEditorTab = "query" | "metadata";
+export type QueryBuilderQueryStatus = "idle" | "running" | "complete";
+
+export type ForeignKeyReference = {
+  status: number;
+  value: number;
+};
+
+export interface QueryBuilderUIControls {
+  isShowingDataReference: boolean;
+  isShowingTemplateTagsEditor: boolean;
+  isShowingNewbModal: boolean;
+  isEditing: boolean;
+  isRunning: boolean;
+  isQueryComplete: boolean;
+  isShowingSummarySidebar: boolean;
+  isShowingFilterSidebar: boolean;
+  isShowingChartTypeSidebar: boolean;
+  isShowingChartSettingsSidebar: boolean;
+  isShowingQuestionDetailsSidebar: boolean;
+  isShowingTimelineSidebar: boolean;
+  initialChartSetting: null;
+  isPreviewing: boolean;
+  isShowingRawTable: boolean;
+  queryBuilderMode: QueryBuilderMode;
+  previousQueryBuilderMode: boolean;
+  snippetCollectionId: number | null;
+  datasetEditorTab: DatasetEditorTab;
+}
+
+export interface QueryBuilderLoadingControls {
+  showLoadCompleteFavicon: boolean;
+  documentTitle: string;
+  timeoutId: string;
+}
+
+export interface QueryBuilderState {
+  uiControls: QueryBuilderUIControls;
+
+  loadingControls: QueryBuilderLoadingControls;
+  queryStatus: QueryBuilderQueryStatus;
+  queryResults: Dataset[] | null;
+  queryStartTime: number | null;
+  cancelQueryDeferred: Promise<void> | null;
+
+  card: Card | null;
+  originalCard: Card | null;
+  lastRunCard: Card | null;
+
+  parameterValues: Record<string, ParameterValueOrArray>;
+
+  zoomedRowObjectId: number | string | null;
+  tableForeignKeyReferences: Record<number, ForeignKeyReference> | null;
+
+  visibleTimelineIds: number[];
+  selectedTimelineEventIds: number[];
+
+  metadataDiff: Record<string, Partial<Field>>;
+
+  currentState: {
+    card: Card;
+    cardId?: number;
+    serializedCard: string;
+  } | null;
+}
diff --git a/frontend/src/metabase-types/store/state.ts b/frontend/src/metabase-types/store/state.ts
index 7875873e76239d7dabffc3e765c81ad73353a205..dc079ead7c0b50595450a022b763c66b1b1dd9b7 100644
--- a/frontend/src/metabase-types/store/state.ts
+++ b/frontend/src/metabase-types/store/state.ts
@@ -3,6 +3,7 @@ import { AdminState } from "./admin";
 import { AppState } from "./app";
 import { EntitiesState } from "./entities";
 import { FormState } from "./forms";
+import { QueryBuilderState } from "./qb";
 import { SettingsState } from "./settings";
 import { SetupState } from "./setup";
 
@@ -12,6 +13,7 @@ export interface State {
   currentUser: User;
   entities: EntitiesState;
   form: FormState;
+  qb: QueryBuilderState;
   settings: SettingsState;
   setup: SetupState;
 }