diff --git a/frontend/interfaces/underscore.js b/frontend/interfaces/underscore.js
index 8b3511ac04ba9054b193152dff50dbb5dc1a3333..4c9edd5d120f3bcb168833766c6b521c0803d665 100644
--- a/frontend/interfaces/underscore.js
+++ b/frontend/interfaces/underscore.js
@@ -21,6 +21,11 @@ declare module "underscore" {
 
   declare function map<T, U>(a: T[], iteratee: (val: T, n?: number)=>U): U[];
   declare function map<K, T, U>(a: {[key:K]: T}, iteratee: (val: T, k?: K)=>U): U[];
+  declare function mapObject(
+        object: Object,
+        iteratee: (val: any, key: string) => Object,
+        context?: mixed
+  ): Object;
 
   declare function object<T>(a: Array<[string, T]>): {[key:string]: T};
 
diff --git a/frontend/src/metabase-lib/lib/metadata/Metadata.js b/frontend/src/metabase-lib/lib/metadata/Metadata.js
index 5442aafd20ee5003da201a58dbd676ed2d606026..c4ccb35410635c8f582584c180d8cb1d9d52d7c7 100644
--- a/frontend/src/metabase-lib/lib/metadata/Metadata.js
+++ b/frontend/src/metabase-lib/lib/metadata/Metadata.js
@@ -38,4 +38,9 @@ export default class Metadata extends Base {
         // $FlowFixMe
         return (Object.values(this.metrics): Metric[]);
     }
+
+    segmentsList(): Metric[] {
+        // $FlowFixMe
+        return (Object.values(this.segments): Segment[]);
+    }
 }
diff --git a/frontend/src/metabase-lib/lib/metadata/Metric.js b/frontend/src/metabase-lib/lib/metadata/Metric.js
index 10b69a7fd99808139b476657f20049aa119b0318..915b6c27dc656ca01e680b3193da32e60460f345 100644
--- a/frontend/src/metabase-lib/lib/metadata/Metric.js
+++ b/frontend/src/metabase-lib/lib/metadata/Metric.js
@@ -18,4 +18,8 @@ export default class Metric extends Base {
     aggregationClause(): Aggregation {
         return ["METRIC", this.id];
     }
+
+    isActive(): boolean {
+        return !!this.is_active;
+    }
 }
diff --git a/frontend/src/metabase-lib/lib/metadata/Segment.js b/frontend/src/metabase-lib/lib/metadata/Segment.js
index 26f3effae4fa05e6321dc9eb4cb989c5dee2771c..9c1bfad6c6b2697b41f8728584ca7d850f28e9de 100644
--- a/frontend/src/metabase-lib/lib/metadata/Segment.js
+++ b/frontend/src/metabase-lib/lib/metadata/Segment.js
@@ -1,9 +1,9 @@
 /* @flow weak */
 
 import Base from "./Base";
-import Question from "../Question";
 import Database from "./Database";
 import Table from "./Table";
+import type { FilterClause } from "metabase/meta/types/Query";
 
 /**
  * Wrapper class for a segment. Belongs to a {@link Database} and possibly a {@link Table}
@@ -15,8 +15,11 @@ export default class Segment extends Base {
     database: Database;
     table: Table;
 
-    newQuestion(): Question {
-        // $FlowFixMe
-        return new Question();
+    filterClause(): FilterClause {
+        return ["SEGMENT", this.id];
+    }
+
+    isActive(): boolean {
+        return !!this.is_active;
     }
 }
diff --git a/frontend/src/metabase-lib/lib/queries/NativeQuery.js b/frontend/src/metabase-lib/lib/queries/NativeQuery.js
index 7beee3058bfbe1024242ec068f196ba4d6b89691..19690b60e46e989a7544f45b5a4c7cfe41b2232d 100644
--- a/frontend/src/metabase-lib/lib/queries/NativeQuery.js
+++ b/frontend/src/metabase-lib/lib/queries/NativeQuery.js
@@ -16,7 +16,7 @@ import {
     getEngineNativeRequiresTable
 } from "metabase/lib/engine";
 
-import { chain, getIn, assocIn } from "icepick";
+import { chain, assoc, getIn, assocIn } from "icepick";
 import _ from "underscore";
 
 import type {
@@ -93,6 +93,21 @@ export default class NativeQuery extends AtomicQuery {
 
     /* Methods unique to this query type */
 
