diff --git a/src/components/alerts/alert.css b/src/components/alerts/alert.css
new file mode 100644
index 0000000000000000000000000000000000000000..3bc1c932c723bc55fdde203b07e5d32f4f127724
--- /dev/null
+++ b/src/components/alerts/alert.css
@@ -0,0 +1,28 @@
+@import "../../css/units.css";
+@import "../../css/colors.css";
+@import "../../css/z-index.css";
+
+.alert {
+    width: 100%;
+    background: #FFF0DF;
+    display: flex;
+    flex-direction: row;
+    overflow: hidden;
+    align-items: left;
+    border: 1px solid #FF8C1A;
+    border-radius: 8px;
+    padding: 12px;
+    box-shadow: 2px 2px 2px 2px rgba(255, 140, 26, 0.25);
+}
+
+.alert-message {
+    color: #555;
+    font-weight: bold;
+    font-size: 12px;
+    line-height: 22pt;
+    width: 100%;
+}
+
+.alert-remove-button {
+    color: #FF8C1A;
+}
diff --git a/src/components/alerts/alerts.jsx b/src/components/alerts/alerts.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..e467c05e8a644d23de76c4f98b7f7f0aa26db35c
--- /dev/null
+++ b/src/components/alerts/alerts.jsx
@@ -0,0 +1,41 @@
+import classNames from 'classnames';
+import React from 'react';
+import PropTypes from 'prop-types';
+import Box from '../box/box.jsx';
+import Button from '../button/button.jsx';
+
+import styles from './alert.css';
+
+const Alerts = ({
+    className,
+    message,
+    onCloseAlert
+}) => (
+    <Box
+        bounds="parent"
+        className={classNames(className)}
+    >
+        <Box
+            className={styles.alert}
+        >
+            <div className={styles.alertMessage}>
+                {message}
+            </div>
+            <Button
+                className={styles.alertRemoveButton}
+                onClick={onCloseAlert}
+            >
+                { /* eslint-disable react/jsx-no-literals */ }
+                x
+            </Button>
+        </Box>
+    </Box>
+);
+
+Alerts.propTypes = {
+    className: PropTypes.string,
+    message: PropTypes.string.isRequired,
+    onCloseAlert: PropTypes.func.isRequired
+};
+
+export default Alerts;
diff --git a/src/components/gui/gui.css b/src/components/gui/gui.css
index 086011f4ba0a975499f0f7892fcc2eaa3bcee5b5..16f79ea4d684308cf8a6095bb4246b7966eb87af 100644
--- a/src/components/gui/gui.css
+++ b/src/components/gui/gui.css
@@ -278,3 +278,15 @@ $fade-out-distance: 15px;
 .extension-button > div {
     margin-top: 0;
 }
+
+/* Alerts */
+
+.alerts-container {
+    width: 448px;
+    z-index: $z-index-alerts;
+    left: 0;
+    right: 0;
+    margin: auto;
+    position: absolute;
+    margin-top: 53px;
+}
diff --git a/src/components/gui/gui.jsx b/src/components/gui/gui.jsx
index aa1dfc0393388111d80c4179e21b7a0d62fa95f1..76ef997d89ba1d73a971cb10fffc4fa4e9c0242b 100644
--- a/src/components/gui/gui.jsx
+++ b/src/components/gui/gui.jsx
@@ -27,6 +27,7 @@ import ImportModal from '../../containers/import-modal.jsx';
 import WebGlModal from '../../containers/webgl-modal.jsx';
 import TipsLibrary from '../../containers/tips-library.jsx';
 import Cards from '../../containers/cards.jsx';
+import Alerts from '../../containers/alerts.jsx';
 import DragLayer from '../../containers/drag-layer.jsx';
 
 import layout, {STAGE_SIZE_MODES} from '../../lib/layout-constants';
