diff --git a/package.json b/package.json
index a58e55026ce6de481ac05f110b597435926d7c32..b8649d8c1e8dd0e430e9eae5c1534f69007606bf 100644
--- a/package.json
+++ b/package.json
@@ -91,7 +91,7 @@
     "scratch-audio": "0.1.0-prerelease.1516198804",
     "scratch-blocks": "0.1.0-prerelease.1519256473",
     "scratch-l10n": "2.0.20180108132626",
-    "scratch-paint": "0.2.0-prerelease.20180227161624",
+    "scratch-paint": "0.2.0-prerelease.20180302160120",
     "scratch-render": "0.1.0-prerelease.1516837442",
     "scratch-storage": "0.4.0",
     "scratch-vm": "0.1.0-prerelease.1519681201-prerelease.1519681262",
diff --git a/src/components/crash-message/crash-message.css b/src/components/crash-message/crash-message.css
new file mode 100644
index 0000000000000000000000000000000000000000..605f7fdab9e745a602bdb1d9ed32aa123de1b819
--- /dev/null
+++ b/src/components/crash-message/crash-message.css
@@ -0,0 +1,28 @@
+@import "../../css/colors.css";
+@import "../../css/units.css";
+@import "../../css/typography.css";
+
+.crash-wrapper {
+    background-color: $motion-primary;
+    width: 100%;
+    height: 100%;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+.body {
+    width: 35%;
+    color: white;
+    text-align: center;
+}
+
+.reloadButton {
+    border: 1px solid $motion-primary;
+    border-radius: 0.25rem;
+    padding: 0.5rem 2rem;
+    background: white;
+    color: $motion-primary;
+    font-weight: bold;
+    font-size: 0.875rem;
+    cursor: pointer;
+}
diff --git a/src/components/crash-message/crash-message.jsx b/src/components/crash-message/crash-message.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..d5fc45d163072d6394c5da665ee6427b6d0159a4
--- /dev/null
+++ b/src/components/crash-message/crash-message.jsx
@@ -0,0 +1,38 @@
+import PropTypes from 'prop-types';
+import React from 'react';
+import Box from '../box/box.jsx';
+
+import styles from './crash-message.css';
+import reloadIcon from './reload.svg';
+
+const CrashMessage = props => (
+    <div className={styles.crashWrapper}>
+        <Box className={styles.body}>
+            <img
+                className={styles.reloadIcon}
+                src={reloadIcon}
+            />
+            <h2>
+                Oops! Something went wrong.
+            </h2>
+            <p>
+                We are so sorry, but it looks like Scratch has crashed. This bug has been
+                automatically reported to the Scratch Team. Please refresh your page to try
+                again.
+
+            </p>
+            <button
+                className={styles.reloadButton}
+                onClick={props.onReload}
+            >
+                Reload
+            </button>
+        </Box>
+    </div>
+);
+
+CrashMessage.propTypes = {
+    onReload: PropTypes.func.isRequired
+};
+
+export default CrashMessage;
diff --git a/src/components/crash-message/reload.svg b/src/components/crash-message/reload.svg
new file mode 100644
index 0000000000000000000000000000000000000000..b74601fac9d4aaaaf53b50a26411b86949c2e5f3
Binary files /dev/null and b/src/components/crash-message/reload.svg differ
diff --git a/src/components/gui/gui.jsx b/src/components/gui/gui.jsx
index 5c7a378dc43c44ff9f3d5d37e3b9ae79ffbbe87f..b7f2a0acd1d73abf9f683dd8c7d3505394c8a441 100644
--- a/src/components/gui/gui.jsx
+++ b/src/components/gui/gui.jsx
@@ -14,7 +14,7 @@ import TargetPane from '../../containers/target-pane.jsx';
 import SoundTab from '../../containers/sound-tab.jsx';
 import StageHeader from '../../containers/stage-header.jsx';
 import Stage from '../../containers/stage.jsx';
-
+import Loader from '../loader/loader.jsx';
 import Box from '../box/box.jsx';
 import FeedbackForm from '../feedback-form/feedback-form.jsx';
 import MenuBar from '../menu-bar/menu-bar.jsx';
@@ -44,6 +44,7 @@ const GUIComponent = props => {
         feedbackFormVisible,
         importInfoVisible,
         intl,
+        loading,
         onExtensionButtonClick,
         onActivateTab,
         previewInfoVisible,
@@ -78,6 +79,9 @@ const GUIComponent = props => {
             {previewInfoVisible ? (
                 <PreviewModal />
             ) : null}
+            {loading ? (
+                <Loader />
+            ) : null}
             {importInfoVisible ? (
                 <ImportModal />
             ) : null}
@@ -176,6 +180,7 @@ GUIComponent.propTypes = {
     feedbackFormVisible: PropTypes.bool,
     importInfoVisible: PropTypes.bool,
     intl: intlShape.isRequired,
+    loading: PropTypes.bool,
     onActivateTab: PropTypes.func,
     onExtensionButtonClick: PropTypes.func,
     onTabSelect: PropTypes.func,
diff --git a/src/components/loader/bottom-block.svg b/src/components/loader/bottom-block.svg
new file mode 100644
index 0000000000000000000000000000000000000000..b397068c448eeabc04d4245e1f5cdd210b72df5c
Binary files /dev/null and b/src/components/loader/bottom-block.svg differ
diff --git a/src/components/loader/loader.css b/src/components/loader/loader.css
new file mode 100644
index 0000000000000000000000000000000000000000..68f8e5f4f08f852f5f1ac3c968d30e5c33729a8e
--- /dev/null
+++ b/src/components/loader/loader.css
@@ -0,0 +1,89 @@
+@import "../../css/colors.css";
+
+.background {
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    z-index: 999; /* Below preview modal */
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    background-color: $motion-primary;
+    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+    text-align: center;
+    color: white;
+}
+
+.block-animation {
+    width: 125px;
+    height: 150px;
+    margin: 50px auto 0px;
+}
+
+.block-animation img {
+    display: block;
+    position: relative;
+    height: 30%;
+    margin-top: -4px;
+}
+
+.topBlock {
+    animation: top-slide-in 1.5s ease infinite;
+}
+
+.middleBlock {
+    animation: middle-slide-in 1.5s ease infinite;
+}
+
+.bottomBlock {
+    animation: bottom-slide-in 1.5s ease infinite;
+}
+
+
+@keyframes top-slide-in {
+  0% {
+    transform: translateY(50px);
+    opacity: 0;
+  }
+
+  33% {
+    transform: translateY(0px);
+    opacity: 1;
+  }
+}
+
+@keyframes middle-slide-in {
+  0% {
+    transform: translateY(50px);
+    opacity: 0;
+  }
+
+  33% {
+    transform: translateY(50px);
+    opacity: 0;
+  }
+
+  66% {
+    transform: translateY(0px);
+    opacity: 1;
+  }
+}
+
+@keyframes bottom-slide-in {
+  0% {
+    transform: translateY(50px);
+    opacity: 0;
+  }
+
+  66% {
+    transform: translateY(50px);
+    opacity: 0;
+  }
+
+  100% {
+    transform: translateY(0px);
+    opacity: 1;
+  }
+}
diff --git a/src/components/loader/loader.jsx b/src/components/loader/loader.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..8a93e5c36abd385665c9fcdd1374f30096d9c0a8
--- /dev/null
+++ b/src/components/loader/loader.jsx
@@ -0,0 +1,144 @@
+import React from 'react';
+import {FormattedMessage} from 'react-intl';
+import styles from './loader.css';
+
+import topBlock from './top-block.svg';
+import middleBlock from './middle-block.svg';
+import bottomBlock from './bottom-block.svg';
+
+const LoaderComponent = () => {
+    const messages = [
+        {
+            message: (
+                <FormattedMessage
+                    defaultMessage="Creating blocks …"
+                    description="One of the loading messages"
+                    id="gui.loader.message1"
+                />
+            ),
+            weight: 50
+        },
+        {
+            message: (
+                <FormattedMessage
+                    defaultMessage="Loading sprites …"
+                    description="One of the loading messages"
+                    id="gui.loader.message2"
+                />
+            ),
+            weight: 50
+        },
+        {
+            message: (
+                <FormattedMessage
+                    defaultMessage="Loading sounds …"
+                    description="One of the loading messages"
+                    id="gui.loader.message3"
+                />
+            ),
+            weight: 50
+        },
+        {
+            message: (
+                <FormattedMessage
+                    defaultMessage="Loading extensions …"
+                    description="One of the loading messages"
+                    id="gui.loader.message4"
+                />
+            ),
+            weight: 50
+        },
+        {
+            message: (
+                <FormattedMessage
+                    defaultMessage="Creating blocks …"
+                    description="One of the loading messages"
+                    id="gui.loader.message1"
+                />
+            ),
+            weight: 20
+        },
+        {
+            message: (
+                <FormattedMessage
+                    defaultMessage="Herding cats …"
+                    description="One of the loading messages"
+                    id="gui.loader.message5"
+                />
+            ),
+            weight: 1
+        },
+        {
+            message: (
+                <FormattedMessage
+                    defaultMessage="Transmitting nanos …"
+                    description="One of the loading messages"
+                    id="gui.loader.message6"
+                />
+            ),
+            weight: 1
+        },
+        {
+            message: (
+                <FormattedMessage
+                    defaultMessage="Inflating gobos …"
+                    description="One of the loading messages"
+                    id="gui.loader.message7"
+                />
+            ),
+            weight: 1
+        },
+        {
+            message: (
+                <FormattedMessage
+                    defaultMessage="Preparing emojiis …"
+                    description="One of the loading messages"
+                    id="gui.loader.message8"
+                />
+            ),
+            weight: 1
+        }
+    ];
+
+    let message;
+    const sum = messages.reduce((acc, m) => acc + m.weight, 0);
+    let rand = sum * Math.random();
+    for (let i = 0; i < messages.length; i++) {
+        rand -= messages[i].weight;
+        if (rand <= 0) {
+            message = messages[i].message;
+            break;
+        }
+    }
+
+    return (
+        <div className={styles.background}>
+            <div className={styles.container}>
+                <div className={styles.blockAnimation}>
+                    <img
+                        className={styles.topBlock}
+                        src={topBlock}
+                    />
+                    <img
+                        className={styles.middleBlock}
+                        src={middleBlock}
+                    />
+                    <img
+                        className={styles.bottomBlock}
+                        src={bottomBlock}
+                    />
+                </div>
+                <h1 className={styles.title}>
+                    <FormattedMessage
+                        defaultMessage="Loading Project"
+                        description="Main loading message"
+                        id="gui.loader.headline"
+                    />
+                </h1>
+                <p>{message}</p>
+            </div>
+        </div>
+    );
+};
+
+export default LoaderComponent;
diff --git a/src/components/loader/middle-block.svg b/src/components/loader/middle-block.svg
new file mode 100644
index 0000000000000000000000000000000000000000..6e52d4213a9e8bfff2c8a0289fa324cfcbd60c27
Binary files /dev/null and b/src/components/loader/middle-block.svg differ
diff --git a/src/components/loader/top-block.svg b/src/components/loader/top-block.svg
new file mode 100644
index 0000000000000000000000000000000000000000..2b52a0d5d09684056643fb04aec7c80967569c95
Binary files /dev/null and b/src/components/loader/top-block.svg differ
diff --git a/src/containers/error-boundary.jsx b/src/containers/error-boundary.jsx
index 210520bf51bddc91260132c78900cf941e6a5646..d7f558c166f3da16eb00b4a88423add555a994e1 100644
--- a/src/containers/error-boundary.jsx
+++ b/src/containers/error-boundary.jsx
@@ -2,6 +2,7 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import platform from 'platform';
 import BrowserModalComponent from '../components/browser-modal/browser-modal.jsx';
+import CrashMessageComponent from '../components/crash-message/crash-message.jsx';
 import log from '../lib/log.js';
 import analytics from '../lib/analytics';
 
@@ -28,21 +29,16 @@ class ErrorBoundary extends React.Component {
         window.history.back();
     }
 
+    handleReload () {
+        window.location.replace(window.location.origin);
+    }
+
     render () {
         if (this.state.hasError) {
             if (platform.name === 'IE') {
                 return <BrowserModalComponent onBack={this.handleBack} />;
             }
-            return (
-                <div style={{margin: '2rem'}}>
-                    <h1>Oops! Something went wrong.</h1>
-                    <p>
-                        We are so sorry, but it looks like Scratch has crashed. This bug has been
-                        automatically reported to the Scratch Team. Please refresh your page to try
-                        again.
-                    </p>
-                </div>
-            );
+            return <CrashMessageComponent onReload={this.handleReload} />;
         }
         return this.props.children;
     }
diff --git a/src/containers/gui.jsx b/src/containers/gui.jsx
index de4fe27a284623c4058f07e62da59d32fd378643..320eedcdb6661a076d39bea33892c9e4a0deefa4 100644
--- a/src/containers/gui.jsx
+++ b/src/containers/gui.jsx
@@ -17,16 +17,29 @@ import vmListenerHOC from '../lib/vm-listener-hoc.jsx';
 import GUIComponent from '../components/gui/gui.jsx';
 
 class GUI extends React.Component {
+    constructor (props) {
+        super(props);
+        this.state = {
+            loading: true
+        };
+    }
     componentDidMount () {
         this.audioEngine = new AudioEngine();
         this.props.vm.attachAudioEngine(this.audioEngine);
-        this.props.vm.loadProject(this.props.projectData);
-        this.props.vm.setCompatibilityMode(true);
-        this.props.vm.start();
+        this.props.vm.loadProject(this.props.projectData).then(() => {
+            this.setState({loading: false}, () => {
+                this.props.vm.setCompatibilityMode(true);
+                this.props.vm.start();
+            });
+        });
     }
     componentWillReceiveProps (nextProps) {
         if (this.props.projectData !== nextProps.projectData) {
-            this.props.vm.loadProject(nextProps.projectData);
+            this.setState({loading: true}, () => {
+                this.props.vm.loadProject(nextProps.projectData).then(() => {
+                    this.setState({loading: false});
+                });
+            });
         }
     }
     componentWillUnmount () {
@@ -35,12 +48,14 @@ class GUI extends React.Component {
     render () {
         const {
             children,
+            fetchingProject,
             projectData, // eslint-disable-line no-unused-vars
             vm,
             ...componentProps
         } = this.props;
         return (
             <GUIComponent
+                loading={fetchingProject || this.state.loading}
                 vm={vm}
                 {...componentProps}
             >
@@ -53,6 +68,7 @@ class GUI extends React.Component {
 GUI.propTypes = {
     ...GUIComponent.propTypes,
     feedbackFormVisible: PropTypes.bool,
+    fetchingProject: PropTypes.bool,
     importInfoVisible: PropTypes.bool,
     previewInfoVisible: PropTypes.bool,
     projectData: PropTypes.string,
diff --git a/src/lib/default-project/5c81a336fab8be57adc039a8a2b33ca9.png b/src/lib/default-project/5c81a336fab8be57adc039a8a2b33ca9.png
deleted file mode 100755
index da373d2cf3ab7c4c617d307eec5a044ae43917ee..0000000000000000000000000000000000000000
Binary files a/src/lib/default-project/5c81a336fab8be57adc039a8a2b33ca9.png and /dev/null differ
diff --git a/src/lib/default-project/index.js b/src/lib/default-project/index.js
index bc1ace99984c8fc8982f59dcba5fdcb3f3bb7386..d0589f6113eac9ceb788f2b0020d95b29bb6efe4 100644
--- a/src/lib/default-project/index.js
+++ b/src/lib/default-project/index.js
@@ -5,7 +5,6 @@ import projectJson from './project.json';
 import popWav from '!buffer-loader!./83a9787d4cb6f3b7632b4ddfebf74367.wav';
 import meowWav from '!buffer-loader!./83c36d806dc92327b9e7049a565c6bff.wav';
 import backdrop from '!buffer-loader!./739b5e2a2435f6e1ec2993791b423146.png';
-import penLayer from '!buffer-loader!./5c81a336fab8be57adc039a8a2b33ca9.png';
 import costume1 from '!raw-loader!./09dc888b0b7df19f70d81588ae73420e.svg';
 import costume2 from '!raw-loader!./3696356a03a8d938318876a593572843.svg';
 /* eslint-enable import/no-unresolved */
@@ -31,11 +30,6 @@ export default [{
     assetType: 'ImageBitmap',
     dataFormat: 'PNG',
     data: backdrop
-}, {
-    id: '5c81a336fab8be57adc039a8a2b33ca9',
-    assetType: 'ImageBitmap',
-    dataFormat: 'PNG',
-    data: penLayer
 }, {
     id: '09dc888b0b7df19f70d81588ae73420e',
     assetType: 'ImageVector',
diff --git a/src/lib/default-project/project.json b/src/lib/default-project/project.json
old mode 100644
new mode 100755
index 165f391e361ecc1b98b1b6f602a0e471858a6098..c1ae335d848b25a005b0fc353766ce6a5be05042
--- a/src/lib/default-project/project.json
+++ b/src/lib/default-project/project.json
@@ -1,67 +1 @@
-{
-    "objName": "Stage",
-    "sounds": [{
-            "soundName": "pop",
-            "soundID": 1,
-            "md5": "83a9787d4cb6f3b7632b4ddfebf74367.wav",
-            "sampleCount": 258,
-            "rate": 11025,
-            "format": ""
-        }],
-    "costumes": [{
-            "costumeName": "backdrop1",
-            "baseLayerID": 2,
-            "baseLayerMD5": "739b5e2a2435f6e1ec2993791b423146.png",
-            "bitmapResolution": 1,
-            "rotationCenterX": 240,
-            "rotationCenterY": 180
-        }],
-    "currentCostumeIndex": 0,
-    "penLayerMD5": "5c81a336fab8be57adc039a8a2b33ca9.png",
-    "penLayerID": -1,
-    "tempoBPM": 60,
-    "videoAlpha": 0.5,
-    "variables": [{
-        "name": "my variable",
-        "isPersistent": false,
-        "value": 0
-    }],
-    "children": [{
-            "objName": "Sprite1",
-            "sounds": [{
-                    "soundName": "Meow",
-                    "soundID": 0,
-                    "md5": "83c36d806dc92327b9e7049a565c6bff.wav",
-                    "sampleCount": 18688,
-                    "rate": 22050,
-                    "format": ""
-                }],
-            "costumes": [{
-                    "costumeName": "costume1",
-                    "baseLayerID": 0,
-                    "baseLayerMD5": "09dc888b0b7df19f70d81588ae73420e.svg",
-                    "bitmapResolution": 1,
-                    "rotationCenterX": 47,
-                    "rotationCenterY": 55
-                },
-                {
-                    "costumeName": "costume2",
-                    "baseLayerID": 1,
-                    "baseLayerMD5": "3696356a03a8d938318876a593572843.svg",
-                    "bitmapResolution": 1,
-                    "rotationCenterX": 47,
-                    "rotationCenterY": 55
-                }],
-            "currentCostumeIndex": 0,
-            "scratchX": 0,
-            "scratchY": 0,
-            "scale": 1,
-            "direction": 90,
-            "rotationStyle": "normal",
-            "isDraggable": false,
-            "indexInLibrary": 1,
-            "visible": true,
-            "spriteInfo": {
-            }
-        }]
-}
+{"targets":[{"id":"`jEk@4|i[#Fk?(8x)AV.","name":"Stage","isStage":true,"x":0,"y":0,"size":100,"direction":90,"draggable":false,"currentCostume":0,"costume":{"name":"backdrop1","bitmapResolution":1,"rotationCenterX":240,"rotationCenterY":180,"skinId":2,"dataFormat":"png","assetId":"739b5e2a2435f6e1ec2993791b423146"},"costumeCount":1,"visible":true,"rotationStyle":"all around","blocks":{},"variables":{"`jEk@4|i[#Fk?(8x)AV.-my variable":{"id":"`jEk@4|i[#Fk?(8x)AV.-my variable","name":"my variable","type":"","isCloud":false,"value":0}},"lists":{},"costumes":[{"name":"backdrop1","bitmapResolution":1,"rotationCenterX":240,"rotationCenterY":180,"skinId":2,"dataFormat":"png","assetId":"739b5e2a2435f6e1ec2993791b423146"}],"sounds":[{"name":"pop","format":"","rate":11025,"sampleCount":258,"soundID":1,"md5":"83a9787d4cb6f3b7632b4ddfebf74367.wav","data":null,"dataFormat":"wav","assetId":"83a9787d4cb6f3b7632b4ddfebf74367","soundId":"p=i?*Zt*I]@]x_*V`mut"}]},{"id":"9xJ@2eKXvx:/*Q^3Rib#","name":"Sprite1","isStage":false,"x":0,"y":0,"size":100,"direction":90,"draggable":false,"currentCostume":0,"costume":{"name":"costume1","bitmapResolution":1,"rotationCenterX":47,"rotationCenterY":55,"skinId":0,"dataFormat":"svg","assetId":"09dc888b0b7df19f70d81588ae73420e"},"costumeCount":2,"visible":true,"rotationStyle":"all around","blocks":{},"variables":{},"lists":{},"costumes":[{"name":"costume1","bitmapResolution":1,"rotationCenterX":47,"rotationCenterY":55,"skinId":0,"dataFormat":"svg","assetId":"09dc888b0b7df19f70d81588ae73420e"},{"name":"costume2","bitmapResolution":1,"rotationCenterX":47,"rotationCenterY":55,"skinId":1,"dataFormat":"svg","assetId":"3696356a03a8d938318876a593572843"}],"sounds":[{"name":"Meow","format":"","rate":22050,"sampleCount":18688,"soundID":0,"md5":"83c36d806dc92327b9e7049a565c6bff.wav","data":null,"dataFormat":"wav","assetId":"83c36d806dc92327b9e7049a565c6bff","soundId":"]z6@jLeJ2W%gr/eA1HB+"}]}],"meta":{"semver":"3.0.0","vm":"0.1.0","agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"}}
\ No newline at end of file
diff --git a/src/lib/project-loader-hoc.jsx b/src/lib/project-loader-hoc.jsx
index 854928c7eaa2720dff7150c586faf9e179d90116..2c20b9fed50736b490643d02ca40c06f11a051a0 100644
--- a/src/lib/project-loader-hoc.jsx
+++ b/src/lib/project-loader-hoc.jsx
@@ -17,21 +17,25 @@ const ProjectLoaderHOC = function (WrappedComponent) {
             this.updateProject = this.updateProject.bind(this);
             this.state = {
                 projectId: null,
-                projectData: null
+                projectData: null,
+                fetchingProject: false
             };
         }
         componentDidMount () {
             window.addEventListener('hashchange', this.updateProject);
             this.updateProject();
         }
-        componentDidUpdate (prevProps, prevState) {
-            if (this.state.projectId !== prevState.projectId) {
-                storage
-                    .load(storage.AssetType.Project, this.state.projectId, storage.DataFormat.JSON)
-                    .then(projectAsset => projectAsset && this.setState({
-                        projectData: projectAsset.data.toString()
-                    }))
-                    .catch(err => log.error(err));
+        componentWillUpdate (nextProps, nextState) {
+            if (this.state.projectId !== nextState.projectId) {
+                this.setState({fetchingProject: true}, () => {
+                    storage
+                        .load(storage.AssetType.Project, this.state.projectId, storage.DataFormat.JSON)
+                        .then(projectAsset => projectAsset && this.setState({
+                            projectData: projectAsset.data.toString(),
+                            fetchingProject: false
+                        }))
+                        .catch(err => log.error(err));
+                });
             }
         }
         componentWillUnmount () {
@@ -60,6 +64,7 @@ const ProjectLoaderHOC = function (WrappedComponent) {
             if (!this.state.projectData) return null;
             return (
                 <WrappedComponent
+                    fetchingProject={this.state.fetchingProject}
                     projectData={this.state.projectData}
                     {...this.props}
                 />