+    /**
+     * @returns a new query with the provided Database set.
+     */
+    setDatabase(database: Database): NativeQuery {
+        if (database.id !== this.databaseId()) {
+            // TODO: this should reset the rest of the query?
+            return new NativeQuery(
+                this._originalQuestion,
+                assoc(this.datasetQuery(), "database", database.id)
+            );
+        } else {
+            return this;
+        }
+    }
+
     hasWritePermission(): boolean {
         const database = this.database();
         return database != null && database.native_permissions === "write";
diff --git a/frontend/src/metabase/components/SearchHeader.css b/frontend/src/metabase/components/SearchHeader.css
index f053bae23692cbfa6121066151dac76d9380ad05..95e1e4440d4a04bbb9627e048f6dfe8ff56cf40d 100644
--- a/frontend/src/metabase/components/SearchHeader.css
+++ b/frontend/src/metabase/components/SearchHeader.css
@@ -1,9 +1,5 @@
 @import '../questions/Questions.css';
 
-:local(.searchHeader) {
-    composes: flex align-center from "style";
-}
-
 :local(.searchIcon) {
     color: var(--muted-color);
 }
@@ -12,6 +8,7 @@
     composes: borderless from "style";
     color: var(--title-color);
     font-size: 20px;
+    width: 100%;
 }
 :local(.searchBox)::-webkit-input-placeholder {
     color: var(--subtitle-color);
diff --git a/frontend/src/metabase/components/SearchHeader.jsx b/frontend/src/metabase/components/SearchHeader.jsx
index ccd13419418a580b8f348d047bc75520414686e1..f087cff31b2649657bf62bb7bfd82184dce61fcf 100644
--- a/frontend/src/metabase/components/SearchHeader.jsx
+++ b/frontend/src/metabase/components/SearchHeader.jsx
@@ -2,13 +2,11 @@
 import React from "react";
 import PropTypes from "prop-types";
 import S from "./SearchHeader.css";
-
 import Icon from "metabase/components/Icon.jsx";
-
 import cx from "classnames";
 
-const SearchHeader = ({ searchText, setSearchText }) =>
-    <div className={S.searchHeader}>
+const SearchHeader = ({ searchText, setSearchText, autoFocus, inputRef, resetSearchText }) =>
+    <div className="flex align-center">
         <Icon className={S.searchIcon} name="search" size={18} />
         <input
             className={cx("input bg-transparent", S.searchBox)}
@@ -16,12 +14,25 @@ const SearchHeader = ({ searchText, setSearchText }) =>
             placeholder="Filter this list..."
             value={searchText}
             onChange={(e) => setSearchText(e.target.value)}
+            autoFocus={!!autoFocus}
+            ref={inputRef || (() => {})}
         />
+        { resetSearchText && searchText !== "" &&
+            <Icon
+                name="close"
+                className="cursor-pointer text-grey-2"
+                size={18}
+                onClick={resetSearchText}
+            />
+        }
     </div>
 
 SearchHeader.propTypes = {
     searchText: PropTypes.string.isRequired,
     setSearchText: PropTypes.func.isRequired,
+    autoFocus: PropTypes.bool,
+    inputRef: PropTypes.func,
+    resetSearchText: PropTypes.func
 };
 
 export default SearchHeader;
diff --git a/frontend/src/metabase/containers/EntitySearch.jsx b/frontend/src/metabase/containers/EntitySearch.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..5fb33bdfaa0042b5466bb547606fe901addf798a
--- /dev/null
+++ b/frontend/src/metabase/containers/EntitySearch.jsx
@@ -0,0 +1,479 @@
+import React, { Component } from 'react'
+import { connect } from 'react-redux'
+import { push } from "react-router-redux";
+import _ from "underscore";
+import cx from "classnames";
+
+import SearchHeader from "metabase/components/SearchHeader";
+
+import { caseInsensitiveSearch } from "metabase/lib/string";
+import Icon from "metabase/components/Icon";
+import EmptyState from "metabase/components/EmptyState";
+import { Link } from "react-router";
+import { KEYCODE_DOWN, KEYCODE_ENTER, KEYCODE_UP } from "metabase/lib/keyboard";
+
+const PAGE_SIZE = 10
+
+const SEARCH_GROUPINGS = [
+    {
+        name: "Name",
+        icon: null,
+        // Name grouping is a no-op grouping so always put all results to same group with identifier `0`
+        groupBy: () => 0,
+        // Setting name to null hides the group header in SearchResultsGroup component
+        getGroupName: () => null
+    },
+    {
+        name: "Table",
+        icon: "table2",
+        groupBy: (entity) => entity.table.id,
+        getGroupName: (entity) => entity.table.display_name
+    },
+    {
+        name: "Database",
+        icon: "database",
+        groupBy: (entity) => entity.table.db.id,
+        getGroupName: (entity) => entity.table.db.name
+    },
+    {
+        name: "Creator",
+        icon: "mine",
+        groupBy: (entity) => entity.creator.id,
+        getGroupName: (entity) => entity.creator.common_name
+    },
+]
+const DEFAULT_SEARCH_GROUPING = SEARCH_GROUPINGS[0]
+
+type Props = {
+    title: string,
+    // Sorted list of entities like segments or metrics
+    entities: any[],
+    getUrlForEntity: (any) => void
+}
+
+export default class EntitySearch extends Component {
+    searchHeaderInput: ?HTMLButtonElement
+    props: Props
+
+    constructor(props) {
+        super(props);
+        this.state = {
+            filteredEntities: props.entities,
+            currentGrouping: DEFAULT_SEARCH_GROUPING,
+            searchText: ""
+        };
+    }
+
+    componentWillReceiveProps = (nextProps) => {
+        this.applyFiltersForEntities(nextProps.entities)
+    }
+
+    setSearchText = (searchText) => {
+        this.setState({ searchText }, this.applyFiltersAfterFilterChange)
+    }
+
+    resetSearchText = () => {
+        this.setSearchText("")
+        this.searchHeaderInput.focus()
+    }
+
+    applyFiltersAfterFilterChange = () => this.applyFiltersForEntities(this.props.entities)
+
+    applyFiltersForEntities = (entities) => {
+        const { searchText } = this.state;
+
+        if (searchText !== "") {
+            const filteredEntities = entities.filter(({ name, description }) =>
+                caseInsensitiveSearch(name, searchText)
+            )
+
+            this.setState({ filteredEntities })
+        }
+        else {
+            this.setState({ filteredEntities: entities })
+        }
+    }
+
+    setGrouping = (grouping) => {
+        this.setState({ currentGrouping: grouping })
+        this.searchHeaderInput.focus()
+    }
+
+    // Returns an array of groups based on current grouping. The groups are sorted by their name.
+    // Entities inside each group aren't separately sorted as EntitySearch expects that the `entities`
+    // is already in the desired order.
+    getGroups = () => {
+        const { currentGrouping, filteredEntities } = this.state;
+
+        return _.chain(filteredEntities)
+            .groupBy(currentGrouping.groupBy)
+            .pairs()
+            .map(([groupId, entitiesInGroup]) => ({
+                groupName: currentGrouping.getGroupName(entitiesInGroup[0]),
+                entitiesInGroup
+            }))
+            .sortBy(({ groupName }) => groupName !== null && groupName.toLowerCase())
+            .value()
+    }
+
+    render() {
+        const { title, getUrlForEntity } = this.props;
+        const { searchText, currentGrouping, filteredEntities } = this.state;
+
+        const hasUngroupedResults = !currentGrouping.icon && filteredEntities.length > 0
+
+        return (
+            <div className="bg-slate-extra-light full Entity-search">
+                <div className="wrapper wrapper--small pt4 pb4">
+                    <div className="flex mb4 align-center" style={{ height: "50px" }}>
+                        <Icon
+                            className="Entity-search-back-button shadowed cursor-pointer text-grey-4 mr2 flex align-center circle p2 bg-white transition-background transition-color"
+                            style={{
+                                border: "1px solid #DCE1E4",
+                                boxShadow: "0 2px 4px 0 #DCE1E4"
+                            }}
+                            name="backArrow"
+                            onClick={ () => window.history.back() }
+                        />
+                        <div className="text-centered flex-full">
+                            <h2>{title}</h2>
+                        </div>
+                    </div>
+                    <div>
+                        <SearchGroupingOptions
+                            currentGrouping={currentGrouping}
+                            setGrouping={this.setGrouping}
+                        />
+                        <div
+                            className={cx("bg-white bordered", { "rounded": !hasUngroupedResults }, { "rounded-top": hasUngroupedResults })}
+                            style={{ padding: "5px 15px" }}
+                        >
+                            <SearchHeader
+                                searchText={searchText}
+                                setSearchText={this.setSearchText}
+                                autoFocus
+                                inputRef={el => this.searchHeaderInput = el}
+                                resetSearchText={this.resetSearchText}
+                            />
+                        </div>
+                        { filteredEntities.length > 0 &&
+                            <GroupedSearchResultsList
+                                groupingIcon={currentGrouping.icon}
+                                groups={this.getGroups()}
+                                getUrlForEntity={getUrlForEntity}
+                            />
+                        }
+                        { filteredEntities.length === 0 &&
+                            <div className="mt4">
+                                <EmptyState
+                                    message={
+                                        <div className="mt4">
+                                            <h3 className="text-grey-5">No results found</h3>
+                                            <p className="text-grey-4">Try adjusting your filter to find what you’re
+                                                looking for.</p>
+                                        </div>
+                                    }
+                                    image="/app/img/empty_question"
+                                    imageHeight="213px"
+                                    imageClassName="mln2"
+                                    smallDescription
+                                />
+                            </div>
+                        }
+                    </div>
+                </div>
+            </div>
+        )
+    }
+}
+
+export const SearchGroupingOptions = ({ currentGrouping, setGrouping }) =>
+    <div className="Entity-search-grouping-options">
+        <h3 className="mb3">View by</h3>
+        <ul>
+            { SEARCH_GROUPINGS.map((groupingOption) =>
+                <SearchGroupingOption
+                    key={groupingOption.name}
+                    grouping={groupingOption}
+                    active={currentGrouping === groupingOption}
+                    setGrouping={setGrouping}
+                />
+            )}
+        </ul>
+    </div>
+
+export class SearchGroupingOption extends Component {
+    props: {
+        grouping: any,
+        active: boolean,
+        setGrouping: (any) => boolean
+    }
+
+    onSetGrouping = () => {
+        this.props.setGrouping(this.props.grouping)
+    }
+
+    render() {
+        const { grouping, active } = this.props;
+
+        return (
+            <li
+                className={cx(
+                    "my2 cursor-pointer text-uppercase text-small text-green-saturated-hover",
+                    {"text-grey-4": !active},
+                    {"text-green-saturated": active}
+                )}
+                onClick={this.onSetGrouping}
+            >
+                {grouping.name}
+            </li>
+        )
+    }
+}
+
+export class GroupedSearchResultsList extends Component {
+    props: {
+        groupingIcon: string,
+        groups: any,
+        getUrlForEntity: (any) => void,
+    }
+
+    state = {
+        highlightedItemIndex: 0,
+        // `currentPages` is used as a map-like structure for storing the current pagination page for each group.
+        // If a given group has no value in currentPages, then it is assumed to be in the first page (`0`).
+        currentPages: {}
+    }
+
+    componentDidMount() {
+        window.addEventListener("keydown", this.onKeyDown, true);
+    }
+
+    componentWillUnmount() {
+        window.removeEventListener("keydown", this.onKeyDown, true);
+    }
+
+    componentWillReceiveProps() {
+        this.setState({
+            highlightedItemIndex: 0,
+            currentPages: {}
+        })
+    }
+
+    /**
+     * Returns the count of currently visible entities for each result group.
+     */
+    getVisibleEntityCounts() {
+        const { groups } = this.props;
+        const { currentPages } = this.state
+        return groups.map((group, index) =>
+            Math.min(PAGE_SIZE, group.entitiesInGroup.length - (currentPages[index] || 0) * PAGE_SIZE)
+        )
+    }
+
+    onKeyDown = (e) => {
+        const { highlightedItemIndex } = this.state
+
+        if (e.keyCode === KEYCODE_UP) {
+            this.setState({ highlightedItemIndex: Math.max(0, highlightedItemIndex - 1) })
+            e.preventDefault();
+        } else if (e.keyCode === KEYCODE_DOWN) {
+            const visibleEntityCount = this.getVisibleEntityCounts().reduce((a, b) => a + b)
+            this.setState({ highlightedItemIndex: Math.min(highlightedItemIndex + 1, visibleEntityCount - 1) })
+            e.preventDefault();
+        }
+    }
+
+    /**
+     * Returns `{ groupIndex, itemIndex }` which describes that which item in which group is currently highlighted.
+     * Calculates it based on current visible entities (as pagination affects which entities are visible on given time)
+     * and the current highlight index that is modified with up and down arrow keys
+     */
+    getHighlightPosition() {
+        const { highlightedItemIndex } = this.state
+        const visibleEntityCounts = this.getVisibleEntityCounts()
+
+        let entitiesInPreviousGroups = 0
+        for (let groupIndex = 0; groupIndex < visibleEntityCounts.length; groupIndex++) {
+            const visibleEntityCount = visibleEntityCounts[groupIndex]
+            const indexInCurrentGroup = highlightedItemIndex - entitiesInPreviousGroups
+
+            if (indexInCurrentGroup <= visibleEntityCount - 1) {
+                return { groupIndex, itemIndex: indexInCurrentGroup }
+            }
+
+           entitiesInPreviousGroups += visibleEntityCount
+        }
+    }
+
+    /**
+     * Sets the current pagination page by finding the group that match the `entities` list of entities
+     */
+    setCurrentPage = (entities, page) => {
+        const { groups } = this.props;
+        const { currentPages } = this.state;
+        const groupIndex = groups.findIndex((group) => group.entitiesInGroup === entities)
+
+        this.setState({
+            highlightedItemIndex: 0,
+            currentPages: {
+                ...currentPages,
+                [groupIndex]: page
+            }
+        })
+    }
+
+    render() {
+        const { groupingIcon, groups, getUrlForEntity } = this.props;
+        const { currentPages } = this.state;
+
+        const highlightPosition = this.getHighlightPosition(groups)
+
+        return (
+            <div className="full">
+                {groups.map(({ groupName, entitiesInGroup }, groupIndex) =>
+                    <SearchResultsGroup
+                        key={groupIndex}
+                        groupName={groupName}
+                        groupIcon={groupingIcon}
+                        entities={entitiesInGroup}
+                        getUrlForEntity={getUrlForEntity}
+                        highlightItemAtIndex={groupIndex === highlightPosition.groupIndex ? highlightPosition.itemIndex : undefined}
+                        currentPage={currentPages[groupIndex] || 0}
+                        setCurrentPage={this.setCurrentPage}
+                    />
+                )}
+            </div>
+        )
+    }
+}
+
+export const SearchResultsGroup = ({ groupName, groupIcon, entities, getUrlForEntity, highlightItemAtIndex, currentPage, setCurrentPage }) =>
+    <div>
+        { groupName !== null &&
+            <div className="flex align-center bg-slate-almost-extra-light bordered mt3 px3 py2">
+                <Icon className="mr1" style={{color: "#BCC5CA"}} name={groupIcon}/>
+                <h4>{groupName}</h4>
+            </div>
+        }
+        <SearchResultsList
+            entities={entities}
+            getUrlForEntity={getUrlForEntity}
+            highlightItemAtIndex={highlightItemAtIndex}
+            currentPage={currentPage}
+            setCurrentPage={setCurrentPage}
+        />
+    </div>
+
+
+class SearchResultsList extends Component {
+    props: {
+        entities: any[],
+        getUrlForEntity: () => void,
+        highlightItemAtIndex?: number,
+        currentPage: number,
+        setCurrentPage: (entities, number) => void
+    }
+
+    state = {
+        page: 0
+    }
+
+    getPaginationSection = (start, end, entityCount) => {
+        const { entities, currentPage, setCurrentPage } = this.props
+
+        const currentEntitiesText = start === end ? `${start + 1}` : `${start + 1}-${end + 1}`
+        const isInBeginning = start === 0
+        const isInEnd = end + 1 >= entityCount
+
+        return (
+            <li className="py1 px3 flex justify-end align-center">
+                <span className="text-bold">{ currentEntitiesText }</span>&nbsp;of&nbsp;<span
+                className="text-bold">{entityCount}</span>
+                <span
+                    className={cx(
+                        "mx1 flex align-center justify-center rounded",
+                        { "cursor-pointer bg-grey-2 text-white": !isInBeginning },
+                        { "bg-grey-0 text-grey-1": isInBeginning }
+                    )}
+                    style={{width: "22px", height: "22px"}}
+                    onClick={() => !isInBeginning && setCurrentPage(entities, currentPage - 1)}>
+                    <Icon name="chevronleft" size={14}/>
+                </span>
+                <span
+                    className={cx(
+                        "flex align-center justify-center rounded",
+                        { "cursor-pointer bg-grey-2 text-white": !isInEnd },
+                        { "bg-grey-0 text-grey-2": isInEnd }
+                    )}
+                    style={{width: "22px", height: "22px"}}
+                    onClick={() => !isInEnd && setCurrentPage(entities, currentPage + 1)}>
+                        <Icon name="chevronright" size={14}/>
+                </span>
+            </li>
+        )
+    }
+    render() {
+        const { currentPage, entities, getUrlForEntity, highlightItemAtIndex } = this.props
+
+        const showPagination = PAGE_SIZE < entities.length
+
+        let start = PAGE_SIZE * currentPage;
+        let end = Math.min(entities.length - 1, PAGE_SIZE * (currentPage + 1) - 1);
+        const entityCount = entities.length;
+
+        const entitiesInCurrentPage = entities.slice(start, end + 1)
+
+        return (
+            <ol className="Entity-search-results-list flex-full bg-white border-left border-right border-bottom rounded-bottom">
+                {entitiesInCurrentPage.map((entity, index) =>
+                    <SearchResultListItem key={index} entity={entity} getUrlForEntity={getUrlForEntity} highlight={ highlightItemAtIndex === index } />
+                )}
+                {showPagination && this.getPaginationSection(start, end, entityCount)}
+            </ol>
+        )
+    }
+}
+
+@connect(null, { onChangeLocation: push })
+export class SearchResultListItem extends Component {
+    props: {
+        entity: any,
+        getUrlForEntity: (any) => void,
+        highlight?: boolean,
+
+        onChangeLocation: (string) => void
+    }
+
+    componentDidMount() {
+        window.addEventListener("keydown", this.onKeyDown, true);
+    }
+    componentWillUnmount() {
+        window.removeEventListener("keydown", this.onKeyDown, true);
+    }
+    /**
+     * If the current search result entity is highlighted via arrow keys, then we want to
+     * let the press of Enter to navigate to that entity
+     */
+    onKeyDown = (e) => {
+        const { highlight, entity, getUrlForEntity, onChangeLocation } = this.props;
+        if (highlight && e.keyCode === KEYCODE_ENTER) {
+            onChangeLocation(getUrlForEntity(entity))
+        }
+    }
+
+    render() {
+        const { entity, highlight, getUrlForEntity } = this.props;
+
+        return (
+            <li>
+                <Link
+                className={cx("no-decoration flex py2 px3 cursor-pointer bg-slate-extra-light-hover border-bottom", { "bg-grey-0": highlight })}
+                to={getUrlForEntity(entity)}
+                >
+                    <h4 className="text-brand flex-full mr1"> { entity.name } </h4>
+                </Link>
+            </li>
+        )
+    }
+}
diff --git a/frontend/src/metabase/css/containers/entity_search.css b/frontend/src/metabase/css/containers/entity_search.css
new file mode 100644
index 0000000000000000000000000000000000000000..ac8bf588aae4d1ddd87d61ec22b919bd81281230
--- /dev/null
+++ b/frontend/src/metabase/css/containers/entity_search.css
@@ -0,0 +1,34 @@
+@media screen and (--breakpoint-min-md) {
+    .Entity-search-back-button {
+        position: absolute;
+        margin-left: -150px;
+    }
+
+    .Entity-search-grouping-options {
+        position: absolute;
+        margin-left: -150px;
+        margin-top: 22px;
+    }
+}
+
+
+@media screen and (--breakpoint-max-md) {
+    .Entity-search-grouping-options {
+        display: flex;
+        align-items: center;
+    }
+    .Entity-search-grouping-options > h3 {
+        margin-bottom: 0;
+        margin-right: 20px;
+    }
+    .Entity-search-grouping-options > ul {
+        display: flex;
+    }
+    .Entity-search-grouping-options > ul > li {
+        margin-right: 10px;
+    }
+}
+
+.Entity-search input {
+    width: 100%;
+}
\ No newline at end of file
diff --git a/frontend/src/metabase/css/core/colors.css b/frontend/src/metabase/css/core/colors.css
index b9087cd8cc26ea6650d10a4c1220c32971632efc..9e8a624b5498fae7f50116517dc8032d1945397d 100644
--- a/frontend/src/metabase/css/core/colors.css
+++ b/frontend/src/metabase/css/core/colors.css
@@ -22,10 +22,12 @@
   --orange-color: #F9A354;
   --purple-color: #A989C5;
   --green-color: #9CC177;
+  --green-saturated-color: #84BB4C;
   --dark-color: #4C545B;
   --error-color: #EF8C8C;
   --slate-color: #9BA5B1;
   --slate-light-color: #DFE8EA;
+  --slate-almost-extra-light-color: #EDF2F5;
   --slate-extra-light-color: #F9FBFC;
 }
 