@@ -53,6 +54,7 @@ let isRendererSupported = null;
 const GUIComponent = props => {
     const {
         activeTabIndex,
+        alertsVisible,
         basePath,
         backdropLibraryVisible,
         backpackOptions,
@@ -108,7 +110,11 @@ const GUIComponent = props => {
                 isRendererSupported={isRendererSupported}
                 stageSize={stageSize}
                 vm={vm}
-            />
+            >
+                {alertsVisible ? (
+                    <Alerts className={styles.alertsContainer} />
+                ) : null}
+            </StageWrapper>
         ) : (
             <Box
                 className={styles.pageWrapper}
@@ -133,6 +139,9 @@ const GUIComponent = props => {
                 {cardsVisible ? (
                     <Cards />
                 ) : null}
+                {alertsVisible ? (
+                    <Alerts className={styles.alertsContainer} />
+                ) : null}
                 {costumeLibraryVisible ? (
                     <CostumeLibrary
                         vm={vm}
diff --git a/src/containers/alerts.jsx b/src/containers/alerts.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..c47d956dea31b7021a5f27fb26ed8612558fca1e
--- /dev/null
+++ b/src/containers/alerts.jsx
@@ -0,0 +1,23 @@
+import {connect} from 'react-redux';
+
+import {
+    showAlert,
+    closeAlert
+} from '../reducers/alerts';
+
+import AlertsComponent from '../components/alerts/alerts.jsx';
+
+const mapStateToProps = state => ({
+    visible: state.scratchGui.alerts.visible,
+    message: state.scratchGui.alerts.message
+});
+
+const mapDispatchToProps = dispatch => ({
+    onShowAlert: () => dispatch(showAlert()),
+    onCloseAlert: () => dispatch(closeAlert())
+});
+
+export default connect(
+    mapStateToProps,
+    mapDispatchToProps
+)(AlertsComponent);
diff --git a/src/containers/gui.jsx b/src/containers/gui.jsx
index 04c6142dce25e073c4f0a0676cd2ab3e5c37590d..6ef14439ba7c19b2f39301e15e3154fc59dd25b8 100644
--- a/src/containers/gui.jsx
+++ b/src/containers/gui.jsx
@@ -125,6 +125,7 @@ GUI.propTypes = {
 
 const mapStateToProps = (state, ownProps) => ({
     activeTabIndex: state.scratchGui.editorTab.activeTabIndex,
+    alertsVisible: state.scratchGui.alerts.visible,
     backdropLibraryVisible: state.scratchGui.modals.backdropLibrary,
     blocksTabVisible: state.scratchGui.editorTab.activeTabIndex === BLOCKS_TAB_INDEX,
     cardsVisible: state.scratchGui.cards.visible,
diff --git a/src/css/z-index.css b/src/css/z-index.css
index 26893f08fa5147930328992359d709777bef0ec7..87cc2cd01a70bc8cc35a88f6019b6744040a26e3 100644
--- a/src/css/z-index.css
+++ b/src/css/z-index.css
@@ -23,6 +23,7 @@ $z-index-stage-color-picker-background: 2000;
 $z-index-stage-with-color-picker: 2010;
 $z-index-stage-header: 5000;
 $z-index-stage-wrapper-overlay: 5000;
+$z-index-alerts: 5010;
 
 /* in most interfaces, the context menu is always on top */
 $z-index-context-menu: 10000;
diff --git a/src/lib/vm-listener-hoc.jsx b/src/lib/vm-listener-hoc.jsx
index 67e70f90019e90b92c262fdef5067c12c9c927ff..cf2307726c49e3a53a246119ae623b07e458cef6 100644
--- a/src/lib/vm-listener-hoc.jsx
+++ b/src/lib/vm-listener-hoc.jsx
@@ -9,6 +9,7 @@ import {updateTargets} from '../reducers/targets';
 import {updateBlockDrag} from '../reducers/block-drag';
 import {updateMonitors} from '../reducers/monitors';
 import {setRunningState, setTurboState} from '../reducers/vm-status';
+import {showAlert} from '../reducers/alerts';
 
 /*
  * Higher Order Component to manage events emitted by the VM
@@ -36,6 +37,7 @@ const vmListenerHOC = function (WrappedComponent) {
             this.props.vm.on('TURBO_MODE_OFF', this.props.onTurboModeOff);
             this.props.vm.on('PROJECT_RUN_START', this.props.onProjectRunStart);
             this.props.vm.on('PROJECT_RUN_STOP', this.props.onProjectRunStop);
+            this.props.vm.on('PERIPHERAL_ERROR', this.props.onShowAlert);
         }
         componentDidMount () {
             if (this.props.attachKeyboardEvents) {
@@ -93,6 +95,7 @@ const vmListenerHOC = function (WrappedComponent) {
                 onProjectRunStop,
                 onTurboModeOff,
                 onTurboModeOn,
+                onShowAlert,
                 /* eslint-enable no-unused-vars */
                 ...props
             } = this.props;
@@ -107,6 +110,7 @@ const vmListenerHOC = function (WrappedComponent) {
         onMonitorsUpdate: PropTypes.func.isRequired,
         onProjectRunStart: PropTypes.func.isRequired,
         onProjectRunStop: PropTypes.func.isRequired,
+        onShowAlert: PropTypes.func.isRequired,
         onTargetsUpdate: PropTypes.func.isRequired,
         onTurboModeOff: PropTypes.func.isRequired,
         onTurboModeOn: PropTypes.func.isRequired,
@@ -134,7 +138,10 @@ const vmListenerHOC = function (WrappedComponent) {
         onProjectRunStart: () => dispatch(setRunningState(true)),
         onProjectRunStop: () => dispatch(setRunningState(false)),
         onTurboModeOn: () => dispatch(setTurboState(true)),
-        onTurboModeOff: () => dispatch(setTurboState(false))
+        onTurboModeOff: () => dispatch(setTurboState(false)),
+        onShowAlert: () => {
+            dispatch(showAlert('Scratch has lost connection to peripheral.'));
+        }
     });
     return connect(
         mapStateToProps,
diff --git a/src/reducers/alerts.js b/src/reducers/alerts.js
new file mode 100644
index 0000000000000000000000000000000000000000..bc152e38f380f93969e34ebe68dadf1c9dead572
--- /dev/null
+++ b/src/reducers/alerts.js
@@ -0,0 +1,42 @@
+const CLOSE_ALERT = 'scratch-gui/alerts/CLOSE_ALERT';
+const SHOW_ALERT = 'scratch-gui/alerts/SHOW_ALERT';
+
+const initialState = {
+    message: '',
+    visible: false
+};
+
+const reducer = function (state, action) {
+    if (typeof state === 'undefined') state = initialState;
+    switch (action.type) {
+    case SHOW_ALERT:
+        return Object.assign({}, state, {
+            visible: true,
+            message: action.message
+        });
+    case CLOSE_ALERT:
+        return Object.assign({}, state, {
+            visible: false
+        });
+    default:
+        return state;
+    }
+};
+
+const closeAlert = function () {
+    return {type: CLOSE_ALERT};
+};
+
+const showAlert = function (message) {
+    return {
+        type: SHOW_ALERT,
+        message
+    };
+};
+
+export {
+    reducer as default,
+    initialState as alertsInitialState,
+    closeAlert,
+    showAlert
+};
diff --git a/src/reducers/gui.js b/src/reducers/gui.js
index 8869c1a35031e1d46b8dd28f4f408d2500946840..4d6cea9c0ea151d29bf92945ae10d61e59c8dbf8 100644
--- a/src/reducers/gui.js
+++ b/src/reducers/gui.js
@@ -1,4 +1,5 @@
 import {applyMiddleware, compose, combineReducers} from 'redux';
+import alertsReducer, {alertsInitialState} from './alerts';
 import assetDragReducer, {assetDragInitialState} from './asset-drag';
 import cardsReducer, {cardsInitialState} from './cards';
 import colorPickerReducer, {colorPickerInitialState} from './color-picker';
@@ -26,6 +27,7 @@ import decks from '../lib/libraries/decks/index.jsx';
 const guiMiddleware = compose(applyMiddleware(throttle(300, {leading: true, trailing: true})));
 
 const guiInitialState = {
+    alerts: alertsInitialState,
     assetDrag: assetDragInitialState,
     blockDrag: blockDragInitialState,
     cards: cardsInitialState,
@@ -91,6 +93,7 @@ const initTutorialCard = function (currentState, deckId) {
 };
 
 const guiReducer = combineReducers({
+    alerts: alertsReducer,
     assetDrag: assetDragReducer,
     blockDrag: blockDragReducer,
     cards: cardsReducer,