diff --git a/src/components/close-button/close-button.css b/src/components/close-button/close-button.css
index 1864e7b2aaede98cf6f4b827db6ba63586275f47..88ebb526ef01c81aeacae0597450e5c992b88951 100644
--- a/src/components/close-button/close-button.css
+++ b/src/components/close-button/close-button.css
@@ -49,3 +49,18 @@
     width: 0.75rem;
     height: 0.75rem;
 }
+
+.back-icon {
+  position: relative;
+  margin: 0.25rem;
+  user-select: none;
+}
+
+.small .back-icon {
+    width: 50%;
+}
+
+.large .back-icon {
+    width: 2rem;
+    height: 2rem;
+}
diff --git a/src/components/close-button/close-button.jsx b/src/components/close-button/close-button.jsx
index 039a8750b7ae108506a2077c07ad2e66496c1217..befac229f5b0a5da58f3c1e1b25b6d9d64c79357 100644
--- a/src/components/close-button/close-button.jsx
+++ b/src/components/close-button/close-button.jsx
@@ -4,6 +4,7 @@ import classNames from 'classnames';
 
 import styles from './close-button.css';
 import closeIcon from './icon--close.svg';
+import backIcon from './icon--back.svg';
 
 const CloseButton = props => (
     <div
@@ -20,10 +21,16 @@ const CloseButton = props => (
         tabIndex="0"
         onClick={props.onClick}
     >
-        <img
-            className={styles.closeIcon}
-            src={closeIcon}
-        />
+        {props.buttonType === 'back' ?
+            <img
+                className={styles.backIcon}
+                src={backIcon}
+            /> :
+            <img
+                className={styles.closeIcon}
+                src={closeIcon}
+            />
+        }
     </div>
 );
 
@@ -31,13 +38,15 @@ CloseButton.SIZE_SMALL = 'small';
 CloseButton.SIZE_LARGE = 'large';
 
 CloseButton.propTypes = {
+    buttonType: PropTypes.oneOf(['back', 'close']),
     className: PropTypes.string,
     onClick: PropTypes.func.isRequired,
     size: PropTypes.oneOf([CloseButton.SIZE_SMALL, CloseButton.SIZE_LARGE])
 };
 
 CloseButton.defaultProps = {
-    size: CloseButton.SIZE_LARGE
+    size: CloseButton.SIZE_LARGE,
+    buttonType: 'close'
 };
 
 export default CloseButton;
diff --git a/src/components/close-button/icon--back.svg b/src/components/close-button/icon--back.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e3f82a6fdb679c27301413397fc8838f74bbb9ae
Binary files /dev/null and b/src/components/close-button/icon--back.svg differ
diff --git a/src/components/gui/gui.jsx b/src/components/gui/gui.jsx
index 488e705e88db5ce7cb76a4cc320446b0dab1b35b..5c7a378dc43c44ff9f3d5d37e3b9ae79ffbbe87f 100644
--- a/src/components/gui/gui.jsx
+++ b/src/components/gui/gui.jsx
@@ -19,6 +19,7 @@ import Box from '../box/box.jsx';
 import FeedbackForm from '../feedback-form/feedback-form.jsx';
 import MenuBar from '../menu-bar/menu-bar.jsx';
 import PreviewModal from '../../containers/preview-modal.jsx';
+import ImportModal from '../../containers/import-modal.jsx';
 import WebGlModal from '../../containers/webgl-modal.jsx';
 
 import layout from '../../lib/layout-constants.js';
@@ -41,6 +42,7 @@ const GUIComponent = props => {
         children,
         costumesTabVisible,
         feedbackFormVisible,
+        importInfoVisible,
         intl,
         onExtensionButtonClick,
         onActivateTab,
@@ -76,6 +78,9 @@ const GUIComponent = props => {
             {previewInfoVisible ? (
                 <PreviewModal />
             ) : null}
+            {importInfoVisible ? (
+                <ImportModal />
+            ) : null}
             {feedbackFormVisible ? (
                 <FeedbackForm />
             ) : null}
@@ -169,9 +174,11 @@ GUIComponent.propTypes = {
     children: PropTypes.node,
     costumesTabVisible: PropTypes.bool,
     feedbackFormVisible: PropTypes.bool,
+    importInfoVisible: PropTypes.bool,
     intl: intlShape.isRequired,
     onActivateTab: PropTypes.func,
     onExtensionButtonClick: PropTypes.func,
+    onTabSelect: PropTypes.func,
     previewInfoVisible: PropTypes.bool,
     soundsTabVisible: PropTypes.bool,
     vm: PropTypes.instanceOf(VM).isRequired
diff --git a/src/components/import-modal/import-modal.css b/src/components/import-modal/import-modal.css
new file mode 100644
index 0000000000000000000000000000000000000000..b794fd7530cf3711fdf2dae1891df79c3138324d
--- /dev/null
+++ b/src/components/import-modal/import-modal.css
@@ -0,0 +1,185 @@
+@import "../../css/colors.css";
+@import "../../css/units.css";
+@import "../../css/typography.css";
+
+.modal-overlay {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    z-index: 1000;
+    background-color: hsla(215, 100%, 65%, .9);
+}
+
+.modal-content {
+    margin: 100px auto;
+    outline: none;
+    border: .25rem solid hsla(0, 100%, 100%, .25);
+    padding: 0;
+    border-radius: $space;
+    user-select: none;
+    width: 500px;
+    color: $text-primary;
+    overflow: hidden;
+}
+
+/*
+    TODO figure out how to remove filter altogether
+    since it is null...
+    Modal header has 3 items:
+    |x     title       filter|
+
+    Use the same width for both side item containers,
+    so that title remains centered
+*/
+$sides: 20rem;
+
+.header {
+    display: flex;
+    flex-direction: row;
+    flex-wrap: nowrap;
+    justify-content: flex-start;
+    height: $library-header-height;
+
+    box-sizing: border-box;
+    width: 100%;
+    background-color: $import-primary;
+}
+
+.header-item {
+    display: flex;
+    align-items: center;
+    padding: 1rem;
+    text-decoration: none;
+    color: white;
+    user-select: none;
+}
+
+.header-item-filter {
+    display: flex;
+    flex-basis: $sides;
+    justify-content: flex-end;
+}
+
+.header-item-title {
+    flex-grow: 1;
+    flex-shrink: 0;
+    justify-content: center;
+    user-select: none;
+    letter-spacing: 0.4px;
+    cursor: default;
+}
+
+.header-item-title h2 {
+    font-size: 1.25rem;
+}
+
+.header-item-close {
+    display: flex;
+    flex-basis: $sides;
+    justify-content: flex-start;
+}
+
+.body {
+    background: $ui-pane-gray;
+    padding: 1.5rem 2.25rem;
+    text-align: center;
+}
+
+.input-row {
+    margin: 1.5rem 0;
+    font-weight: bolder;
+    text-align: right;
+    display: flex;
+    justify-content: center;
+    border: 1px solid;
+    border-radius: 0.25rem;
+    overflow: hidden;
+}
+
+.ok-input-container {
+    border-color: $motion-primary;
+    box-shadow: 0 0 0 0.2rem $motion-transparent;
+}
+
+.bad-input-container {
+    border-color: $data-primary;
+    box-shadow: 0 0 0 0.2rem hsla(30, 100%, 55%, 0.15);
+}
+
+.input-row input {
+    width: 100%;
+    padding: 0 1rem;
+    height: 3rem;
+    color: #6b6b6b;
+    font-size: .875rem;
+    outline: none;
+    border: none;
+}
+
+.input-row input::placeholder {
+    font-style: italic;
+    color: rgba(87,94,117,0.5);
+}
+
+.input-row button {
+    padding: 0.5rem 2rem;
+    font-weight: bold;
+    font-size: .875rem;
+    cursor: pointer;
+    border: 0px solid $import-primary;
+    outline: none;
+}
+
+.input-row button.ok-button {
+    background: $import-primary;
+    color: white;
+}
+
+.error-row {
+    margin: 1.5rem 0;
+    text-align: center;
+    display: flex;
+    justify-content: center;
+    background: hsla(30, 100%, 55%, 0.25);
+    color: $data-primary;
+    border: 1px solid $data-primary;
+    border-radius: 0.25rem;
+}
+
+.error-row p {
+    font-size: 0.875rem;
+    font-weight: bold;
+}
+
+/* Confirmation buttons at the bottom of the modal */
+.button-row {
+    margin: 1.5rem 0;
+    font-weight: bolder;
+    text-align: right;
+    display: flex;
+    justify-content: center;
+}
+
+.button-row button {
+    border: 1px solid $motion-primary;
+    border-radius: 0.25rem;
+    padding: 0.5rem 1.5rem;
+    background: white;
+    font-weight: bold;
+    font-size: .875rem;
+    cursor: pointer;
+    color: $motion-primary;
+}
+
+.faq-link-text {
+    margin: 2rem 0 .5rem 0;
+    font-size: .875rem;
+    color: $text-primary;
+}
+
+.faq-link {
+    color: $motion-primary;
+    text-decoration: none;
+}
diff --git a/src/components/import-modal/import-modal.jsx b/src/components/import-modal/import-modal.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..ad42929e7d6c24afced4c2febf2bda976ea27f2b
--- /dev/null
+++ b/src/components/import-modal/import-modal.jsx
@@ -0,0 +1,155 @@
+import PropTypes from 'prop-types';
+import React from 'react';
+import ReactModal from 'react-modal';
+import Box from '../box/box.jsx';
+import {defineMessages, injectIntl, intlShape, FormattedMessage} from 'react-intl';
+import classNames from 'classnames';
+
+import CloseButton from '../close-button/close-button.jsx';
+
+import styles from './import-modal.css';
+
+const messages = defineMessages({
+    title: {
+        id: 'gui.importInfo.title',
+        defaultMessage: 'View a Scratch 2.0 Project',
+        description: 'Scratch 2.0 import modal label - for accessibility'
+    },
+    formDescription: {
+        defaultMessage:
+            'Enter a link to one of your shared Scratch projects. Changes made in this 3.0 Preview will not be saved.',
+        description: 'Import project message',
+        id: 'gui.importInfo.message'
+    },
+    invalidFormatError: {
+        id: 'gui.importInfo.invalidFormatError',
+        defaultMessage: 'Uh oh, that project link or id doesn\'t look quite right.',
+        description: 'Invalid project link or id message'
+    }
+});
+
+const ImportModal = ({intl, ...props}) => (
+    <ReactModal
+        isOpen
+        className={styles.modalContent}
+        contentLabel={intl.formatMessage({...messages.title})}
+        overlayClassName={styles.modalOverlay}
+        onRequestClose={props.onCancel}
+    >
+        <Box>
+            <div className={styles.header}>
+                <div
+                    className={classNames(
+                        styles.headerItem,
+                        styles.headerItemClose
+                    )}
+                >
+                    <CloseButton
+                        buttonType="back"
+                        size={CloseButton.SIZE_LARGE}
+                        onClick={props.onGoBack}
+                    />
+                </div>
+                <div
+                    className={classNames(
+                        styles.headerItem,
+                        styles.headerItemTitle
+                    )}
+                >
+                    <h2>
+                        {intl.formatMessage({...messages.title})}
+                    </h2>
+                </div>
+                <div className={classNames(styles.headerItem, styles.headerItemFilter)}>
+                    {null}
+                </div>
+            </div>
+        </Box>
+
+        <Box className={styles.body}>
+            <p>
+                {intl.formatMessage({...messages.formDescription})}
+            </p>
+            <Box
+                className={classNames(styles.inputRow,
+                    (props.hasValidationError ? styles.badInputContainer : styles.okInputContainer))
+                }
+            >
+                <input
+                    autoFocus
+                    placeholder={props.placeholder}
+                    value={props.inputValue}
+                    onChange={props.onChange}
+                    onKeyPress={props.onKeyPress}
+                />
+                <button
+                    className={styles.okButton}
+                    title="viewproject"
+                    onClick={props.onViewProject}
+                >
+                    <FormattedMessage
+                        defaultMessage="View"
+                        description="Label for button to load a scratch 2.0 project"
+                        id="gui.importModal.viewproject"
+                    />
+                </button>
+            </Box>
+            {props.hasValidationError ?
+                <Box className={styles.errorRow}>
+                    <p>
+                        <FormattedMessage
+                            {...messages[`${props.errorMessage}`]}
+                        />
+                    </p>
+                </Box> : null
+            }
+            <Box className={styles.buttonRow}>
+                <button
+                    onClick={props.onGoBack}
+                >
+                    <FormattedMessage
+                        defaultMessage="Go Back"
+                        description="Label for button to back out of importing a project"
+                        id="gui.importInfo.goback"
+                    />
+                </button>
+            </Box>
+            <Box className={styles.faqLinkText}>
+                <FormattedMessage
+                    defaultMessage="To learn more, go to the {previewFaqLink}."
+                    description="Invitation to try 3.0 preview"
+                    id="gui.importInfo.previewfaq"
+                    values={{
+                        previewFaqLink: (
+                            <a
+                                className={styles.faqLink}
+                                href="//scratch.mit.edu/preview-faq"
+                            >
+                                <FormattedMessage
+                                    defaultMessage="Preview FAQ"
+                                    description="link to Scratch 3.0 preview FAQ page"
+                                    id="gui.importInfo.previewfaqlink"
+                                />
+                            </a>
+                        )
+                    }}
+                />
+            </Box>
+        </Box>
+    </ReactModal>
+);
+
+ImportModal.propTypes = {
+    errorMessage: PropTypes.string.isRequired,
+    hasValidationError: PropTypes.bool.isRequired,
+    inputValue: PropTypes.string.isRequired,
+    intl: intlShape.isRequired,
+    onCancel: PropTypes.func.isRequired,
+    onChange: PropTypes.func.isRequired,
+    onGoBack: PropTypes.func.isRequired,
+    onKeyPress: PropTypes.func.isRequired,
+    onViewProject: PropTypes.func.isRequired,
+    placeholder: PropTypes.string
+};
+
+export default injectIntl(ImportModal);
diff --git a/src/components/preview-modal/preview-modal.css b/src/components/preview-modal/preview-modal.css
index 858beb5bad1de1eeaf30e9cdbc786621cfa3723a..c6e5037e8c60cd226103cdcc3f4131ebe8aa9745 100644
--- a/src/components/preview-modal/preview-modal.css
+++ b/src/components/preview-modal/preview-modal.css
@@ -51,7 +51,7 @@
 .button-row button {
     border: 1px solid $motion-primary;
     border-radius: 0.25rem;
-    padding: 0.5rem 2rem;
+    padding: 0.5rem 1.5rem;
     background: white;
     font-weight: bold;
     font-size: .875rem;
@@ -66,6 +66,13 @@
 .button-row button.no-button {
     color: $motion-primary;
 }
+
+.button-row button.view-project-button {
+    background: $import-primary;
+    border-color: $import-primary;
+    color: white;
+}
+
 .button-row button + button {
     margin-left: 0.5rem;
 }
diff --git a/src/components/preview-modal/preview-modal.jsx b/src/components/preview-modal/preview-modal.jsx
index 71a3b029ca86bb8793f3aa8848c11b0e91294a9d..5772b518539a7541f30859a3aef6540eef030878 100644
--- a/src/components/preview-modal/preview-modal.jsx
+++ b/src/components/preview-modal/preview-modal.jsx
@@ -71,6 +71,17 @@ const PreviewModal = ({intl, ...props}) => (
                         }}
                     />
                 </button>
+                <button
+                    className={styles.viewProjectButton}
+                    title="viewproject"
+                    onClick={props.onViewProject}
+                >
+                    <FormattedMessage
+                        defaultMessage="View 2.0 Project"
+                        description="Label for button to import a 2.0 project"
+                        id="gui.previewModal.viewproject"
+                    />
+                </button>
             </Box>
             <Box className={styles.faqLinkText}>
                 <FormattedMessage
@@ -100,7 +111,8 @@ const PreviewModal = ({intl, ...props}) => (
 PreviewModal.propTypes = {
     intl: intlShape.isRequired,
     onCancel: PropTypes.func.isRequired,
-    onTryIt: PropTypes.func.isRequired
+    onTryIt: PropTypes.func.isRequired,
+    onViewProject: PropTypes.func.isRequired
 };
 
 export default injectIntl(PreviewModal);
diff --git a/src/containers/gui.jsx b/src/containers/gui.jsx
index bae6f9684ec5e3553a2d1eeb4e32eb10da4793d0..de4fe27a284623c4058f07e62da59d32fd378643 100644
--- a/src/containers/gui.jsx
+++ b/src/containers/gui.jsx
@@ -53,6 +53,7 @@ class GUI extends React.Component {
 GUI.propTypes = {
     ...GUIComponent.propTypes,
     feedbackFormVisible: PropTypes.bool,
+    importInfoVisible: PropTypes.bool,
     previewInfoVisible: PropTypes.bool,
     projectData: PropTypes.string,
     vm: PropTypes.instanceOf(VM)
@@ -65,6 +66,7 @@ const mapStateToProps = state => ({
     blocksTabVisible: state.editorTab.activeTabIndex === BLOCKS_TAB_INDEX,
     costumesTabVisible: state.editorTab.activeTabIndex === COSTUMES_TAB_INDEX,
     feedbackFormVisible: state.modals.feedbackForm,
+    importInfoVisible: state.modals.importInfo,
     previewInfoVisible: state.modals.previewInfo,
     soundsTabVisible: state.editorTab.activeTabIndex === SOUNDS_TAB_INDEX
 });
diff --git a/src/containers/import-modal.jsx b/src/containers/import-modal.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..1c2ddbefbb4639cec62cbf37fc7ceae33a45dbc8
--- /dev/null
+++ b/src/containers/import-modal.jsx
@@ -0,0 +1,111 @@
+import bindAll from 'lodash.bindall';
+import PropTypes from 'prop-types';
+import React from 'react';
+import {connect} from 'react-redux';
+
+import ImportModalComponent from '../components/import-modal/import-modal.jsx';
+
+import {
+    closeImportInfo,
+    openPreviewInfo
+} from '../reducers/modals';
+
+class ImportModal extends React.Component {
+    constructor (props) {
+        super(props);
+        bindAll(this, [
+            'handleViewProject',
+            'handleCancel',
+            'handleChange',
+            'handleGoBack',
+            'handleKeyPress'
+        ]);
+
+        this.state = {
+            inputValue: '',
+            hasValidationError: false,
+            errorMessage: ''
+        };
+    }
+    handleKeyPress (event) {
+        if (event.key === 'Enter') this.handleViewProject();
+    }
+    handleViewProject () {
+        const inputValue = this.state.inputValue;
+        const projectId = this.validate(inputValue);
+
+        if (projectId) {
+            const projectLink = document.createElement('a');
+            document.body.appendChild(projectLink);
+            projectLink.href = `#${projectId}`;
+            projectLink.click();
+            document.body.removeChild(projectLink);
+            this.props.onViewProject();
+        } else {
+            this.setState({
+                hasValidationError: true,
+                errorMessage: `invalidFormatError`});
+        }
+    }
+    handleChange (e) {
+        this.setState({inputValue: e.target.value, hasValidationError: false});
+    }
+    validate (input) {
+        const urlMatches = input.match(/^(?:https:\/\/)?scratch\.mit\.edu\/projects\/(\d+)/);
+        if (urlMatches && urlMatches.length > 0) {
+            return urlMatches[1];
+        }
+        const projectIdMatches = input.match(/^#?(\d+)$/);
+        if (projectIdMatches && projectIdMatches.length > 0) {
+            return projectIdMatches[1];
+        }
+        return null;
+    }
+    handleCancel () {
+        this.props.onCancel();
+    }
+    handleGoBack () {
+        this.props.onBack();
+    }
+    render () {
+        return (
+            <ImportModalComponent
+                errorMessage={this.state.errorMessage}
+                hasValidationError={this.state.hasValidationError}
+                inputValue={this.state.inputValue}
+                placeholder="scratch.mit.edu/projects/123456789"
+                onCancel={this.handleCancel}
+                onChange={this.handleChange}
+                onGoBack={this.handleGoBack}
+                onKeyPress={this.handleKeyPress}
+                onViewProject={this.handleViewProject}
+            />
+        );
+    }
+}
+
+ImportModal.propTypes = {
+    onBack: PropTypes.func.isRequired,
+    onCancel: PropTypes.func.isRequired,
+    onViewProject: PropTypes.func
+};
+
+const mapStateToProps = () => ({});
+
+const mapDispatchToProps = dispatch => ({
+    onBack: () => {
+        dispatch(closeImportInfo());
+        dispatch(openPreviewInfo());
+    },
+    onCancel: () => {
+        dispatch(closeImportInfo());
+    },
+    onViewProject: () => {
+        dispatch(closeImportInfo());
+    }
+});
+
+export default connect(
+    mapStateToProps,
+    mapDispatchToProps
+)(ImportModal);
diff --git a/src/containers/preview-modal.jsx b/src/containers/preview-modal.jsx
index 8d50dc83c279e5c4b1660b012b7f15cd83344c3b..1209f251f0445da6a5aa0d65f8fa6d343ce5654e 100644
--- a/src/containers/preview-modal.jsx
+++ b/src/containers/preview-modal.jsx
@@ -8,7 +8,8 @@ import PreviewModalComponent from '../components/preview-modal/preview-modal.jsx
 import BrowserModalComponent from '../components/browser-modal/browser-modal.jsx';
 
 import {
-    closePreviewInfo
+    closePreviewInfo,
+    openImportInfo
 } from '../reducers/modals';
 
 class PreviewModal extends React.Component {
@@ -16,7 +17,8 @@ class PreviewModal extends React.Component {
         super(props);
         bindAll(this, [
             'handleTryIt',
-            'handleCancel'
+            'handleCancel',
+            'handleViewProject'
         ]);
 
         this.state = {
@@ -30,6 +32,9 @@ class PreviewModal extends React.Component {
     handleCancel () {
         window.location.replace('https://scratch.mit.edu');
     }
+    handleViewProject () {
+        this.props.onViewProject();
+    }
     supportedBrowser () {
         if (platform.name === 'IE') {
             return false;
@@ -42,6 +47,7 @@ class PreviewModal extends React.Component {
                 previewing={this.state.previewing}
                 onCancel={this.handleCancel}
                 onTryIt={this.handleTryIt}
+                onViewProject={this.handleViewProject}
             /> :
             <BrowserModalComponent
                 onBack={this.handleCancel}
@@ -51,7 +57,8 @@ class PreviewModal extends React.Component {
 }
 
 PreviewModal.propTypes = {
-    onTryIt: PropTypes.func
+    onTryIt: PropTypes.func,
+    onViewProject: PropTypes.func
 };
 
 const mapStateToProps = () => ({});
@@ -59,6 +66,10 @@ const mapStateToProps = () => ({});
 const mapDispatchToProps = dispatch => ({
     onTryIt: () => {
         dispatch(closePreviewInfo());
+    },
+    onViewProject: () => {
+        dispatch(closePreviewInfo());
+        dispatch(openImportInfo());
     }
 });
 
diff --git a/src/css/colors.css b/src/css/colors.css
index f4611c06e25e2ffad536fd7520186dd57fd29101..be8a9a0dbe1ef45a5a3214f1d8d00b92f4b74d42 100644
--- a/src/css/colors.css
+++ b/src/css/colors.css
@@ -21,3 +21,5 @@ $data-primary: #FF8C1A;
 $pen-primary: #11B581;
 
 $form-border: #E9EEF2;
+
+$import-primary: #0FBD8C;
diff --git a/src/reducers/modals.js b/src/reducers/modals.js
index ffbca3f8c07feb4326c83e2de284eb2bf4108fc5..ba038ff3464e2d3c33373e5fb54f9d92fe1544f3 100644
--- a/src/reducers/modals.js
+++ b/src/reducers/modals.js
@@ -7,6 +7,7 @@ const MODAL_BACKDROP_LIBRARY = 'backdropLibrary';
 const MODAL_COSTUME_LIBRARY = 'costumeLibrary';
 const MODAL_EXTENSION_LIBRARY = 'extensionLibrary';
 const MODAL_FEEDBACK_FORM = 'feedbackForm';
+const MODAL_IMPORT_INFO = 'importInfo';
 const MODAL_PREVIEW_INFO = 'previewInfo';
 const MODAL_SOUND_LIBRARY = 'soundLibrary';
 const MODAL_SPRITE_LIBRARY = 'spriteLibrary';
@@ -18,6 +19,7 @@ const initialState = {
     [MODAL_COSTUME_LIBRARY]: false,
     [MODAL_EXTENSION_LIBRARY]: false,
     [MODAL_FEEDBACK_FORM]: false,
+    [MODAL_IMPORT_INFO]: false,
     [MODAL_PREVIEW_INFO]: true,
     [MODAL_SOUND_LIBRARY]: false,
     [MODAL_SPRITE_LIBRARY]: false,
@@ -67,6 +69,14 @@ const openFeedbackForm = function () {
     analytics.pageview('/modals/feedback');
     return openModal(MODAL_FEEDBACK_FORM);
 };
+const openImportInfo = function () {
+    analytics.pageview('modals/import');
+    return openModal(MODAL_IMPORT_INFO);
+};
+const openPreviewInfo = function () {
+    analytics.pageview('/modals/preview');
+    return openModal(MODAL_PREVIEW_INFO);
+};
 const openSoundLibrary = function () {
     analytics.pageview('/libraries/sounds');
     return openModal(MODAL_SOUND_LIBRARY);
@@ -79,10 +89,6 @@ const openSoundRecorder = function () {
     analytics.pageview('/modals/microphone');
     return openModal(MODAL_SOUND_RECORDER);
 };
-const openPreviewInfo = function () {
-    analytics.pageview('/modals/preview');
-    return openModal(MODAL_PREVIEW_INFO);
-};
 const closeBackdropLibrary = function () {
     return closeModal(MODAL_BACKDROP_LIBRARY);
 };
@@ -95,6 +101,9 @@ const closeExtensionLibrary = function () {
 const closeFeedbackForm = function () {
     return closeModal(MODAL_FEEDBACK_FORM);
 };
+const closeImportInfo = function () {
+    return closeModal(MODAL_IMPORT_INFO);
+};
 const closePreviewInfo = function () {
     return closeModal(MODAL_PREVIEW_INFO);
 };
@@ -113,6 +122,7 @@ export {
     openCostumeLibrary,
     openExtensionLibrary,
     openFeedbackForm,
+    openImportInfo,
     openPreviewInfo,
     openSoundLibrary,
     openSpriteLibrary,
@@ -121,6 +131,7 @@ export {
     closeCostumeLibrary,
     closeExtensionLibrary,
     closeFeedbackForm,
+    closeImportInfo,
     closePreviewInfo,
     closeSpriteLibrary,
     closeSoundLibrary,
diff --git a/test/integration/project-loading.test.js b/test/integration/project-loading.test.js
index 9d5cb0384252aa9aacb96bd3a780173050dda366..6add67c42b178055b653bf94cf9a29c41a5db9cc 100644
--- a/test/integration/project-loading.test.js
+++ b/test/integration/project-loading.test.js
@@ -4,6 +4,7 @@ import SeleniumHelper from '../helpers/selenium-helper';
 const {
     clickText,
     clickXpath,
+    findByXpath,
     getDriver,
     getLogs,
     loadUri
@@ -31,7 +32,40 @@ describe('Loading scratch gui', () => {
 
     describe('Loading projects by ID', () => {
 
-        test('Load a project by ID', async () => {
+        test('Load 2.0 project using import modal', async () => {
+            await loadUri(uri);
+            await clickText('View 2.0 Project');
+            const el = await findByXpath("//input[@placeholder='scratch.mit.edu/projects/123456789']");
+            const projectId = '96708228';
+            await el.sendKeys(`scratch.mit.edu/projects/${projectId}`);
+            await clickXpath('//button[@title="viewproject"]');
+            await new Promise(resolve => setTimeout(resolve, 2000));
+            await clickXpath('//img[@title="Go"]');
+            await new Promise(resolve => setTimeout(resolve, 2000));
+            await clickXpath('//img[@title="Stop"]');
+            const logs = await getLogs();
+            await expect(logs).toEqual([]);
+        });
+
+        test('Invalid url when loading project through modal lets you try again', async () => {
+            await loadUri(uri);
+            await clickText('View 2.0 Project');
+            let el = await findByXpath("//input[@placeholder='scratch.mit.edu/projects/123456789']");
+            await el.sendKeys('thisisnotaurl');
+            await clickXpath('//button[@title="viewproject"]');
+            el = await findByXpath("//input[@placeholder='scratch.mit.edu/projects/123456789']");
+            await el.clear();
+            await el.sendKeys('scratch.mit.edu/projects/96708228');
+            await clickXpath('//button[@title="viewproject"]');
+            await new Promise(resolve => setTimeout(resolve, 2000));
+            await clickXpath('//img[@title="Go"]');
+            await new Promise(resolve => setTimeout(resolve, 2000));
+            await clickXpath('//img[@title="Stop"]');
+            const logs = await getLogs();
+            await expect(logs).toEqual([]);
+        });
+
+        test('Load a project by ID directly through url', async () => {
             const projectId = '96708228';
             await loadUri(`${uri}#${projectId}`);
             await clickXpath('//button[@title="tryit"]');