@@ -106,6 +108,11 @@
     color: var(--green-color);
 }
 
+.text-green-saturated,
+.text-green-saturated-hover:hover {
+    color: var(--green-saturated-color);
+}
+
 .text-orange,
 .text-orange-hover:hover {
     color: var(--orange-color);
@@ -148,7 +155,9 @@
 
 .bg-slate { background-color: var(--slate-color); }
 .bg-slate-light { background-color: var(--slate-light-color); }
+.bg-slate-almost-extra-light { background-color: var(--slate-almost-extra-light-color);}
 .bg-slate-extra-light { background-color: var(--slate-extra-light-color); }
+.bg-slate-extra-light-hover:hover { background-color: var(--slate-extra-light-color); }
 
 .text-dark, :local(.text-dark) {
     color: var(--dark-color);
diff --git a/frontend/src/metabase/css/core/grid.css b/frontend/src/metabase/css/core/grid.css
index 7bcfcaf96f764161f2bf5a7727f358fbd6506bc7..dea70d422fdff7506ac610ce7d390aaed2dd6bc2 100644
--- a/frontend/src/metabase/css/core/grid.css
+++ b/frontend/src/metabase/css/core/grid.css
@@ -239,6 +239,9 @@
   .large-Grid--guttersXXl > .Grid-cell {
     padding: 5em 0 0 5em;
   }
+  .large-Grid--normal > .Grid-cell {
+    flex: 1;
+  }
 }
 
 .Grid-cell.Cell--1of3 {
diff --git a/frontend/src/metabase/css/core/layout.css b/frontend/src/metabase/css/core/layout.css
index 1636716bf5f9e41b0d0ed84ccd01376956ff450e..d5a68a934806232f4d24d661f872086ddbbcdfd4 100644
--- a/frontend/src/metabase/css/core/layout.css
+++ b/frontend/src/metabase/css/core/layout.css
@@ -34,6 +34,10 @@
 .block,
 :local(.block)        { display: block; }
 
+@media screen and (--breakpoint-min-lg) {
+.lg-block { display: block; }
+}
+
 .inline,
 :local(.inline)       { display: inline; }
 
@@ -76,6 +80,18 @@
     }
 }
 
+@media screen and (--breakpoint-min-lg) {
+  .wrapper.lg-wrapper--trim {
+        max-width: var(--lg-width);
+  }
+}
+
+@media screen and (--breakpoint-min-xl) {
+  .wrapper.lg-wrapper--trim {
+        max-width: var(--xl-width);
+  }
+}
+
 /* fully fit the parent element - use as a base for app-y pages like QB or settings */
 .spread, :local(.spread) {
   position: absolute;
diff --git a/frontend/src/metabase/css/core/rounded.css b/frontend/src/metabase/css/core/rounded.css
index 3d27f218a99693f0b7ac25c85682c36f9b647dff..7a49794c7255b4f326248535dd5fa1fc15b7c781 100644
--- a/frontend/src/metabase/css/core/rounded.css
+++ b/frontend/src/metabase/css/core/rounded.css
@@ -6,6 +6,10 @@
   border-radius: var(--default-border-radius);
 }
 
