diff --git a/package.json b/package.json
index 7765b8dd74165a1be9eafcd6b8bcabc1d63c7a36..7d221cc7cc3b81884a7ab67e7e34256a3b8d8f8d 100644
--- a/package.json
+++ b/package.json
@@ -62,7 +62,7 @@
     "scratch-audio": "^0.1.0-prerelease.0",
     "scratch-blocks": "^0.1.0-prerelease.0",
     "scratch-render": "^0.1.0-prerelease.0",
-    "scratch-storage": "^0.0.1-prerelease.0",
+    "scratch-storage": "^0.1.0",
     "scratch-vm": "^0.1.0-prerelease.0",
     "style-loader": "0.16.1",
     "svg-to-image": "1.1.3",
diff --git a/src/components/asset-panel/selector.jsx b/src/components/asset-panel/selector.jsx
index d0d076bab5b9be6ecc64a152cb8e3f6954021106..0ddc2bb51202771fc9861ac603174bb28716773f 100644
--- a/src/components/asset-panel/selector.jsx
+++ b/src/components/asset-panel/selector.jsx
@@ -27,6 +27,7 @@ const Selector = props => {
             <Box className={styles.listArea}>
                 {items.map((item, index) => (
                     <SpriteSelectorItem
+                        assetId={item.assetId}
                         className={styles.listItem}
                         costumeURL={item.url}
                         id={index}
diff --git a/src/components/button/button.css b/src/components/button/button.css
new file mode 100644
index 0000000000000000000000000000000000000000..44243650f970d16aa787b8a44da3763e595802ce
--- /dev/null
+++ b/src/components/button/button.css
@@ -0,0 +1,3 @@
+.button {
+    cursor: pointer;
+}
diff --git a/src/components/button/button.jsx b/src/components/button/button.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..dbc852395625e7e2b3fec55a7a71de91e5e1aa37
--- /dev/null
+++ b/src/components/button/button.jsx
@@ -0,0 +1,31 @@
+const classNames = require('classnames');
+const PropTypes = require('prop-types');
+const React = require('react');
+
+const styles = require('./button.css');
+
+const ButtonComponent = ({
+    className,
+    onClick,
+    children,
+    ...props
+}) => (
+    <span
+        className={classNames(
+            styles.button,
+            className
+        )}
+        role="button"
+        onClick={onClick}
+        {...props}
+    >
+        {children}
+    </span>
+);
+
+ButtonComponent.propTypes = {
+    children: PropTypes.node,
+    className: PropTypes.string,
+    onClick: PropTypes.func.isRequired
+};
+module.exports = ButtonComponent;
diff --git a/src/components/gui/gui.jsx b/src/components/gui/gui.jsx
index 91ed77ec2ada63de1bcb53e85b0a6acd38989c89..9bf21c40de33d13d0edb32d36522bbcac7a728c0 100644
--- a/src/components/gui/gui.jsx
+++ b/src/components/gui/gui.jsx
@@ -19,6 +19,8 @@ const GUIComponent = props => {
         basePath,
         children,
         vm,
+        onTabSelect,
+        tabIndex,
         ...componentProps
     } = props;
     if (children) {
@@ -29,13 +31,6 @@ const GUIComponent = props => {
         );
     }
 
-    // @todo hack to resize blockly manually in case resize happened while hidden
-    const handleTabSelect = tabIndex => {
-        if (tabIndex === 0) {
-            setTimeout(() => window.dispatchEvent(new Event('resize')));
-        }
-    };
-
     return (
         <Box
             className={styles.pageWrapper}
@@ -48,7 +43,7 @@ const GUIComponent = props => {
                         <Tabs
                             className={styles.tabs}
                             forceRenderTabPanel={true} // eslint-disable-line react/jsx-boolean-value
-                            onSelect={handleTabSelect}
+                            onSelect={onTabSelect}
                         >
                             <TabList className={styles.tabList}>
                                 <Tab className={styles.tab}>Scripts</Tab>
@@ -59,6 +54,7 @@ const GUIComponent = props => {
                                 <Box className={styles.blocksWrapper}>
                                     <Blocks
                                         grow={1}
+                                        isVisible={tabIndex === 0} // Scripts tab
                                         options={{
                                             media: `${basePath}static/blocks-media/`
                                         }}
@@ -102,6 +98,8 @@ const GUIComponent = props => {
 GUIComponent.propTypes = {
     basePath: PropTypes.string,
     children: PropTypes.node,
+    onTabSelect: PropTypes.func,
+    tabIndex: PropTypes.number,
     vm: PropTypes.instanceOf(VM).isRequired
 };
 GUIComponent.defaultProps = {
diff --git a/src/components/load-button/load-button.css b/src/components/load-button/load-button.css
new file mode 100644
index 0000000000000000000000000000000000000000..527718028aedbf6ec6636afe0df0625e2005c35c
--- /dev/null
+++ b/src/components/load-button/load-button.css
@@ -0,0 +1,3 @@
+.file-input {
+    display: none;
+}
diff --git a/src/components/load-button/load-button.jsx b/src/components/load-button/load-button.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..29b2962e5a6f2b6642c80ac9449f458f2ea70f85
--- /dev/null
+++ b/src/components/load-button/load-button.jsx
@@ -0,0 +1,36 @@
+const PropTypes = require('prop-types');
+const React = require('react');
+
+const ButtonComponent = require('../button/button.jsx');
+
+const styles = require('./load-button.css');
+
+const LoadButtonComponent = ({
+    inputRef,
+    onChange,
+    onClick,
+    title,
+    ...props
+}) => (
+    <span {...props}>
+        <ButtonComponent onClick={onClick}>{title}</ButtonComponent>
+        <input
+            className={styles.fileInput}
+            ref={inputRef}
+            type="file"
+            onChange={onChange}
+        />
+    </span>
+);
+
+LoadButtonComponent.propTypes = {
+    className: PropTypes.string,
+    inputRef: PropTypes.func.isRequired,
+    onChange: PropTypes.func.isRequired,
+    onClick: PropTypes.func.isRequired,
+    title: PropTypes.string
+};
+LoadButtonComponent.defaultProps = {
+    title: 'Load'
+};
+module.exports = LoadButtonComponent;
diff --git a/src/components/menu-bar/menu-bar.jsx b/src/components/menu-bar/menu-bar.jsx
index b34a2e1900a937ecba22f8d9944f48563136223f..4397b5002ea47789ed47cd3283a6ba917c24373d 100644
--- a/src/components/menu-bar/menu-bar.jsx
+++ b/src/components/menu-bar/menu-bar.jsx
@@ -2,6 +2,9 @@ const classNames = require('classnames');
 const React = require('react');
 
 const Box = require('../box/box.jsx');
+const LoadButton = require('../../containers/load-button.jsx');
+const SaveButton = require('../../containers/save-button.jsx');
+
 const styles = require('./menu-bar.css');
 const scratchLogo = require('./scratch-logo.svg');
 
@@ -18,7 +21,8 @@ const MenuBar = function MenuBar () {
                     src={scratchLogo}
                 />
             </div>
-            <div className={styles.menuItem} >Animation Playtest Prototype</div>
+            <SaveButton className={styles.menuItem} />
+            <LoadButton className={styles.menuItem} />
         </Box>
     );
 };
diff --git a/src/components/sprite-selector/sprite-selector.jsx b/src/components/sprite-selector/sprite-selector.jsx
index df48343745100b55e7f2a1334681b0aec65c3e58..3410c75809e683e67f664d11b01049f003fd0855 100644
--- a/src/components/sprite-selector/sprite-selector.jsx
+++ b/src/components/sprite-selector/sprite-selector.jsx
@@ -53,17 +53,15 @@ const SpriteSelectorComponent = function (props) {
                     {Object.keys(sprites)
                         // Re-order by list order
                         .sort((id1, id2) => sprites[id1].order - sprites[id2].order)
-                        .map(id => (
+                        .map(id => sprites[id])
+                        .map(sprite => (
                             <SpriteSelectorItem
+                                assetId={sprite.costume && sprite.costume.assetId}
                                 className={styles.sprite}
-                                costumeURL={
-                                    sprites[id].costume &&
-                                    sprites[id].costume.url
-                                }
-                                id={id}
-                                key={id}
-                                name={sprites[id].name}
-                                selected={id === selectedId}
+                                id={sprite.id}
+                                key={sprite.id}
+                                name={sprite.name}
+                                selected={sprite.id === selectedId}
                                 onClick={onSelectSprite}
                                 onDeleteButtonClick={onDeleteSprite}
                             />
diff --git a/src/components/stage/stage.css b/src/components/stage/stage.css
index 0b22fa3c6428d30e7dfb40423df8ffd1a679d184..4cc5d309266c0ae0aefd658863d1e9210f794d20 100644
--- a/src/components/stage/stage.css
+++ b/src/components/stage/stage.css
@@ -23,4 +23,5 @@
     left: 0;
     width: 100%;
     height: 100%;
+    pointer-events: none;
 }
diff --git a/src/components/target-pane/target-pane.jsx b/src/components/target-pane/target-pane.jsx
index 5d8fc1915cd185125ad12104a80c341590406895..c779f274713413e13d62851dae45c54223caadaa 100644
--- a/src/components/target-pane/target-pane.jsx
+++ b/src/components/target-pane/target-pane.jsx
@@ -1,5 +1,3 @@
-const isEqual = require('lodash.isequal');
-const omit = require('lodash.omit');
 const classNames = require('classnames');
 const PropTypes = require('prop-types');
 const React = require('react');
@@ -23,119 +21,106 @@ const addIcon = require('./icon--add.svg');
  * @param {object} props Props for the component
  * @returns {React.Component} rendered component
  */
-class TargetPane extends React.Component {
-    shouldComponentUpdate (nextProps) {
-        return (
-            // Do a normal shallow compare on all props except sprites
-            Object.keys(omit(nextProps, ['sprites']))
-                .reduce((all, k) => all || nextProps[k] !== this.props[k], false) ||
-            // Deep compare on sprites object
-            !isEqual(this.props.sprites, nextProps.sprites)
-        );
-    }
-    render () {
-        const {
-            editingTarget,
-            backdropLibraryVisible,
-            costumeLibraryVisible,
-            soundLibraryVisible,
-            spriteLibraryVisible,
-            onChangeSpriteDirection,
-            onChangeSpriteName,
-            onChangeSpriteRotationStyle,
-            onChangeSpriteVisibility,
-            onChangeSpriteX,
-            onChangeSpriteY,
-            onDeleteSprite,
-            onNewSpriteClick,
-            onNewBackdropClick,
-            onRequestCloseBackdropLibrary,
-            onRequestCloseCostumeLibrary,
-            onRequestCloseSoundLibrary,
-            onRequestCloseSpriteLibrary,
-            onSelectSprite,
-            stage,
-            sprites,
-            vm,
-            ...componentProps
-        } = this.props;
-        return (
-            <Box
-                className={styles.targetPane}
-                {...componentProps}
-            >
+const TargetPane = ({
+    editingTarget,
+    backdropLibraryVisible,
+    costumeLibraryVisible,
+    soundLibraryVisible,
+    spriteLibraryVisible,
+    onChangeSpriteDirection,
+    onChangeSpriteName,
+    onChangeSpriteRotationStyle,
+    onChangeSpriteVisibility,
+    onChangeSpriteX,
+    onChangeSpriteY,
+    onDeleteSprite,
+    onNewSpriteClick,
+    onNewBackdropClick,
+    onRequestCloseBackdropLibrary,
+    onRequestCloseCostumeLibrary,
+    onRequestCloseSoundLibrary,
+    onRequestCloseSpriteLibrary,
+    onSelectSprite,
+    stage,
+    sprites,
+    vm,
+    ...componentProps
+}) => (
+    <Box
+        className={styles.targetPane}
+        {...componentProps}
+    >
 
-                <SpriteSelectorComponent
-                    selectedId={editingTarget}
-                    sprites={sprites}
-                    onChangeSpriteDirection={onChangeSpriteDirection}
-                    onChangeSpriteName={onChangeSpriteName}
-                    onChangeSpriteRotationStyle={onChangeSpriteRotationStyle}
-                    onChangeSpriteVisibility={onChangeSpriteVisibility}
-                    onChangeSpriteX={onChangeSpriteX}
-                    onChangeSpriteY={onChangeSpriteY}
-                    onDeleteSprite={onDeleteSprite}
-                    onSelectSprite={onSelectSprite}
-                />
-                <Box className={styles.stageSelectorWrapper}>
-                    {stage.id && <StageSelector
-                        backdropCount={stage.costumeCount}
-                        id={stage.id}
-                        selected={stage.id === editingTarget}
-                        url={
-                            stage.costume &&
-                            stage.costume.url
-                        }
-                        onSelect={onSelectSprite}
-                    />}
-                    <Box>
+        <SpriteSelectorComponent
+            selectedId={editingTarget}
+            sprites={sprites}
+            onChangeSpriteDirection={onChangeSpriteDirection}
+            onChangeSpriteName={onChangeSpriteName}
+            onChangeSpriteRotationStyle={onChangeSpriteRotationStyle}
+            onChangeSpriteVisibility={onChangeSpriteVisibility}
+            onChangeSpriteX={onChangeSpriteX}
+            onChangeSpriteY={onChangeSpriteY}
+            onDeleteSprite={onDeleteSprite}
+            onSelectSprite={onSelectSprite}
+        />
+        <Box className={styles.stageSelectorWrapper}>
+            {stage.id && <StageSelector
+                assetId={
+                    stage.costume &&
+                    stage.costume.assetId
+                }
+                backdropCount={stage.costumeCount}
+                id={stage.id}
+                selected={stage.id === editingTarget}
+                onSelect={onSelectSprite}
+            />}
+            <Box>
 
-                        <button
-                            className={classNames(styles.addButtonWrapper, styles.addButtonWrapperSprite)}
-                            onClick={onNewSpriteClick}
-                        >
-                            <img
-                                className={styles.addButton}
-                                src={addIcon}
-                            />
-                        </button>
+                <button
+                    className={classNames(styles.addButtonWrapper, styles.addButtonWrapperSprite)}
+                    onClick={onNewSpriteClick}
+                >
+                    <img
+                        className={styles.addButton}
+                        src={addIcon}
+                    />
+                </button>
 
-                        <button
-                            className={classNames(styles.addButtonWrapper, styles.addButtonWrapperStage)}
-                            onClick={onNewBackdropClick}
-                        >
-                            <img
-                                className={styles.addButton}
-                                src={addIcon}
-                            />
-                        </button>
+                <button
+                    className={classNames(styles.addButtonWrapper, styles.addButtonWrapperStage)}
+                    onClick={onNewBackdropClick}
+                >
+                    <img
+                        className={styles.addButton}
+                        src={addIcon}
+                    />
+                </button>
 
-                        <SpriteLibrary
-                            visible={spriteLibraryVisible}
-                            vm={vm}
-                            onRequestClose={onRequestCloseSpriteLibrary}
-                        />
-                        <CostumeLibrary
-                            visible={costumeLibraryVisible}
-                            vm={vm}
-                            onRequestClose={onRequestCloseCostumeLibrary}
-                        />
-                        <SoundLibrary
-                            visible={soundLibraryVisible}
-                            vm={vm}
-                            onRequestClose={onRequestCloseSoundLibrary}
-                        />
-                        <BackdropLibrary
-                            visible={backdropLibraryVisible}
-                            vm={vm}
-                            onRequestClose={onRequestCloseBackdropLibrary}
-                        />
-                    </Box>
-                </Box>
+                <SpriteLibrary
+                    visible={spriteLibraryVisible}
+                    vm={vm}
+                    onRequestClose={onRequestCloseSpriteLibrary}
+                />
+                <CostumeLibrary
+                    visible={costumeLibraryVisible}
+                    vm={vm}
+                    onRequestClose={onRequestCloseCostumeLibrary}
+                />
+                <SoundLibrary
+                    visible={soundLibraryVisible}
+                    vm={vm}
+                    onRequestClose={onRequestCloseSoundLibrary}
+                />
+                <BackdropLibrary
+                    visible={backdropLibraryVisible}
+                    vm={vm}
+                    onRequestClose={onRequestCloseBackdropLibrary}
+                />
             </Box>
-        );
-    }
-}
+        </Box>
+    </Box>
+);
+
 const spriteShape = PropTypes.shape({
     costume: PropTypes.shape({
         url: PropTypes.string,
diff --git a/src/containers/blocks.jsx b/src/containers/blocks.jsx
index ecd816204ee5a7d760e04a67d0f34599065eb1f6..58d5cb2e1b616b2fce1121d9ba004f949b52a65a 100644
--- a/src/containers/blocks.jsx
+++ b/src/containers/blocks.jsx
@@ -52,7 +52,21 @@ class Blocks extends React.Component {
         this.attachVM();
     }
     shouldComponentUpdate (nextProps, nextState) {
-        return this.state.prompt !== nextState.prompt;
+        return this.state.prompt !== nextState.prompt || this.props.isVisible !== nextProps.isVisible;
+    }
+    componentDidUpdate (prevProps) {
+        if (this.props.isVisible === prevProps.isVisible) {
+            return;
+        }
+
+        // @todo hack to resize blockly manually in case resize happened while hidden
+        if (this.props.isVisible) { // Scripts tab
+            window.dispatchEvent(new Event('resize'));
+            this.workspace.setVisible(true);
+            this.workspace.toolbox_.refreshSelection();
+        } else {
+            this.workspace.setVisible(false);
+        }
     }
     componentWillUnmount () {
         this.detachVM();
@@ -146,6 +160,7 @@ class Blocks extends React.Component {
         const {
             options, // eslint-disable-line no-unused-vars
             vm, // eslint-disable-line no-unused-vars
+            isVisible, // eslint-disable-line no-unused-vars
             ...props
         } = this.props;
         return (
@@ -169,11 +184,12 @@ class Blocks extends React.Component {
 }
 
 Blocks.propTypes = {
+    isVisible: PropTypes.bool.isRequired,
     options: PropTypes.shape({
         media: PropTypes.string,
         zoom: PropTypes.shape({
-            controls: PropTypes.boolean,
-            wheel: PropTypes.boolean,
+            controls: PropTypes.bool,
+            wheel: PropTypes.bool,
             startScale: PropTypes.number
         }),
         colours: PropTypes.shape({
diff --git a/src/containers/costume-tab.jsx b/src/containers/costume-tab.jsx
index 2c6c04a7e65e777d575a9e009555a5543ecbce10..24f54bc7832152757c7b0cfb9fcccc2050729d2c 100644
--- a/src/containers/costume-tab.jsx
+++ b/src/containers/costume-tab.jsx
@@ -38,7 +38,7 @@ class CostumeTab extends React.Component {
         editingTarget.sprite.costumes = editingTarget.sprite.costumes
             .slice(0, costumeIndex)
             .concat(editingTarget.sprite.costumes.slice(costumeIndex + 1));
-        this.props.vm.runtime.spriteInfoReport(editingTarget);
+        this.props.vm.runtime.requestTargetsUpdate(editingTarget);
         // @todo not sure if this is getting redrawn correctly
         this.props.vm.runtime.requestRedraw();
 
diff --git a/src/containers/gui.jsx b/src/containers/gui.jsx
index dec5c6c6d671587f28259b64f9f2841d8527af7f..fbc11d7da672f36029eb3a5c8373b17ac5e44fbe 100644
--- a/src/containers/gui.jsx
+++ b/src/containers/gui.jsx
@@ -1,12 +1,20 @@
 const PropTypes = require('prop-types');
 const React = require('react');
 const VM = require('scratch-vm');
+const bindAll = require('lodash.bindall');
 
 const vmListenerHOC = require('../lib/vm-listener-hoc.jsx');
 
 const GUIComponent = require('../components/gui/gui.jsx');
 
 class GUI extends React.Component {
+    constructor (props) {
+        super(props);
+        bindAll(this, [
+            'handleTabSelect'
+        ]);
+        this.state = {tabIndex: 0};
+    }
     componentDidMount () {
         this.props.vm.loadProject(this.props.projectData);
         this.props.vm.setCompatibilityMode(true);
@@ -20,6 +28,9 @@ class GUI extends React.Component {
     componentWillUnmount () {
         this.props.vm.stopAll();
     }
+    handleTabSelect (tabIndex) {
+        this.setState({tabIndex});
+    }
     render () {
         const {
             projectData, // eslint-disable-line no-unused-vars
@@ -28,7 +39,9 @@ class GUI extends React.Component {
         } = this.props;
         return (
             <GUIComponent
+                tabIndex={this.state.tabIndex}
                 vm={vm}
+                onTabSelect={this.handleTabSelect}
                 {...componentProps}
             />
         );
diff --git a/src/containers/load-button.jsx b/src/containers/load-button.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..dcbd4fe016094c04c940428758c6c858b682deb0
--- /dev/null
+++ b/src/containers/load-button.jsx
@@ -0,0 +1,55 @@
+const bindAll = require('lodash.bindall');
+const PropTypes = require('prop-types');
+const React = require('react');
+const {connect} = require('react-redux');
+
+const LoadButtonComponent = require('../components/load-button/load-button.jsx');
+
+class LoadButton extends React.Component {
+    constructor (props) {
+        super(props);
+        bindAll(this, [
+            'setFileInput',
+            'handleChange',
+            'handleClick'
+        ]);
+    }
+    handleChange (e) {
+        const reader = new FileReader();
+        reader.onload = () => this.props.loadProject(reader.result);
+        reader.readAsText(e.target.files[0]);
+    }
+    handleClick () {
+        this.fileInput.click();
+    }
+    setFileInput (input) {
+        this.fileInput = input;
+    }
+    render () {
+        const {
+            loadProject, // eslint-disable-line no-unused-vars
+            ...props
+        } = this.props;
+        return (
+            <LoadButtonComponent
+                inputRef={this.setFileInput}
+                onChange={this.handleChange}
+                onClick={this.handleClick}
+                {...props}
+            />
+        );
+    }
+}
+
+LoadButton.propTypes = {
+    loadProject: PropTypes.func.isRequired
+};
+
+const mapStateToProps = state => ({
+    loadProject: state.vm.fromJSON.bind(state.vm)
+});
+
+module.exports = connect(
+    mapStateToProps,
+    () => ({}) // omit dispatch prop
+)(LoadButton);
diff --git a/src/containers/save-button.jsx b/src/containers/save-button.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..f5e7ab018681e8008171ac64e8964db3e77a59ec
--- /dev/null
+++ b/src/containers/save-button.jsx
@@ -0,0 +1,62 @@
+const bindAll = require('lodash.bindall');
+const PropTypes = require('prop-types');
+const React = require('react');
+const {connect} = require('react-redux');
+
+const ButtonComponent = require('../components/button/button.jsx');
+
+class SaveButton extends React.Component {
+    constructor (props) {
+        super(props);
+        bindAll(this, [
+            'handleClick'
+        ]);
+    }
+    handleClick () {
+        const json = this.props.saveProjectSb3();
+
+        // Download project data into a file - create link element,
+        // simulate click on it, and then remove it.
+        const saveLink = document.createElement('a');
+        document.body.appendChild(saveLink);
+
+        const data = new Blob([json], {type: 'text'});
+        const url = window.URL.createObjectURL(data);
+        saveLink.href = url;
+
+        // File name: project-DATE-TIME
+        const date = new Date();
+        const timestamp = `${date.toLocaleDateString()}-${date.toLocaleTimeString()}`;
+        saveLink.download = `project-${timestamp}.json`;
+        saveLink.click();
+        window.URL.revokeObjectURL(url);
+        document.body.removeChild(saveLink);
+    }
+    render () {
+        const {
+            saveProjectSb3, // eslint-disable-line no-unused-vars
+            ...props
+        } = this.props;
+        return (
+            <ButtonComponent
+                onClick={this.handleClick}
+                {...props}
+            >
+                Save
+            </ButtonComponent>
+        );
+    }
+}
+
+SaveButton.propTypes = {
+    saveProjectSb3: PropTypes.func.isRequired
+};
+
+const mapStateToProps = state => ({
+    saveProjectSb3: state.vm.saveProjectSb3.bind(state.vm)
+});
+
+module.exports = connect(
+    mapStateToProps,
+    () => ({}) // omit dispatch prop
+)(SaveButton);
diff --git a/src/containers/sprite-selector-item.jsx b/src/containers/sprite-selector-item.jsx
index a9182996e171321066dc8cf52233816b32b6aa4f..d6c738cb3002688b3d812367f30b8cd8e27a1406 100644
--- a/src/containers/sprite-selector-item.jsx
+++ b/src/containers/sprite-selector-item.jsx
@@ -2,6 +2,8 @@ const bindAll = require('lodash.bindall');
 const PropTypes = require('prop-types');
 const React = require('react');
 
+const {connect} = require('react-redux');
+
 const SpriteSelectorItemComponent = require('../components/sprite-selector-item/sprite-selector-item.jsx');
 
 class SpriteSelectorItem extends React.Component {
@@ -24,9 +26,12 @@ class SpriteSelectorItem extends React.Component {
     }
     render () {
         const {
-            id, // eslint-disable-line no-unused-vars
-            onClick, // eslint-disable-line no-unused-vars
-            onDeleteButtonClick, // eslint-disable-line no-unused-vars
+            /* eslint-disable no-unused-vars */
+            assetId,
+            id,
+            onClick,
+            onDeleteButtonClick,
+            /* eslint-enable no-unused-vars */
             ...props
         } = this.props;
         return (
@@ -40,6 +45,7 @@ class SpriteSelectorItem extends React.Component {
 }
 
 SpriteSelectorItem.propTypes = {
+    assetId: PropTypes.string,
     costumeURL: PropTypes.string,
     id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
     name: PropTypes.string,
@@ -48,4 +54,10 @@ SpriteSelectorItem.propTypes = {
     selected: PropTypes.bool
 };
 
-module.exports = SpriteSelectorItem;
+const mapStateToProps = (state, {assetId, costumeURL}) => ({
+    costumeURL: costumeURL || (assetId && state.vm.runtime.storage.get(assetId).encodeDataURI())
+});
+
+module.exports = connect(
+    mapStateToProps
+)(SpriteSelectorItem);
diff --git a/src/containers/stage-selector.jsx b/src/containers/stage-selector.jsx
index d37a4437c51d2c6c8b6b631005fc5a938e3f7256..9b4b83d0d7a3efcdd98697915af2da8c51ba6a62 100644
--- a/src/containers/stage-selector.jsx
+++ b/src/containers/stage-selector.jsx
@@ -2,6 +2,8 @@ const bindAll = require('lodash.bindall');
 const PropTypes = require('prop-types');
 const React = require('react');
 
+const {connect} = require('react-redux');
+
 const StageSelectorComponent = require('../components/stage-selector/stage-selector.jsx');
 
 class StageSelector extends React.Component {
@@ -18,6 +20,7 @@ class StageSelector extends React.Component {
     render () {
         const {
             /* eslint-disable no-unused-vars */
+            assetId,
             id,
             onSelect,
             /* eslint-enable no-unused-vars */
@@ -36,4 +39,12 @@ StageSelector.propTypes = {
     id: PropTypes.string,
     onSelect: PropTypes.func
 };
-module.exports = StageSelector;
+
+const mapStateToProps = (state, {assetId}) => ({
+    url: assetId && state.vm.runtime.storage.get(assetId).encodeDataURI()
+});
+
+module.exports = connect(
+    mapStateToProps,
+    () => ({}) // omit dispatch prop
+)(StageSelector);
diff --git a/src/lib/vm-listener-hoc.jsx b/src/lib/vm-listener-hoc.jsx
index 8c80ae5d9694711a50a3974aa2704883d57de76e..d2a7b0ca572967f990df5356073f35c8f0935f1f 100644
--- a/src/lib/vm-listener-hoc.jsx
+++ b/src/lib/vm-listener-hoc.jsx
@@ -3,8 +3,6 @@ const PropTypes = require('prop-types');
 const React = require('react');
 const VM = require('scratch-vm');
 
-const Storage = require('./storage');
-
 const {connect} = require('react-redux');
 
 const targets = require('../reducers/targets');
@@ -29,7 +27,6 @@ const vmListenerHOC = function (WrappedComponent) {
             // If the wrapped component uses the vm in componentDidMount, then
             // we need to start listening before mounting the wrapped component.
             this.props.vm.on('targetsUpdate', this.props.onTargetsUpdate);
-            this.props.vm.on('SPRITE_INFO_REPORT', this.props.onSpriteInfoReport);
         }
         componentDidMount () {
             if (this.props.attachKeyboardEvents) {
@@ -92,20 +89,16 @@ const vmListenerHOC = function (WrappedComponent) {
         onTargetsUpdate: PropTypes.func,
         vm: PropTypes.instanceOf(VM).isRequired
     };
-    const defaultVM = new VM('vm-listener-hoc');
-    defaultVM.attachStorage(new Storage());
     VMListener.defaultProps = {
-        attachKeyboardEvents: true,
-        vm: defaultVM
+        attachKeyboardEvents: true
     };
-    const mapStateToProps = () => ({});
+    const mapStateToProps = state => ({
+        vm: state.vm
+    });
     const mapDispatchToProps = dispatch => ({
         onTargetsUpdate: data => {
             dispatch(targets.updateEditingTarget(data.editingTarget));
             dispatch(targets.updateTargets(data.targetList));
-        },
-        onSpriteInfoReport: spriteInfo => {
-            dispatch(targets.updateTarget(spriteInfo));
         }
     });
     return connect(
diff --git a/src/reducers/gui.js b/src/reducers/gui.js
index bde1a2f3f1c6a02d9a8e1a7131754ef91ee3f33d..9b1cf60671fd255e31ba620dbdff2dd1d6f280ef 100644
--- a/src/reducers/gui.js
+++ b/src/reducers/gui.js
@@ -2,6 +2,7 @@ const {combineReducers} = require('redux');
 
 module.exports = combineReducers({
     modals: require('./modals'),
+    monitors: require('./monitors'),
     targets: require('./targets'),
-    monitors: require('./monitors')
+    vm: require('./vm')
 });
diff --git a/src/reducers/targets.js b/src/reducers/targets.js
index c2f6219acea9de791eedbbe496bc0926448fe48f..0ed67cf2de94ceadf32e143037321458c5347a68 100644
--- a/src/reducers/targets.js
+++ b/src/reducers/targets.js
@@ -1,8 +1,5 @@
-const defaultsDeep = require('lodash.defaultsdeep');
-
 const UPDATE_EDITING_TARGET = 'scratch-gui/targets/UPDATE_EDITING_TARGET';
 const UPDATE_TARGET_LIST = 'scratch-gui/targets/UPDATE_TARGET_LIST';
-const UPDATE_TARGET = 'scratch/targets/UPDATE_TARGET';
 
 const initialState = {
     sprites: {},
@@ -12,39 +9,19 @@ const initialState = {
 const reducer = function (state, action) {
     if (typeof state === 'undefined') state = initialState;
     switch (action.type) {
-    case UPDATE_TARGET:
-        if (action.target.id === state.stage.id) {
-            return Object.assign({}, state, {
-                stage: Object.assign({}, state.stage, action.target)
-            });
-        }
-        return Object.assign({}, state, {
-            sprites: defaultsDeep(
-                {[action.target.id]: action.target},
-                state.sprites
-            )
-        });
     case UPDATE_TARGET_LIST:
         return Object.assign({}, state, {
             sprites: action.targets
                 .filter(target => !target.isStage)
                 .reduce(
-                    (targets, target, listId) => defaultsDeep(
-                        {[target.id]: {order: listId, ...target}},
-                        {[target.id]: state.sprites[target.id]},
-                        targets
+                    (targets, target, listId) => Object.assign(
+                        targets,
+                        {[target.id]: {order: listId, ...target}}
                     ),
                     {}
                 ),
             stage: action.targets
-                .filter(target => target.isStage)
-                .reduce(
-                    (stage, target) => {
-                        if (target.id !== stage.id) return target;
-                        return defaultsDeep(target, stage);
-                    },
-                    state.stage
-                )
+                .filter(target => target.isStage)[0] || {}
         });
     case UPDATE_EDITING_TARGET:
         return Object.assign({}, state, {editingTarget: action.target});
@@ -52,15 +29,6 @@ const reducer = function (state, action) {
         return state;
     }
 };
-reducer.updateTarget = function (target) {
-    return {
-        type: UPDATE_TARGET,
-        target: target,
-        meta: {
-            throttle: 30
-        }
-    };
-};
 reducer.updateTargets = function (targetList) {
     return {
         type: UPDATE_TARGET_LIST,
diff --git a/src/reducers/vm.js b/src/reducers/vm.js
new file mode 100644
index 0000000000000000000000000000000000000000..1fd0eb4a2f199b7329783d825445adcf550b6176
--- /dev/null
+++ b/src/reducers/vm.js
@@ -0,0 +1,24 @@
+const VM = require('scratch-vm');
+const Storage = require('../lib/storage');
+
+const SET_VM = 'scratch-gui/vm/SET_VM';
+const defaultVM = new VM();
+defaultVM.attachStorage(new Storage());
+const initialState = defaultVM;
+
+const reducer = function (state, action) {
+    if (typeof state === 'undefined') state = initialState;
+    switch (action.type) {
+    case SET_VM:
+        return action.vm;
+    default:
+        return state;
+    }
+};
+reducer.setVM = function (vm) {
+    return {
+        type: SET_VM,
+        vm: vm
+    };
+};
+module.exports = reducer;