+.rounded-med, :local(.rounded-med) {
+  border-radius: var(--med-border-radius);
+}
+
 .rounded-top {
   border-top-left-radius:  var(--default-border-radius);
   border-top-right-radius: var(--default-border-radius);
diff --git a/frontend/src/metabase/css/index.css b/frontend/src/metabase/css/index.css
index 95ee56f34e5a58cfb35ebc7acac7d39ba1e5011a..af07ba3c870211f867dedc021fda7cc648deb92b 100644
--- a/frontend/src/metabase/css/index.css
+++ b/frontend/src/metabase/css/index.css
@@ -12,6 +12,8 @@
 @import './components/select.css';
 @import './components/table.css';
 
+@import './containers/entity_search.css';
+
 @import './admin.css';
 @import './card.css';
 @import './dashboard.css';
diff --git a/frontend/src/metabase/lib/redux.js b/frontend/src/metabase/lib/redux.js
index 81d58aa3ca77f0ba9c8ba73ab71e58c12c0b2836..18ed1a8b088419dc7ec2cd511b5f869127761921 100644
--- a/frontend/src/metabase/lib/redux.js
+++ b/frontend/src/metabase/lib/redux.js
@@ -65,11 +65,15 @@ export const fetchData = async ({
     const existingData = getIn(getState(), existingStatePath);
     const statePath = requestStatePath.concat(['fetch']);
     try {
-        const requestState = getIn(getState(), ["requests", ...statePath]);
+        const requestState = getIn(getState(), ["requests", "states", ...statePath]);
         if (!requestState || requestState.error || reload) {
             dispatch(setRequestState({ statePath, state: "LOADING" }));
             const data = await getData();
-            dispatch(setRequestState({ statePath, state: "LOADED" }));
+
+            // NOTE Atte Keinänen 8/23/17:
+            // Dispatch `setRequestState` after clearing the call stack because we want to the actual data to be updated
+            // before we notify components via `state.requests.fetches` that fetching the data is completed
+            setTimeout(() => dispatch(setRequestState({ statePath, state: "LOADED" })), 0);
 
             return data;
         }
diff --git a/frontend/src/metabase/new_query/components/NewQueryOption.jsx b/frontend/src/metabase/new_query/components/NewQueryOption.jsx
index 41931adcbf60f44436dbb46bbc07e4b618311bb5..cc1503208943485327ebba2c5521f91bf407bc93 100644
--- a/frontend/src/metabase/new_query/components/NewQueryOption.jsx
+++ b/frontend/src/metabase/new_query/components/NewQueryOption.jsx
@@ -1,12 +1,13 @@
 import React, { Component } from "react";
 import cx from "classnames";
+import { Link } from "react-router";
 
 export default class NewQueryOption extends Component {
    props: {
        image: string,
        title: string,
        description: string,
-       onClick: () => void
+       to: string
    };
 
    state = {
@@ -14,19 +15,20 @@ export default class NewQueryOption extends Component {
    };
 
    render() {
-       const { width, image, title, description, onClick } = this.props;
+       const { width, image, title, description, to } = this.props;
        const { hover } = this.state;
 
        return (
-           <div
-               className="bg-white p3 align-center bordered rounded cursor-pointer transition-all text-centered text-brand-light"
+           <Link
+               className="block no-decoration bg-white px3 pt4 align-center bordered rounded cursor-pointer transition-all text-centered"
                style={{
+                   boxSizing: "border-box",
                    boxShadow: hover ? "0 3px 8px 0 rgba(220,220,220,0.50)" : "0 1px 3px 0 rgba(220,220,220,0.50)",
-                   height: "310px"
+                   height: 340
                }}
                onMouseOver={() => this.setState({hover: true})}
                onMouseLeave={() => this.setState({hover: false})}
-               onClick={onClick}
+               to={to}
            >
                <div className="flex align-center layout-centered" style={{ height: "160px" }}>
                    <img
@@ -36,11 +38,11 @@ export default class NewQueryOption extends Component {
                    />
 
                </div>
-               <div className="text-grey-2 text-normal mt2 mb2 text-paragraph" style={{lineHeight: "1.5em"}}>
-                   <h2 className={cx("transition-all", {"text-grey-5": !hover}, {"text-brand": hover})}>{title}</h2>
-                   <p className={"text-grey-4"}>{description}</p>
+               <div className="text-normal mt2 mb2 text-paragraph" style={{lineHeight: "1.25em"}}>
+                   <h2 className={cx("transition-all", {"text-brand": hover})}>{title}</h2>
+                   <p className={"text-grey-4 text-small"}>{description}</p>
                </div>
-           </div>
+           </Link>
        );
    }
 }
diff --git a/frontend/src/metabase/new_query/containers/MetricSearch.jsx b/frontend/src/metabase/new_query/containers/MetricSearch.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..fe74845f673a315356328b7256e5fd0336732f55
--- /dev/null
+++ b/frontend/src/metabase/new_query/containers/MetricSearch.jsx
@@ -0,0 +1,97 @@
+import React, { Component } from 'react'
+import { connect } from 'react-redux'
+import { fetchMetrics, fetchDatabases } from "metabase/redux/metadata";
+import LoadingAndErrorWrapper from "metabase/components/LoadingAndErrorWrapper";
+import EntitySearch from "metabase/containers/EntitySearch";
+import { getMetadata, getMetadataFetched } from "metabase/selectors/metadata";
+import _ from 'underscore'
+
+import type { Metric } from "metabase/meta/types/Metric";
+import type Metadata from "metabase-lib/lib/metadata/Metadata";
+import EmptyState from "metabase/components/EmptyState";
+
+import type { StructuredQuery } from "metabase/meta/types/Query";
+import { getCurrentQuery } from "metabase/new_query/selectors";
+import { resetQuery } from '../new_query'
+
+const mapStateToProps = state => ({
+    query: getCurrentQuery(state),
+    metadata: getMetadata(state),
+    metadataFetched: getMetadataFetched(state)
+})
+const mapDispatchToProps = {
+    fetchMetrics,
+    fetchDatabases,
+    resetQuery
+}
+
+@connect(mapStateToProps, mapDispatchToProps)
+export default class MetricSearch extends Component {
+    props: {
+        getUrlForQuery: (StructuredQuery) => void,
+        query: StructuredQuery,
+        metadata: Metadata,
+        metadataFetched: any,
+        fetchMetrics: () => void,
+        fetchDatabases: () => void,
+        resetQuery: () => void,
+    }
+
+    componentDidMount() {
+        this.props.fetchDatabases() // load databases if not loaded yet
+        this.props.fetchMetrics(true) // metrics may change more often so always reload them
+        this.props.resetQuery();
+    }
+
+    getUrlForMetric = (metric: Metric) => {
+        const updatedQuery = this.props.query
+            .setDatabase(metric.table.db)
+            .setTable(metric.table)
+            .addAggregation(metric.aggregationClause())
+
+        return this.props.getUrlForQuery(updatedQuery);
+    }
+
+    render() {
+        const { metadataFetched, metadata } = this.props;
+        const isLoading = !metadataFetched.metrics || !metadataFetched.databases
+
+        return (
+            <LoadingAndErrorWrapper loading={isLoading}>
+                {() => {
+                    const sortedActiveMetrics = _.chain(metadata.metricsList())
+                        .filter((metric) => metric.isActive())
+                        .sortBy(({name}) => name.toLowerCase())
+                        .value()
+
+                    if (sortedActiveMetrics.length > 0) {
+                        return (
+                            <EntitySearch
+                                title="Which metric?"
+                                // TODO Atte Keinänen 8/22/17: If you call `/api/table/:id/table_metadata` it returns
+                                // all metrics (also retired ones) and is missing `is_active` prop. Currently this
+                                // filters them out but we should definitely update the endpoints in the upcoming metadata API refactoring.
+                                entities={sortedActiveMetrics}
+                                getUrlForEntity={this.getUrlForMetric}
+                            />
+                        )
+                    } else {
+                        return (
+                            <div className="mt2 flex-full flex align-center justify-center bg-slate-extra-light">
+                                <EmptyState
+                                    message={<span>Defining common metrics for your team makes it even easier to ask questions</span>}
+                                    image="/app/img/metrics_illustration"
+                                    action="How to create metrics"
+                                    link="http://www.metabase.com/docs/latest/administration-guide/07-segments-and-metrics.html"
+                                    className="mt2"
+                                    imageClassName="mln2"
+                                />
+                            </div>
+                        )
+                    }
+                }}
+            </LoadingAndErrorWrapper>
+        )
+    }
+}
+
diff --git a/frontend/src/metabase/new_query/containers/Metrics.jsx b/frontend/src/metabase/new_query/containers/Metrics.jsx
deleted file mode 100644
index d1b1a464c1aa7e31e549e775a41ef5fa526a9d84..0000000000000000000000000000000000000000
--- a/frontend/src/metabase/new_query/containers/Metrics.jsx
+++ /dev/null
@@ -1,9 +0,0 @@
-import React, { Component } from "react";
-
-class Metrics extends Component {
-    render() {
-        return <div>Metrics</div>;
-    }
-}
-
-export default Metrics;
diff --git a/frontend/src/metabase/new_query/containers/NewQuery.jsx b/frontend/src/metabase/new_query/containers/NewQuery.jsx
deleted file mode 100644
index 8f1db2d0c682124e320391715db009738581b079..0000000000000000000000000000000000000000
--- a/frontend/src/metabase/new_query/containers/NewQuery.jsx
+++ /dev/null
@@ -1,143 +0,0 @@
-/* @flow */
-
-import React, { Component } from 'react'
-import { connect } from 'react-redux'
-
-import { fetchDatabases, fetchTableMetadata } from 'metabase/redux/metadata'
-import { resetQuery, updateQuery } from '../new_query'
-
-import LoadingAndErrorWrapper from "metabase/components/LoadingAndErrorWrapper";
-
-import Table from "metabase-lib/lib/metadata/Table";
-import Database from "metabase-lib/lib/metadata/Database";
-import StructuredQuery from "metabase-lib/lib/queries/StructuredQuery"
-import type { TableId } from "metabase/meta/types/Table";
-import Metadata from "metabase-lib/lib/metadata/Metadata";
-import { getMetadata, getTables } from "metabase/selectors/metadata";
-import NewQueryOption from "metabase/new_query/components/NewQueryOption";
-import NativeQuery from "metabase-lib/lib/queries/NativeQuery";
-import { getCurrentQuery, getPlainNativeQuery } from "metabase/new_query/selectors";
-import Query from "metabase-lib/lib/queries/Query";
-
-const mapStateToProps = state => ({
-    query: getCurrentQuery(state),
-    plainNativeQuery: getPlainNativeQuery(state),
-    metadata: getMetadata(state),
-    tables: getTables(state)
-})
-
-const mapDispatchToProps = {
-    fetchDatabases,
-    fetchTableMetadata,
-    resetQuery,
-    updateQuery
-}
-
-
-type Props = {
-    // Component parameters
-    onComplete: (StructuredQuery) => void,
-
-    // Properties injected with redux connect
-    query: StructuredQuery,
-    plainNativeQuery: NativeQuery,
-
-    resetQuery: () => void,
-    updateQuery: (Query) => void,
-
-    fetchDatabases: () => void,
-    fetchTableMetadata: (TableId) => void,
-
-    metadata: Metadata
-}
-
-export class NewQuery extends Component {
-    props: Props
-
-    componentWillMount() {
-        this.props.fetchDatabases();
-        this.props.resetQuery();
-    }
-
-    startGuiQuery = (database: Database) => {
-        this.props.onComplete(this.props.query);
-    }
-
-    startNativeQuery = (table: Table) => {
-        this.props.onComplete(this.props.plainNativeQuery);
-    }
-
-    // NOTE: Not in the first iteration yet!
-    //
-    // showMetricSearch = () => {
-    //
-    // }
-    //
-    // showSegmentSearch = () => {
-    //
-    // }
-    //
-    // startMetricQuery = (metric: Metric) => {
-    //     this.props.fetchTableMetadata(metric.table().id);
-    //
-    //     this.props.updateQuery(
-    //         this.props.query
-    //             .setDatabase(metric.database)
-    //             .setTable(metric.table)
-    //             .addAggregation(metric.aggregationClause())
-    //     )
-    //         this.props.onComplete(updatedQuery);
-    // }
-
-    render() {
-        const { query } = this.props
-
-        if (!query) {
-            return <LoadingAndErrorWrapper loading={true}/>
-        }
-
-        return (
-            <div className="flex-full full ml-auto mr-auto px1 mt4 mb2 align-center"
-                 style={{maxWidth: "800px"}}>
-                <ol className="flex-full Grid Grid--guttersXl Grid--full small-Grid--1of2">
-
-                    {/*<li className="Grid-cell">
-                        <NewQueryOption
-                            image="/app/img/questions_illustration"
-                            title="Metrics"
-                            description="See data over time, as a map, or pivoted to help you understand trends or changes."
-                        />
-                    </li>
-                    <li className="Grid-cell">
-                        <NewQueryOption
-                            image="/app/img/list_illustration"
-                            title="Segments"
-                            description="Explore tables and see what’s going on underneath your charts."
-                            width={180}
-                        />
-                    </li>*/}
-
-                    <li className="Grid-cell">
-                        {/*TODO: Move illustrations to the new location in file hierarchy. At the same time put an end to the equal-size-@2x ridicule. */}
-                        <NewQueryOption
-                            image="/app/img/custom_question"
-                            title="New question"
-                            description="Use the simple query builder to see trends, lists of things, or to create your own metrics."
-                            onClick={this.startGuiQuery}
-                        />
-                    </li>
-                    <li className="Grid-cell">
-                        <NewQueryOption
-                            image="/app/img/sql_illustration@2x"
-                            title="SQL"
-                            description="For more complicated questions, you can write your own SQL."
-                            onClick={this.startNativeQuery}
-                        />
-                    </li>
-                </ol>
-            </div>
-        )
-    }
-}
-
-export default connect(mapStateToProps, mapDispatchToProps)(NewQuery)
diff --git a/frontend/src/metabase/new_query/containers/NewQueryOptions.jsx b/frontend/src/metabase/new_query/containers/NewQueryOptions.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..2fd3912bfb1277fab9cf140839949d4c99870361
--- /dev/null
+++ b/frontend/src/metabase/new_query/containers/NewQueryOptions.jsx
@@ -0,0 +1,137 @@
+import React, { Component } from 'react'
+import { connect } from 'react-redux'
+
+import {
+    fetchDatabases,
+    fetchMetrics,
+    fetchSegments,
+} from 'metabase/redux/metadata'
+
+import { resetQuery } from '../new_query'
+
+import LoadingAndErrorWrapper from "metabase/components/LoadingAndErrorWrapper";
+import StructuredQuery from "metabase-lib/lib/queries/StructuredQuery"
+import Metadata from "metabase-lib/lib/metadata/Metadata";
+import { getMetadata, getMetadataFetched } from "metabase/selectors/metadata";
+import NewQueryOption from "metabase/new_query/components/NewQueryOption";
+import NativeQuery from "metabase-lib/lib/queries/NativeQuery";
+import { getCurrentQuery, getPlainNativeQuery } from "metabase/new_query/selectors";
+import { getUserIsAdmin } from "metabase/selectors/user";
+
+const mapStateToProps = state => ({
+    query: getCurrentQuery(state),
+    plainNativeQuery: getPlainNativeQuery(state),
+    metadata: getMetadata(state),
+    metadataFetched: getMetadataFetched(state),
+    isAdmin: getUserIsAdmin(state)
+})
+
+const mapDispatchToProps = {
+    fetchDatabases,
+    fetchMetrics,
+    fetchSegments,
+    resetQuery
+}
+
+type Props = {
+    // Component parameters
+    getUrlForQuery: (StructuredQuery) => void,
+    metricSearchUrl: string,
+    segmentSearchUrl: string,
+
+    // Properties injected with redux connect
+    query: StructuredQuery,
+    plainNativeQuery: NativeQuery,
+    metadata: Metadata,
+    isAdmin: boolean,
+
+    resetQuery: () => void,
+
+    fetchDatabases: () => void,
+    fetchMetrics: () => void,
+    fetchSegments: () => void,
+}
+
+export class NewQueryOptions extends Component {
+    props: Props
+
+    componentWillMount() {
+        this.props.fetchDatabases()
+        this.props.fetchMetrics()
+        this.props.fetchSegments()
+
+        this.props.resetQuery();
+    }
+
+    getGuiQueryUrl = () => {
+        return this.props.getUrlForQuery(this.props.query);
+    }
+
+    getNativeQueryUrl = () => {
+        return this.props.getUrlForQuery(this.props.plainNativeQuery);
+    }
+
+    render() {
+        const { query, metadata, metadataFetched, isAdmin, metricSearchUrl, segmentSearchUrl } = this.props
+
+        if (!query || (!isAdmin && (!metadataFetched.metrics || !metadataFetched.segments))) {
+            return <LoadingAndErrorWrapper loading={true}/>
+        }
+
+        const showMetricOption = isAdmin || metadata.metricsList().length > 0
+        const showSegmentOption = isAdmin || metadata.segmentsList().length > 0
+        const showCustomInsteadOfNewQuestionText = showMetricOption || showSegmentOption
+
+        return (
+            <div className="bg-slate-extra-light full-height flex">
+                <div className="wrapper wrapper--trim lg-wrapper--trim xl-wrapper--trim flex-full px1 mt4 mb2 align-center">
+                     <div className="flex align-center justify-center" style={{minHeight: "100%"}}>
+                        <ol className="flex-full Grid Grid--guttersXl Grid--full small-Grid--1of2 large-Grid--normal">
+                            { showMetricOption &&
+                                <li className="Grid-cell">
+                                    <NewQueryOption
+                                        image="/app/img/questions_illustration"
+                                        title="Metrics"
+                                        description="See data over time, as a map, or pivoted to help you understand trends or changes."
+                                        to={metricSearchUrl}
+                                    />
+                                </li>
+                            }
+                            { showSegmentOption &&
+                                <li className="Grid-cell">
+                                    <NewQueryOption
+                                        image="/app/img/list_illustration"
+                                        title="Segments"
+                                        description="Explore tables and see what’s going on underneath your charts."
+                                        width={180}
+                                        to={segmentSearchUrl}
+                                    />
+                                </li>
+                            }
+                            <li className="Grid-cell">
+                                {/*TODO: Move illustrations to the new location in file hierarchy. At the same time put an end to the equal-size-@2x ridicule. */}
+                                <NewQueryOption
+                                    image="/app/img/query_builder_illustration"
+                                    title={ showCustomInsteadOfNewQuestionText ? "Custom" : "New question"}
+                                    description="Use the simple query builder to see trends, lists of things, or to create your own metrics."
+                                    width={180}
+                                    to={this.getGuiQueryUrl}
+                                />
+                            </li>
+                            <li className="Grid-cell">
+                                <NewQueryOption
+                                    image="/app/img/sql_illustration"
+                                    title="SQL"
+                                    description="For more complicated questions, you can write your own SQL."
+                                    to={this.getNativeQueryUrl}
+                                />
+                            </li>
+                        </ol>
+                    </div>
+                </div>
+            </div>
+        )
+    }
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(NewQueryOptions)
diff --git a/frontend/src/metabase/new_query/containers/SegmentSearch.jsx b/frontend/src/metabase/new_query/containers/SegmentSearch.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..aee20268390a2927f7cee6e41b2cf94bc795de7f
--- /dev/null
+++ b/frontend/src/metabase/new_query/containers/SegmentSearch.jsx
@@ -0,0 +1,98 @@
+import React, { Component } from 'react'
+import { connect } from 'react-redux'
+import _ from 'underscore'
+
+import { fetchDatabases, fetchSegments } from "metabase/redux/metadata";
+import LoadingAndErrorWrapper from "metabase/components/LoadingAndErrorWrapper";
+import EntitySearch from "metabase/containers/EntitySearch";
+import { getMetadata, getMetadataFetched } from "metabase/selectors/metadata";
+
+import Metadata from "metabase-lib/lib/metadata/Metadata";
+import type { Segment } from "metabase/meta/types/Segment";
+import EmptyState from "metabase/components/EmptyState";
+
+import type { StructuredQuery } from "metabase/meta/types/Query";
+import { getCurrentQuery } from "metabase/new_query/selectors";
+import { resetQuery } from '../new_query'
+
+const mapStateToProps = state => ({
+    query: getCurrentQuery(state),
+    metadata: getMetadata(state),
+    metadataFetched: getMetadataFetched(state)
+})
+const mapDispatchToProps = {
+    fetchSegments,
+    fetchDatabases,
+    resetQuery
+}
+
+@connect(mapStateToProps, mapDispatchToProps)
+export default class SegmentSearch extends Component {
+    props: {
+        getUrlForQuery: (StructuredQuery) => void,
+        query: StructuredQuery,
+        metadata: Metadata,
+        metadataFetched: any,
+        fetchSegments: () => void,
+        fetchDatabases: () => void,
+        resetQuery: () => void
+    }
+
+    componentDidMount() {
+        this.props.fetchDatabases() // load databases if not loaded yet
+        this.props.fetchSegments(true) // segments may change more often so always reload them
+        this.props.resetQuery();
+    }
+
+    getUrlForSegment = (segment: Segment) => {
+        const updatedQuery = this.props.query
+            .setDatabase(segment.table.database)
+            .setTable(segment.table)
+            .addFilter(segment.filterClause())
+
+        return this.props.getUrlForQuery(updatedQuery);
+    }
+
+    render() {
+        const { metadataFetched, metadata } = this.props;
+
+        const isLoading = !metadataFetched.segments || !metadataFetched.databases
+
+        return (
+            <LoadingAndErrorWrapper loading={isLoading}>
+                {() => {
+                    // TODO Atte Keinänen 8/22/17: If you call `/api/table/:id/table_metadata` it returns
+                    // all segments (also retired ones) and they are missing both `is_active` and `creator` props. Currently this
+                    // filters them out but we should definitely update the endpoints in the upcoming metadata API refactoring.
+                    const sortedActiveSegments = _.chain(metadata.segmentsList())
+                        .filter((segment) => segment.isActive())
+                        .sortBy(({name}) => name.toLowerCase())
+                        .value()
+
+                    if (sortedActiveSegments.length > 0) {
+                        return <EntitySearch
+                            title="Which segment?"
+                            entities={sortedActiveSegments}
+                            getUrlForEntity={this.getUrlForSegment}
+                        />
+                    } else {
+                        return (
+                            <div className="mt2 flex-full flex align-center justify-center bg-slate-extra-light">
+                                <EmptyState
+                                    message={<span>Defining common segments for your team makes it even easier to ask questions</span>}
+                                    image="/app/img/segments_illustration"
+                                    action="How to create segments"
+                                    link="http://www.metabase.com/docs/latest/administration-guide/07-segments-and-metrics.html"
+                                    className="mt2"
+                                    imageClassName="mln2"
+                                />
+                            </div>
+                        )
+                    }
+                }}
+            </LoadingAndErrorWrapper>
+        )
+    }
+
+}
+
diff --git a/frontend/src/metabase/new_query/containers/Segments.jsx b/frontend/src/metabase/new_query/containers/Segments.jsx
deleted file mode 100644
index 41c947aea47b6a76da07aaff956c220bfc1317c9..0000000000000000000000000000000000000000
--- a/frontend/src/metabase/new_query/containers/Segments.jsx
+++ /dev/null
@@ -1,47 +0,0 @@
-import React, { Component } from "react";
-import { connect } from "react-redux";
-import { Link } from "react-router";
-
-import { serializeCardForUrl } from "metabase/lib/card";
-
-import { fetchSegments } from "metabase/redux/metadata";
-import { getSegments } from "metabase/selectors/metadata";
-
-const mapStateToProps = state => ({
-    segments: Object.values(getSegments(state))
-});
-
-const mapDispatchToProps = {
-    fetchSegments
-};
-
-@connect(mapStateToProps, mapDispatchToProps)
-class Segments extends Component {
-    componentWillMount() {
-        this.props.fetchSegments();
-    }
-    render() {
-        const { segments } = this.props;
-        return (
-            <div>
-                <div>
-                    <Link to="question/new">
-                        Back
-                    </Link>
-                    <h2>Which segment?</h2>
-                </div>
-                <ol>
-                    {segments.map(segment => (
-                        <li key={segment.id}>
-                            <Link to={serializeCardForUrl(segment.definition)}>
-                                {segment.name}
-                            </Link>
-                        </li>
-                    ))}
-                </ol>
-            </div>
-        );
-    }
-}
-
-export default Segments;
diff --git a/frontend/src/metabase/new_query/new_query.js b/frontend/src/metabase/new_query/new_query.js
index 3bc383098ee35549ee7722942c85ca0b5393e377..bb911dde0bb581ebfcc9faabd83524befc833d31 100644
--- a/frontend/src/metabase/new_query/new_query.js
+++ b/frontend/src/metabase/new_query/new_query.js
@@ -4,7 +4,7 @@
  */
 
 import { handleActions, combineReducers } from "metabase/lib/redux";
-import StructuredQuery, { STRUCTURED_QUERY_TEMPLATE } from "metabase-lib/lib/queries/StructuredQuery";
+import { STRUCTURED_QUERY_TEMPLATE } from "metabase-lib/lib/queries/StructuredQuery";
 import type { DatasetQuery } from "metabase/meta/types/Card";
 
 /**
@@ -17,21 +17,12 @@ export function resetQuery() {
     }
 }
 
-export const UPDATE_QUERY = "metabase/new_query/UPDATE_QUERY";
-export function updateQuery(updatedQuery: StructuredQuery) {
-    return function(dispatch, getState) {
-        dispatch.action(UPDATE_QUERY, updatedQuery.datasetQuery())
-    }
-}
-
 /**
  * The current query that we are creating
  */
-// TODO Atte Keinänen 6/12/17: Test later how Flow typing with redux-actions could work best for our reducers
 // something like const query = handleActions<DatasetQuery>({
 const datasetQuery = handleActions({
     [RESET_QUERY]: (state, { payload }): DatasetQuery => payload,
-    [UPDATE_QUERY]: (state, { payload }): DatasetQuery => payload
 }, STRUCTURED_QUERY_TEMPLATE);
 
 export default combineReducers({
diff --git a/frontend/src/metabase/new_query/new_query.spec.js b/frontend/src/metabase/new_query/new_query.spec.js
deleted file mode 100644
index 579632e7012a3a060b8fd7e786b3f93847ac8f7f..0000000000000000000000000000000000000000
--- a/frontend/src/metabase/new_query/new_query.spec.js
+++ /dev/null
@@ -1,8 +0,0 @@
-/**
- * Would possibly be nice to test the whole action-reducer-selector loop in here
- */
-describe("New query flow", () => {
-    it("temporary placeholder test", () => {
-       expect(true).toEqual(true);
-    })
-});
diff --git a/frontend/src/metabase/new_query/router_wrappers.js b/frontend/src/metabase/new_query/router_wrappers.js
index 78105c7886b88f27f301eacfa343d81a3f715777..f0111005249c7c198c88b4a63a54d2e84a108076 100644
--- a/frontend/src/metabase/new_query/router_wrappers.js
+++ b/frontend/src/metabase/new_query/router_wrappers.js
@@ -2,12 +2,55 @@ import React, { Component } from "react";
 import { connect } from "react-redux";
 import { push } from "react-router-redux";
 
-import NewQuery from "metabase/new_query/containers/NewQuery";
+import NewQueryOptions from "./containers/NewQueryOptions";
+import SegmentSearch from "./containers/SegmentSearch";
+import MetricSearch from "./containers/MetricSearch";
 
 @connect(null, { onChangeLocation: push })
 export class NewQuestionStart extends Component {
+    getUrlForQuery = (query) => {
+        return query.question().getUrl()
+    }
+
     render() {
-        return <NewQuery onComplete={(query) => this.props.onChangeLocation(query.question().getUrl())} />
+        return (
+            <NewQueryOptions
+                getUrlForQuery={this.getUrlForQuery}
+                metricSearchUrl="/question/new/metric"
+                segmentSearchUrl="/question/new/segment"
+            />
+        )
     }
 }
 
+@connect(null, { onChangeLocation: push })
+export class NewQuestionMetricSearch extends Component {
+    getUrlForQuery = (query) => {
+        return query.question().getUrl()
+    }
+
+    render() {
+        return (
+            <MetricSearch
+                getUrlForQuery={this.getUrlForQuery}
+                defaultStep={"metricSearch"}
+            />
+        )
+    }
+}
+
+@connect(null, { onChangeLocation: push })
+export class NewQuestionSegmentSearch extends Component {
+    getUrlForQuery = (query) => {
+        return query.question().getUrl()
+    }
+
+    render() {
+        return (
+            <SegmentSearch
+                getUrlForQuery={this.getUrlForQuery}
+                defaultStep={"segmentSearch"}
+            />
+        )
+    }
+}
diff --git a/frontend/src/metabase/new_query/selectors.js b/frontend/src/metabase/new_query/selectors.js
index 417b1967d21ad7a9e8499acc1386367b2667a236..c47c9ed47dcd67a37414eee22fd0c3d4e3ef4a57 100644
--- a/frontend/src/metabase/new_query/selectors.js
+++ b/frontend/src/metabase/new_query/selectors.js
@@ -16,6 +16,16 @@ export const getCurrentQuery = state => {
 }
 
 export const getPlainNativeQuery = state => {
+    const metadata = getMetadata(state)
     const question = Question.create({ metadata: getMetadata(state) })
-    return new NativeQuery(question)
+    const databases = metadata.databasesList().filter(db => !db.is_saved_questions)
+
+    // If we only have a single database, then default to that
+    // (native query editor doesn't currently show the db selector if there is only one database available)
+    if (databases.length === 1) {
+        return new NativeQuery(question).setDatabase(databases[0])
+    } else {
+        return new NativeQuery(question)
+    }
+
 }
\ No newline at end of file
diff --git a/frontend/src/metabase/redux/metadata.js b/frontend/src/metabase/redux/metadata.js
index 13507ac73a21210007a32993c94719b157f9d0fc..63b445f0ae103acdf1554702c03468282ec40b3f 100644
--- a/frontend/src/metabase/redux/metadata.js
+++ b/frontend/src/metabase/redux/metadata.js
@@ -81,7 +81,6 @@ export const updateMetricImportantFields = createThunkAction(UPDATE_METRIC_IMPOR
     };
 });
 
-
 export const FETCH_SEGMENTS = "metabase/metadata/FETCH_SEGMENTS";
 export const fetchSegments = createThunkAction(FETCH_SEGMENTS, (reload = false) => {
     return async (dispatch, getState) => {
diff --git a/frontend/src/metabase/redux/requests.js b/frontend/src/metabase/redux/requests.js
index da294bc72d4fdee7c4e2e378390ff7a018aa388d..958d8be731aaa47aa8f99cd2e05c816f214073cc 100644
--- a/frontend/src/metabase/redux/requests.js
+++ b/frontend/src/metabase/redux/requests.js
@@ -1,15 +1,17 @@
 /* @flow weak */
 
 import { handleActions, createAction } from "metabase/lib/redux";
-import { assocIn } from "icepick";
+import { getIn, assocIn } from "icepick";
+import { combineReducers } from "redux";
 
-const SET_REQUEST_STATE = "metabase/requests/SET_REQUEST_STATE";
+export const SET_REQUEST_STATE = "metabase/requests/SET_REQUEST_STATE";
 const CLEAR_REQUEST_STATE = "metabase/requests/CLEAR_REQUEST_STATE";
 
 export const setRequestState = createAction(SET_REQUEST_STATE);
 export const clearRequestState = createAction(CLEAR_REQUEST_STATE);
 
-export default handleActions({
+// For a given state path, returns the current request state ("LOADING", "LOADED" or a request error)
+export const states = handleActions({
     [SET_REQUEST_STATE]: {
         next: (state, { payload }) => assocIn(
             state,
@@ -25,3 +27,25 @@ export default handleActions({
         )
     }
 }, {});
+
+// For given state path, returns true if the data has been successfully fetched at least once
+export const fetched = handleActions({
+    [SET_REQUEST_STATE]: {
+        next: (state, {payload}) => {
+            const isFetch = payload.statePath[payload.statePath.length - 1] === "fetch"
+
+            if (isFetch) {
+                const statePathWithoutFetch = payload.statePath.slice(0, -1)
+                return assocIn(
+                    state,
+                    statePathWithoutFetch,
+                    getIn(state, statePathWithoutFetch) || payload.state === "LOADED"
+                )
+            } else {
+                return state
+            }
+        }
+    }
+}, {})
+
+export default combineReducers({ states, fetched })
diff --git a/frontend/src/metabase/routes.jsx b/frontend/src/metabase/routes.jsx
index eb6a83bf053502996cd4793aeef966892ae872c7..796e82e84bd9ff6554dec75c2b66c1ef957c6b1a 100644
--- a/frontend/src/metabase/routes.jsx
+++ b/frontend/src/metabase/routes.jsx
@@ -42,7 +42,7 @@ import SetupApp from "metabase/setup/containers/SetupApp.jsx";
 import UserSettingsApp from "metabase/user/containers/UserSettingsApp.jsx";
 
 // new question
-import { NewQuestionStart } from "metabase/new_query/router_wrappers";
+import { NewQuestionStart, NewQuestionMetricSearch, NewQuestionSegmentSearch } from "metabase/new_query/router_wrappers";
 
 // admin containers
 import DatabaseListApp from "metabase/admin/databases/containers/DatabaseListApp.jsx";
@@ -200,10 +200,10 @@ export const getRoutes = (store) =>
                 <Route path="/question">
                     <IndexRoute component={QueryBuilder} />
                     { /* NEW QUESTION FLOW */ }
-                    <Route path="new">
+                    <Route path="new" title="New Question">
                         <IndexRoute component={NewQuestionStart} />
-                        {/*<Route path="metrics" component={NewQuestionMetrics} />*/}
-                        {/*<Route path="segments" component={NewQuestionSegments} />*/}
+                        <Route path="metric" title="Metrics" component={NewQuestionMetricSearch} />
+                        <Route path="segment" title="Segments" component={NewQuestionSegmentSearch} />
                     </Route>
                 </Route>
                 <Route path="/question/:cardId" component={QueryBuilder} />
diff --git a/frontend/src/metabase/selectors/metadata.js b/frontend/src/metabase/selectors/metadata.js
index 6cb138df2fd51060ca77156a2e87904acc0395d9..1b6bda217a42d1feccf73be2e8a207faacc9aec5 100644
--- a/frontend/src/metabase/selectors/metadata.js
+++ b/frontend/src/metabase/selectors/metadata.js
@@ -27,6 +27,7 @@ export const getNormalizedFields = state => state.metadata.fields;
 export const getNormalizedMetrics = state => state.metadata.metrics;
 export const getNormalizedSegments = state => state.metadata.segments;
 
+export const getMetadataFetched = state => state.requests.fetched.metadata || {}
 
 // TODO: these should be denomalized but non-cylical, and only to the same "depth" previous "tableMetadata" was, e.x.
 //
@@ -68,6 +69,7 @@ export const getMetadata = createSelector(
         meta.fields    = copyObjects(meta, fields, Field)
         meta.segments  = copyObjects(meta, segments, Segment)
         meta.metrics   = copyObjects(meta, metrics, Metric)
+        // meta.loaded    = getLoadedStatuses(requestStates)
 
         hydrateList(meta.databases, "tables", meta.tables);
 
diff --git a/frontend/test/home/HomepageApp.integ.spec.js b/frontend/test/home/HomepageApp.integ.spec.js
index 74a65737c1dbc867aa3020c9ae3d0520ab67f191..3aecd44370ed11f83553f856bdd3f9c21022260f 100644
--- a/frontend/test/home/HomepageApp.integ.spec.js
+++ b/frontend/test/home/HomepageApp.integ.spec.js
@@ -15,7 +15,6 @@ import {
 import { delay } from 'metabase/lib/promise';
 
 import HomepageApp from "metabase/home/containers/HomepageApp";
-import { createMetric, createSegment } from "metabase/admin/datamodel/datamodel";
 import { FETCH_ACTIVITY } from "metabase/home/actions";
 import { QUERY_COMPLETED } from "metabase/query_builder/actions";
 
@@ -23,22 +22,33 @@ import Activity from "metabase/home/components/Activity";
 import ActivityItem from "metabase/home/components/ActivityItem";
 import ActivityStory from "metabase/home/components/ActivityStory";
 import Scalar from "metabase/visualizations/visualizations/Scalar";
+import { CardApi, MetricApi, SegmentApi } from "metabase/services";
 
 describe("HomepageApp", () => {
+    let questionId = null;
+    let segmentId = null;
+    let metricId = null;
+
     beforeAll(async () => {
         await login()
 
         // Create some entities that will show up in the top of activity feed
         // This test doesn't care if there already are existing items in the feed or not
         // Delays are required for having separable creation times for each entity
-        await createSavedQuestion(unsavedOrderCountQuestion)
+        questionId = (await createSavedQuestion(unsavedOrderCountQuestion)).id()
         await delay(100);
-        await createSegment(orders_past_30_days_segment);
+        segmentId = (await SegmentApi.create(orders_past_30_days_segment)).id;
         await delay(100);
-        await createMetric(vendor_count_metric);
+        metricId = (await MetricApi.create(vendor_count_metric)).id;
         await delay(100);
     })
 
+    afterAll(async () => {
+        await MetricApi.delete({ metricId, revision_message: "Let's exterminate this metric" })
+        await SegmentApi.delete({ segmentId, revision_message: "Let's exterminate this segment" })
+        await CardApi.delete({ cardId: questionId })
+    })
+
     describe("activity feed", async () => {
         it("shows the expected list of activity", async () => {
             const store = await createTestStore()
diff --git a/frontend/test/lib/redux.unit.spec.js b/frontend/test/lib/redux.unit.spec.js
index 723be7003d9532c4bbe7ab2465969fd5abac683e..df8cb0cfc85e5d287c573f089af7d564ec19b4bf 100644
--- a/frontend/test/lib/redux.unit.spec.js
+++ b/frontend/test/lib/redux.unit.spec.js
@@ -3,6 +3,8 @@ import {
     updateData 
 } from 'metabase/lib/redux';
 
+import { delay } from "metabase/lib/promise"
+
 describe("Metadata", () => {
     const getDefaultArgs = ({
         existingData = 'data',
@@ -17,7 +19,7 @@ describe("Metadata", () => {
         requestStatePath = statePath,
         existingStatePath = statePath,
         getState = () => ({
-            requests: { test: { path: { fetch: requestState, update: requestState } } },
+            requests: { states: { test: { path: { fetch: requestState, update: requestState } } } },
             test: { path: existingData }
         }),
         dispatch = jasmine.createSpy('dispatch'),
@@ -39,15 +41,15 @@ describe("Metadata", () => {
     const args = getDefaultArgs({});
 
     describe("fetchData()", () => {
-        it("should return new data if request hasn't been made", async (done) => {
+        it("should return new data if request hasn't been made", async () => {
             const argsDefault = getDefaultArgs({});
             const data = await fetchData(argsDefault);
+            await delay(10);
             expect(argsDefault.dispatch.calls.count()).toEqual(2);
             expect(data).toEqual(args.newData);
-            done();
         });
 
-        it("should return existing data if request has been made", async (done) => {
+        it("should return existing data if request has been made", async () => {
             const argsLoading = getDefaultArgs({requestState: args.requestStateLoading});
             const dataLoading = await fetchData(argsLoading);
             expect(argsLoading.dispatch.calls.count()).toEqual(0);
@@ -57,21 +59,20 @@ describe("Metadata", () => {
             const dataLoaded = await fetchData(argsLoaded);
             expect(argsLoaded.dispatch.calls.count()).toEqual(0);
             expect(dataLoaded).toEqual(args.existingData);
-            done();
         });
 
-        it("should return new data if previous request ended in error", async (done) => {
+        it("should return new data if previous request ended in error", async () => {
             const argsError = getDefaultArgs({requestState: args.requestStateError});
             const dataError = await fetchData(argsError);
+            await delay(10);
             expect(argsError.dispatch.calls.count()).toEqual(2);
             expect(dataError).toEqual(args.newData);
-            done();
         });
 
         // FIXME: this seems to make jasmine ignore the rest of the tests
         // is an exception bubbling up from fetchData? why?
         // how else to test return value in the catch case?
-        xit("should return existing data if request fails", async (done) => {
+        it("should return existing data if request fails", async () => {
             const argsFail = getDefaultArgs({getData: () => Promise.reject('error')});
 
             try{
@@ -82,12 +83,11 @@ describe("Metadata", () => {
             catch(error) {
                 return;
             }
-            done();
         });
     });
 
     describe("updateData()", () => {
-        it("should return new data regardless of previous request state", async (done) => {
+        it("should return new data regardless of previous request state", async () => {
             const argsDefault = getDefaultArgs({});
             const data = await updateData(argsDefault);
             expect(argsDefault.dispatch.calls.count()).toEqual(2);
@@ -107,16 +107,14 @@ describe("Metadata", () => {
             const dataError = await updateData(argsError);
             expect(argsError.dispatch.calls.count()).toEqual(2);
             expect(dataError).toEqual(args.newData);
-            done();
         });
 
-        // FIXME: same problem as fetchData() case
-        xit("should return existing data if request fails", async (done) => {
+        it("should return existing data if request fails", async () => {
             const argsFail = getDefaultArgs({putData: () => {throw new Error('test')}});
-            const data = await fetchData(argsFail);
+            const data = await updateData(argsFail);
+            await delay(10)
             expect(argsFail.dispatch.calls.count()).toEqual(2);
             expect(data).toEqual(args.existingData);
-            done();
         });
     });
 });
diff --git a/frontend/test/query_builder/components/dataref/MetricPane.integ.spec.js b/frontend/test/query_builder/components/dataref/MetricPane.integ.spec.js
index 0ace79bee1ab15a91f50f3ba391e41fd2e29ddfe..44dfe0f771ecdac37ef7f3520c146b48cc5cef60 100644
--- a/frontend/test/query_builder/components/dataref/MetricPane.integ.spec.js
+++ b/frontend/test/query_builder/components/dataref/MetricPane.integ.spec.js
@@ -13,20 +13,21 @@ import { delay } from "metabase/lib/promise"
 import QueryBuilder from "metabase/query_builder/containers/QueryBuilder";
 import DataReference from "metabase/query_builder/components/dataref/DataReference";
 import { vendor_count_metric } from "__support__/sample_dataset_fixture";
-import { createMetric } from "metabase/admin/datamodel/datamodel";
 import { FETCH_TABLE_METADATA } from "metabase/redux/metadata";
 import QueryDefinition from "metabase/query_builder/components/dataref/QueryDefinition";
 import QueryButton from "metabase/components/QueryButton";
 import Scalar from "metabase/visualizations/visualizations/Scalar";
 import * as Urls from "metabase/lib/urls";
+import { MetricApi } from "metabase/services";
 
 describe("MetricPane", () => {
     let store = null;
     let queryBuilder = null;
+    let metricId = null;
 
     beforeAll(async () => {
         await login();
-        await createMetric(vendor_count_metric);
+        metricId = (await MetricApi.create(vendor_count_metric)).id;
         store = await createTestStore()
 
         store.pushPath(Urls.plainQuestion());
@@ -34,6 +35,9 @@ describe("MetricPane", () => {
         await store.waitForActions([INITIALIZE_QB]);
     })
 
+    afterAll(async () => {
+        await MetricApi.delete({ metricId, revision_message: "Let's exterminate this metric" })
+    })
     // NOTE: These test cases are intentionally stateful
     // (doing the whole app rendering thing in every single test case would probably slow things down)
 
diff --git a/frontend/test/query_builder/query_builder.integ.spec.js b/frontend/test/query_builder/query_builder.integ.spec.js
index 69cb6d8c10789474b70fbb601ddc18c1b043923a..7e237152a215c49177e48b638c5d9ebdaf06c39f 100644
--- a/frontend/test/query_builder/query_builder.integ.spec.js
+++ b/frontend/test/query_builder/query_builder.integ.spec.js
@@ -34,7 +34,10 @@ import {
     deleteFieldDimension,
     updateFieldDimension,
     updateFieldValues,
-    FETCH_TABLE_METADATA
+    FETCH_TABLE_METADATA,
+    FETCH_METRICS,
+    FETCH_SEGMENTS,
+    FETCH_DATABASES
 } from "metabase/redux/metadata";
 import FieldList, { DimensionPicker } from "metabase/query_builder/components/FieldList";
 import FilterPopover from "metabase/query_builder/components/filters/FilterPopover";
@@ -65,6 +68,15 @@ import NewQueryOption from "metabase/new_query/components/NewQueryOption";
 import { RESET_QUERY } from "metabase/new_query/new_query";
 import StructuredQuery from "metabase-lib/lib/queries/StructuredQuery";
 import NativeQuery from "metabase-lib/lib/queries/NativeQuery";
+import EntitySearch, {
+    SearchGroupingOption, SearchResultListItem,
+    SearchResultsGroup
+} from "metabase/containers/EntitySearch";
+import { MetricApi, SegmentApi } from "metabase/services";
+import AggregationWidget from "metabase/query_builder/components/AggregationWidget";
+import { SET_REQUEST_STATE } from "metabase/redux/requests";
+import NativeQueryEditor from "metabase/query_builder/components/NativeQueryEditor";
+import DataSelector from "metabase/query_builder/components/DataSelector";
 
 const REVIEW_PRODUCT_ID = 32;
 const REVIEW_RATING_ID = 33;
@@ -98,6 +110,26 @@ describe("QueryBuilder", () => {
      * Simple tests for seeing if the query builder renders without errors
      */
     describe("for new questions", async () => {
+        let metricId = null;
+        let segmentId = null;
+
+        beforeAll(async () => {
+            // TODO: Move these test metric/segment definitions to a central place
+            const metricDef = {name: "A Metric", description: "For testing new question flow", table_id: 1,show_in_getting_started: true,
+                definition: {database: 1, query: {aggregation: ["count"]}}}
+            const segmentDef = {name: "A Segment", description: "For testing new question flow", table_id: 1, show_in_getting_started: true,
+                definition: {database: 1, query: {filter: ["abc"]}}}
+
+            // Needed for question creation flow
+            metricId = (await MetricApi.create(metricDef)).id;
+            segmentId = (await SegmentApi.create(segmentDef)).id;
+        })
+
+        afterAll(async () => {
+            await MetricApi.delete({ metricId, revision_message: "The lifetime of this metric was just a few seconds" })
+            await SegmentApi.delete({ segmentId, revision_message: "Sadly this segment didn't enjoy a long life either" })
+        })
+
         it("redirects /question to /question/new", async () => {
             const store = await createTestStore()
             store.pushPath("/question");
@@ -110,33 +142,106 @@ describe("QueryBuilder", () => {
 
             store.pushPath(Urls.newQuestion());
             const app = mount(store.getAppContainer());
-            await store.waitForActions([RESET_QUERY]);
+            await store.waitForActions([RESET_QUERY, FETCH_METRICS, FETCH_SEGMENTS]);
+            await store.waitForActions([SET_REQUEST_STATE]);
 
-            expect(app.find(NewQueryOption).length).toBe(2)
+            expect(app.find(NewQueryOption).length).toBe(4)
         });
-        it("lets you start a custom gui query", async () => {
+        it("lets you start a custom gui question", async () => {
             const store = await createTestStore()
 
             store.pushPath(Urls.newQuestion());
             const app = mount(store.getAppContainer());
-            await store.waitForActions([RESET_QUERY]);
+            await store.waitForActions([RESET_QUERY, FETCH_METRICS, FETCH_SEGMENTS]);
+            await store.waitForActions([SET_REQUEST_STATE]);
 
-            click(app.find(NewQueryOption).first())
+            click(app.find(NewQueryOption).filterWhere((c) => c.prop('title') === "Custom"))
             await store.waitForActions(INITIALIZE_QB, UPDATE_URL, LOAD_METADATA_FOR_CARD);
             expect(getQuery(store.getState()) instanceof StructuredQuery).toBe(true)
         })
 
-        // Something doesn't work in tests when opening the native query editor :/
-        xit("lets you start a custom native query", async () => {
+        it("lets you start a custom native question", async () => {
+            // Don't render Ace editor in tests because it uses many DOM methods that aren't supported by jsdom
+            // see also parameters.integ.js for more notes about Ace editor testing
+            NativeQueryEditor.prototype.loadAceEditor = () => {}
+
             const store = await createTestStore()
 
             store.pushPath(Urls.newQuestion());
             const app = mount(store.getAppContainer());
-            await store.waitForActions([RESET_QUERY]);
+            await store.waitForActions([RESET_QUERY, FETCH_METRICS, FETCH_SEGMENTS, FETCH_DATABASES]);
+            await store.waitForActions([SET_REQUEST_STATE]);
 
-            click(app.find(NewQueryOption).last())
+            click(app.find(NewQueryOption).filterWhere((c) => c.prop('title') === "SQL"))
             await store.waitForActions(INITIALIZE_QB);
             expect(getQuery(store.getState()) instanceof NativeQuery).toBe(true)
+
+            // No database selector visible because in test environment we should
+            // only have a single database
+            expect(app.find(DataSelector).length).toBe(0)
+
+            // The name of the database should be displayed
+            expect(app.find(NativeQueryEditor).text()).toMatch(/Sample Dataset/)
+        })
+
+        it("lets you start a question from a metric", async () => {
+            const store = await createTestStore()
+
+            store.pushPath(Urls.newQuestion());
+            const app = mount(store.getAppContainer());
+            await store.waitForActions([RESET_QUERY, FETCH_METRICS, FETCH_SEGMENTS]);
+            await store.waitForActions([SET_REQUEST_STATE]);
+
+            click(app.find(NewQueryOption).filterWhere((c) => c.prop('title') === "Metrics"))
+            await store.waitForActions(FETCH_DATABASES);
+            await store.waitForActions([SET_REQUEST_STATE]);
+            expect(store.getPath()).toBe("/question/new/metric")
+
+            const entitySearch = app.find(EntitySearch)
+            const viewByCreator = entitySearch.find(SearchGroupingOption).last()
+            expect(viewByCreator.text()).toBe("Creator");
+            click(viewByCreator)
+
+            const group = entitySearch.find(SearchResultsGroup)
+            expect(group.prop('groupName')).toBe("Bobby Tables")
+
+            const metricSearchResult = group.find(SearchResultListItem)
+                .filterWhere((item) => /A Metric/.test(item.text()))
+            click(metricSearchResult.childAt(0))
+
+            await store.waitForActions([INITIALIZE_QB, QUERY_COMPLETED]);
+            expect(
+                app.find(AggregationWidget).find(".View-section-aggregation").text()
+            ).toBe("A Metric")
+        })
+
+        it("lets you start a question from a segment", async () => {
+            const store = await createTestStore()
+
+            store.pushPath(Urls.newQuestion());
+            const app = mount(store.getAppContainer());
+            await store.waitForActions([RESET_QUERY, FETCH_METRICS, FETCH_SEGMENTS]);
+            await store.waitForActions([SET_REQUEST_STATE]);
+
+            click(app.find(NewQueryOption).filterWhere((c) => c.prop('title') === "Segments"))
+            await store.waitForActions(FETCH_DATABASES);
+            await store.waitForActions([SET_REQUEST_STATE]);
+            expect(store.getPath()).toBe("/question/new/segment")
+
+            const entitySearch = app.find(EntitySearch)
+            const viewByTable = entitySearch.find(SearchGroupingOption).at(1)
+            expect(viewByTable.text()).toBe("Table");
+            click(viewByTable)
+
+            const group = entitySearch.find(SearchResultsGroup)
+                .filterWhere((group) => group.prop('groupName') === "Orders")
+
+            const metricSearchResult = group.find(SearchResultListItem)
+                .filterWhere((item) => /A Segment/.test(item.text()))
+            click(metricSearchResult.childAt(0))
+
+            await store.waitForActions([INITIALIZE_QB, QUERY_COMPLETED]);
+            expect(app.find(FilterWidget).find(".Filter-section-value").text()).toBe("A Segment")
         })
     });
 
@@ -737,7 +842,6 @@ describe("QueryBuilder", () => {
                 const firstRowCells = table.find("tbody tr").first().find("td");
                 expect(firstRowCells.length).toBe(2);
 
-                // lat-long formatting should be improved when it comes to trailing zeros
                 expect(firstRowCells.first().text()).toBe("90° S  –  80° S");
 
                 const countCell = firstRowCells.last();
diff --git a/resources/frontend_client/app/img/custom_question.png b/resources/frontend_client/app/img/custom_question.png
deleted file mode 100644
index dfba328409c9a7bd759cdc26acfe4a1e08ba1b22..0000000000000000000000000000000000000000
Binary files a/resources/frontend_client/app/img/custom_question.png and /dev/null differ
diff --git a/resources/frontend_client/app/img/custom_question@2x.png b/resources/frontend_client/app/img/custom_question@2x.png
deleted file mode 100644
index dfba328409c9a7bd759cdc26acfe4a1e08ba1b22..0000000000000000000000000000000000000000
Binary files a/resources/frontend_client/app/img/custom_question@2x.png and /dev/null differ
diff --git a/resources/frontend_client/app/img/empty_question.png b/resources/frontend_client/app/img/empty_question.png
new file mode 100644
index 0000000000000000000000000000000000000000..7ba003aa07eed085e6916aaac85a3abbae98b412
Binary files /dev/null and b/resources/frontend_client/app/img/empty_question.png differ
diff --git a/resources/frontend_client/app/img/empty_question@2x.png b/resources/frontend_client/app/img/empty_question@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..cb56281af1d6921c7e9e68b0c7b206e20ae1d8ac
Binary files /dev/null and b/resources/frontend_client/app/img/empty_question@2x.png differ
diff --git a/resources/frontend_client/app/img/list_illustration.png b/resources/frontend_client/app/img/list_illustration.png
index 28d872b66634f934a5bb2551c8d7f6c43bacf808..c791c75f8a35d3a791eeb33c961c25bf2d5ef641 100644
Binary files a/resources/frontend_client/app/img/list_illustration.png and b/resources/frontend_client/app/img/list_illustration.png differ
diff --git a/resources/frontend_client/app/img/list_illustration@2x.png b/resources/frontend_client/app/img/list_illustration@2x.png
index 28d872b66634f934a5bb2551c8d7f6c43bacf808..368e777feb0014735e3802eb5c16b69beeaabd6e 100644
Binary files a/resources/frontend_client/app/img/list_illustration@2x.png and b/resources/frontend_client/app/img/list_illustration@2x.png differ
diff --git a/resources/frontend_client/app/img/metrics_illustration.png b/resources/frontend_client/app/img/metrics_illustration.png
new file mode 100644
index 0000000000000000000000000000000000000000..ba198cad7cfdf41a62a4eef66414265227a902e9
Binary files /dev/null and b/resources/frontend_client/app/img/metrics_illustration.png differ
diff --git a/resources/frontend_client/app/img/metrics_illustration@2x.png b/resources/frontend_client/app/img/metrics_illustration@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..ba198cad7cfdf41a62a4eef66414265227a902e9
Binary files /dev/null and b/resources/frontend_client/app/img/metrics_illustration@2x.png differ
diff --git a/resources/frontend_client/app/img/query_builder_illustration.png b/resources/frontend_client/app/img/query_builder_illustration.png
new file mode 100644
index 0000000000000000000000000000000000000000..b387d07336b7f8acaf239856b070ee65607a6a5d
Binary files /dev/null and b/resources/frontend_client/app/img/query_builder_illustration.png differ
diff --git a/resources/frontend_client/app/img/query_builder_illustration@2x.png b/resources/frontend_client/app/img/query_builder_illustration@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..abdd2e6a466bfea142f75bd8a9d1f55a9a598b41
Binary files /dev/null and b/resources/frontend_client/app/img/query_builder_illustration@2x.png differ
diff --git a/resources/frontend_client/app/img/segments_illustration.png b/resources/frontend_client/app/img/segments_illustration.png
new file mode 100644
index 0000000000000000000000000000000000000000..9a53a05472a929a5400c796847fbd6e83f0133fc
Binary files /dev/null and b/resources/frontend_client/app/img/segments_illustration.png differ
diff --git a/resources/frontend_client/app/img/segments_illustration@2x.png b/resources/frontend_client/app/img/segments_illustration@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..9a53a05472a929a5400c796847fbd6e83f0133fc
Binary files /dev/null and b/resources/frontend_client/app/img/segments_illustration@2x.png differ
diff --git a/resources/frontend_client/app/img/sql_illustration.png b/resources/frontend_client/app/img/sql_illustration.png
index 4bc10a2e8eeccc7fc9d0eb2b3d8c4fde43c17b9c..0b9f73d73e9364d9517c58a068916f370b2b5061 100644
Binary files a/resources/frontend_client/app/img/sql_illustration.png and b/resources/frontend_client/app/img/sql_illustration.png differ
diff --git a/resources/frontend_client/app/img/sql_illustration@2x.png b/resources/frontend_client/app/img/sql_illustration@2x.png
index 4bc10a2e8eeccc7fc9d0eb2b3d8c4fde43c17b9c..80d90e26238fd7ad506526e637e13a0568b0a082 100644
Binary files a/resources/frontend_client/app/img/sql_illustration@2x.png and b/resources/frontend_client/app/img/sql_illustration@2x.png differ