diff --git a/src/components/green-flag/green-flag.css b/src/components/green-flag/green-flag.css
index f9ab904f9f4642b12d972be2fb620e2a1732734c..62b5ffe5f2519d3b6bbfccad7e265ca2b634ac0f 100644
--- a/src/components/green-flag/green-flag.css
+++ b/src/components/green-flag/green-flag.css
@@ -1,9 +1,8 @@
 @import "../../css/colors.css";
 
 .green-flag {
-    box-sizing: content-box;
-    width: 1.25rem;
-    height: 1.25rem;
+    width: 2rem;
+    height: 2rem;
     padding: 0.375rem;
     border-radius: 0.25rem;
     user-select: none;
@@ -13,10 +12,7 @@
 }
 
 .green-flag:hover {
-    /* Scale flag image by 1.2, but keep background static */
-    width: 1.5rem;
-    height: 1.5rem;
-    padding: 0.25rem;
+    transform: scale(1.2);
 }
 
 .green-flag.is-active {
diff --git a/src/components/gui/gui.css b/src/components/gui/gui.css
index 508b83b17c2bc1578002380e9c25a04d00c0b90f..72670e031095acc3f02f9466cf892f13e1996710 100644
--- a/src/components/gui/gui.css
+++ b/src/components/gui/gui.css
@@ -10,6 +10,10 @@
     background-color: $ui-primary;
 }
 
+.body-wrapper * {
+    box-sizing: border-box;
+}
+
 .flex-wrapper {
     display: flex;
 
@@ -57,6 +61,7 @@
 .tab {
     flex-grow: 1;
     height: 80%;
+    margin-bottom: 0;
     margin-left: -0.5rem;
 
     border-radius: 1rem 1rem 0 0;
@@ -164,14 +169,6 @@
     max-width: calc(480px + calc($space * 2));
 }
 
-.stage-wrapper {
-    padding-left: $space;
-    padding-right: $space;
-
-    /* Hides negative space between edge of rounded corners + container, when selected */
-    user-select: none;
-}
-
 .target-wrapper {
     display: flex;
     flex-grow: 1;
diff --git a/src/components/gui/gui.jsx b/src/components/gui/gui.jsx
index 6512cecf7ab592615ccf7770aacaf80044a11c79..872950a211c1bd3e229651930659e9dcbe39af75 100644
--- a/src/components/gui/gui.jsx
+++ b/src/components/gui/gui.jsx
@@ -3,7 +3,6 @@ import PropTypes from 'prop-types';
 import React from 'react';
 import {defineMessages, FormattedMessage, injectIntl, intlShape} from 'react-intl';
 import {Tab, Tabs, TabList, TabPanel} from 'react-tabs';
-import MediaQuery from 'react-responsive';
 import tabStyles from 'react-tabs/style/react-tabs.css';
 import VM from 'scratch-vm';
 import Renderer from 'scratch-render';
@@ -12,8 +11,7 @@ import Blocks from '../../containers/blocks.jsx';
 import CostumeTab from '../../containers/costume-tab.jsx';
 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 StageWrapper from '../../containers/stage-wrapper.jsx';
 import Loader from '../loader/loader.jsx';
 import Box from '../box/box.jsx';
 import MenuBar from '../menu-bar/menu-bar.jsx';
@@ -24,7 +22,6 @@ import WebGlModal from '../../containers/webgl-modal.jsx';
 import TipsLibrary from '../../containers/tips-library.jsx';
 import Cards from '../../containers/cards.jsx';
 
-import layout from '../../lib/layout-constants.js';
 import styles from './gui.css';
 import addExtensionIcon from './icon--extensions.svg';
 import codeIcon from './icon--code.svg';
@@ -53,6 +50,7 @@ const GUIComponent = props => {
         costumesTabVisible,
         importInfoVisible,
         intl,
+        isPlayerOnly,
         loading,
         onExtensionButtonClick,
         onActivateCostumesTab,
@@ -66,11 +64,7 @@ const GUIComponent = props => {
         ...componentProps
     } = props;
     if (children) {
-        return (
-            <Box {...componentProps}>
-                {children}
-            </Box>
-        );
+        return <Box {...componentProps}>{children}</Box>;
     }
 
     const tabClassNames = {
@@ -85,7 +79,13 @@ const GUIComponent = props => {
     if (isRendererSupported === null) {
         isRendererSupported = Renderer.isSupported();
     }
-    return (
+
+    return isPlayerOnly ? (
+        <StageWrapper
+            isRendererSupported={isRendererSupported}
+            vm={vm}
+        />
+    ) : (
         <Box
             className={styles.pageWrapper}
             {...componentProps}
@@ -204,27 +204,12 @@ const GUIComponent = props => {
                     </Box>
 
                     <Box className={styles.stageAndTargetWrapper}>
-                        <Box className={styles.stageMenuWrapper}>
-                            <StageHeader vm={vm} />
-                        </Box>
-                        <Box className={styles.stageWrapper}>
-                            {/* eslint-disable arrow-body-style */}
-                            <MediaQuery minWidth={layout.fullSizeMinWidth}>{isFullSize => {
-                                return isRendererSupported ? (
-                                    <Stage
-                                        height={isFullSize ? layout.fullStageHeight : layout.smallerStageHeight}
-                                        shrink={0}
-                                        vm={vm}
-                                        width={isFullSize ? layout.fullStageWidth : layout.smallerStageWidth}
-                                    />
-                                ) : null;
-                            }}</MediaQuery>
-                            {/* eslint-enable arrow-body-style */}
-                        </Box>
+                        <StageWrapper
+                            isRendererSupported={isRendererSupported}
+                            vm={vm}
+                        />
                         <Box className={styles.targetWrapper}>
-                            <TargetPane
-                                vm={vm}
-                            />
+                            <TargetPane vm={vm} />
                         </Box>
                     </Box>
                 </Box>
@@ -241,6 +226,7 @@ GUIComponent.propTypes = {
     costumesTabVisible: PropTypes.bool,
     importInfoVisible: PropTypes.bool,
     intl: intlShape.isRequired,
+    isPlayerOnly: PropTypes.bool,
     loading: PropTypes.bool,
     onActivateCostumesTab: PropTypes.func,
     onActivateSoundsTab: PropTypes.func,
diff --git a/src/components/sprite-info/sprite-info.css b/src/components/sprite-info/sprite-info.css
index ceb9e9ca5f030a0a25794e43e9512511882dc5a4..53758e65cc344038befbdae8066d41e14f2379c7 100644
--- a/src/components/sprite-info/sprite-info.css
+++ b/src/components/sprite-info/sprite-info.css
@@ -31,9 +31,8 @@
 
 .icon-wrapper {
     display: inline-block;
-    box-sizing: content-box;
-    width: 1rem;
-    height: 1rem;
+    width: calc(2rem + 2px);
+    height: calc(2rem + 2px);
     padding: 0.5rem;
     outline: none;
     user-select: none;
diff --git a/src/components/stage-header/stage-header.css b/src/components/stage-header/stage-header.css
index b1cb5569ac29ab35d36b65f70d3bc9494ab26764..2ac722efc5579336874b97e565ecedaab235e213 100644
--- a/src/components/stage-header/stage-header.css
+++ b/src/components/stage-header/stage-header.css
@@ -37,9 +37,8 @@
     display: block;
     border: 1px solid $ui-black-transparent;
     border-radius: .25rem;
-    box-sizing: content-box;
-    width: 1.25rem;
-    height: 1.25rem;
+    width: calc(2rem + 2px);
+    height: calc(2rem + 2px);
     background: $ui-white;
     padding: 0.375rem;
     user-select: none;
diff --git a/src/components/stage-header/stage-header.jsx b/src/components/stage-header/stage-header.jsx
index 7a2beec7cfdf849175a762be24146737211389d8..efada70ed553a7321e250bd22229789a9d6697ad 100644
--- a/src/components/stage-header/stage-header.jsx
+++ b/src/components/stage-header/stage-header.jsx
@@ -48,6 +48,7 @@ const messages = defineMessages({
 const StageHeaderComponent = function (props) {
     const {
         isFullScreen,
+        isPlayerOnly,
         onKeyPress,
         onSetStageLarge,
         onSetStageFull,
@@ -83,51 +84,54 @@ const StageHeaderComponent = function (props) {
             </Box>
         );
     } else {
+        const stageControls =
+            isPlayerOnly ? (
+                []
+            ) : (
+                <div className={styles.stageSizeToggleGroup}>
+                    <ComingSoonTooltip
+                        place="left"
+                        tooltipId="small-stage-button"
+                    >
+                        <div
+                            disabled
+                            className={classNames(
+                                styles.stageButton,
+                                styles.stageButtonLeft,
+                                styles.stageButtonDisabled
+                            )}
+                            role="button"
+                        >
+                            <img
+                                disabled
+                                alt={props.intl.formatMessage(messages.smallStageSizeMessage)}
+                                className={styles.stageButtonIcon}
+                                draggable={false}
+                                src={smallStageIcon}
+                            />
+                        </div>
+                    </ComingSoonTooltip>
+                    <div>
+                        <Button
+                            className={classNames(styles.stageButton, styles.stageButtonRight)}
+                            onClick={onSetStageLarge}
+                        >
+                            <img
+                                alt={props.intl.formatMessage(messages.largeStageSizeMessage)}
+                                className={styles.stageButtonIcon}
+                                draggable={false}
+                                src={largeStageIcon}
+                            />
+                        </Button>
+                    </div>
+                </div>
+            );
         header = (
             <Box className={styles.stageHeaderWrapper}>
                 <Box className={styles.stageMenuWrapper}>
                     <Controls vm={vm} />
                     <div className={styles.stageSizeRow}>
-                        <div className={styles.stageSizeToggleGroup}>
-                            <ComingSoonTooltip
-                                place="left"
-                                tooltipId="small-stage-button"
-                            >
-                                <div
-                                    disabled
-                                    className={classNames(
-                                        styles.stageButton,
-                                        styles.stageButtonLeft,
-                                        styles.stageButtonDisabled
-                                    )}
-                                    role="button"
-                                >
-                                    <img
-                                        disabled
-                                        alt={props.intl.formatMessage(messages.smallStageSizeMessage)}
-                                        className={styles.stageButtonIcon}
-                                        draggable={false}
-                                        src={smallStageIcon}
-                                    />
-                                </div>
-                            </ComingSoonTooltip>
-                            <div>
-                                <Button
-                                    className={classNames(
-                                        styles.stageButton,
-                                        styles.stageButtonRight
-                                    )}
-                                    onClick={onSetStageLarge}
-                                >
-                                    <img
-                                        alt={props.intl.formatMessage(messages.largeStageSizeMessage)}
-                                        className={styles.stageButtonIcon}
-                                        draggable={false}
-                                        src={largeStageIcon}
-                                    />
-                                </Button>
-                            </div>
-                        </div>
+                        {stageControls}
                         <div>
                             <Button
                                 className={styles.stageButton}
@@ -154,6 +158,7 @@ const StageHeaderComponent = function (props) {
 StageHeaderComponent.propTypes = {
     intl: intlShape,
     isFullScreen: PropTypes.bool.isRequired,
+    isPlayerOnly: PropTypes.bool.isRequired,
     onKeyPress: PropTypes.func.isRequired,
     onSetStageFull: PropTypes.func.isRequired,
     onSetStageLarge: PropTypes.func.isRequired,
diff --git a/src/components/stage-wrapper/stage-wrapper.css b/src/components/stage-wrapper/stage-wrapper.css
new file mode 100644
index 0000000000000000000000000000000000000000..122d1b55d473caea07705d90b74ec6bb99529f1a
--- /dev/null
+++ b/src/components/stage-wrapper/stage-wrapper.css
@@ -0,0 +1,14 @@
+@import "../../css/units.css";
+@import "../../css/colors.css";
+
+.stage-wrapper {
+    box-sizing: border-box;
+}
+
+.stage-canvas-wrapper {
+    padding-left: $space;
+    padding-right: $space;
+
+    /* Hides negative space between edge of rounded corners + container, when selected */
+    user-select: none;
+}
diff --git a/src/components/stage-wrapper/stage-wrapper.jsx b/src/components/stage-wrapper/stage-wrapper.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..8cec64e40a9ffdd74d617e2bb611a4637e6e6b6b
--- /dev/null
+++ b/src/components/stage-wrapper/stage-wrapper.jsx
@@ -0,0 +1,47 @@
+import PropTypes from 'prop-types';
+import React from 'react';
+import MediaQuery from 'react-responsive';
+import VM from 'scratch-vm';
+
+import Box from '../box/box.jsx';
+import layout from '../../lib/layout-constants.js';
+import StageHeader from '../../containers/stage-header.jsx';
+import Stage from '../../containers/stage.jsx';
+
+import styles from './stage-wrapper.css';
+
+const StageWrapperComponent = function (props) {
+    const {
+        isRendererSupported,
+        vm
+    } = props;
+
+    return (
+        <Box className={styles.stageWrapper}>
+            <Box className={styles.stageMenuWrapper}>
+                <StageHeader vm={vm} />
+            </Box>
+            <Box className={styles.stageCanvasWrapper}>
+                {/* eslint-disable arrow-body-style */}
+                <MediaQuery minWidth={layout.fullSizeMinWidth}>{isFullSize => {
+                    return isRendererSupported ? (
+                        <Stage
+                            height={isFullSize ? layout.fullStageHeight : layout.smallerStageHeight}
+                            shrink={0}
+                            vm={vm}
+                            width={isFullSize ? layout.fullStageWidth : layout.smallerStageWidth}
+                        />
+                    ) : null;
+                }}</MediaQuery>
+                {/* eslint-enable arrow-body-style */}
+            </Box>
+        </Box>
+    );
+};
+
+StageWrapperComponent.propTypes = {
+    isRendererSupported: PropTypes.bool.isRequired,
+    vm: PropTypes.instanceOf(VM).isRequired
+};
+
+export default StageWrapperComponent;
diff --git a/src/components/stop-all/stop-all.css b/src/components/stop-all/stop-all.css
index 99ebee89284ebd481597ef86874083352b2dc352..b2d878582f40f07a30070215c1132ab75bdd77cc 100644
--- a/src/components/stop-all/stop-all.css
+++ b/src/components/stop-all/stop-all.css
@@ -1,7 +1,6 @@
 .stop-all {
-    box-sizing: content-box;
-    width: 1.25rem;
-    height: 1.25rem;
+    width: 2rem;
+    height: 2rem;
     padding: 0.375rem;
     border-radius: 0.25rem;
     user-select: none;
diff --git a/src/containers/stage-header.jsx b/src/containers/stage-header.jsx
index 724280edd75e212b22dc7363ab77c581a55fadc9..65677e29f224dcb2e9751a68c03012587e6d09f8 100644
--- a/src/containers/stage-header.jsx
+++ b/src/containers/stage-header.jsx
@@ -2,7 +2,8 @@ import PropTypes from 'prop-types';
 import React from 'react';
 import bindAll from 'lodash.bindall';
 import VM from 'scratch-vm';
-import {setStageSize, setFullScreen, STAGE_SIZES} from '../reducers/stage-size';
+import {setStageSize, STAGE_SIZES} from '../reducers/stage-size';
+import {setFullScreen} from '../reducers/mode';
 
 import {connect} from 'react-redux';
 
@@ -41,7 +42,8 @@ class StageHeader extends React.Component {
 }
 
 StageHeader.propTypes = {
-    isFullScreen: PropTypes.bool.isRequired,
+    isFullScreen: PropTypes.bool,
+    isPlayerOnly: PropTypes.bool,
     onSetStageUnFull: PropTypes.func.isRequired,
     stageSize: PropTypes.oneOf(Object.keys(STAGE_SIZES)),
     vm: PropTypes.instanceOf(VM).isRequired
@@ -49,7 +51,8 @@ StageHeader.propTypes = {
 
 const mapStateToProps = state => ({
     stageSize: state.stageSize.stageSize,
-    isFullScreen: state.stageSize.isFullScreen
+    isFullScreen: state.mode.isFullScreen,
+    isPlayerOnly: state.mode.isPlayerOnly
 });
 
 const mapDispatchToProps = dispatch => ({
diff --git a/src/containers/stage-wrapper.jsx b/src/containers/stage-wrapper.jsx
new file mode 100644
index 0000000000000000000000000000000000000000..039f3ab3ca61a3b9001863ccff784cdabdfdc37b
--- /dev/null
+++ b/src/containers/stage-wrapper.jsx
@@ -0,0 +1,13 @@
+import PropTypes from 'prop-types';
+import React from 'react';
+import VM from 'scratch-vm';
+import StageWrapperComponent from '../components/stage-wrapper/stage-wrapper.jsx';
+
+const StageWrapper = props => <StageWrapperComponent {...props} />;
+
+StageWrapper.propTypes = {
+    isRendererSupported: PropTypes.bool.isRequired,
+    vm: PropTypes.instanceOf(VM).isRequired
+};
+
+export default StageWrapper;
diff --git a/src/containers/stage.jsx b/src/containers/stage.jsx
index 96fdf71a682f9c4fbd2be01607effcfd29ae4f54..0820b1741ab83f51203d378e1cb5ff52fc0718af 100644
--- a/src/containers/stage.jsx
+++ b/src/containers/stage.jsx
@@ -394,9 +394,9 @@ Stage.defaultProps = {
 
 const mapStateToProps = state => ({
     isColorPicking: state.colorPicker.active,
-    isFullScreen: state.stageSize.isFullScreen,
-    // Do not use editor drag style in fullscreen mode.
-    useEditorDragStyle: !state.stageSize.isFullScreen
+    isFullScreen: state.mode.isFullScreen,
+    // Do not use editor drag style in fullscreen or player mode.
+    useEditorDragStyle: !(state.mode.isFullScreen || state.mode.isPlayerOnly)
 });
 
 const mapDispatchToProps = dispatch => ({
diff --git a/src/lib/app-state-hoc.jsx b/src/lib/app-state-hoc.jsx
index e593fa40b304624e01b472695f00ad6546046987..ca05ec64ee093b1d395c4d10dfe49ca5f5335869 100644
--- a/src/lib/app-state-hoc.jsx
+++ b/src/lib/app-state-hoc.jsx
@@ -1,4 +1,5 @@
 import React from 'react';
+import PropTypes from 'prop-types';
 import {Provider} from 'react-redux';
 import {createStore, applyMiddleware, compose} from 'redux';
 import throttle from 'redux-throttle';
@@ -6,6 +7,7 @@ import throttle from 'redux-throttle';
 import {intlShape} from 'react-intl';
 import {IntlProvider, updateIntl} from 'react-intl-redux';
 import {intlInitialState} from '../reducers/intl.js';
+import {initialState as modeInitialState, setPlayer, setFullScreen} from '../reducers/mode.js';
 import reducer from '../reducers/gui';
 
 const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
@@ -26,22 +28,43 @@ const AppStateHOC = function (WrappedComponent) {
         constructor (props) {
             super(props);
             let intl = {};
+            let mode = {};
             if (props.intl) {
                 intl = {
-                    intl: {
-                        defaultLocale: 'en',
-                        locale: props.intl.locale,
-                        messages: props.intl.messages
-                    }
+                    defaultLocale: 'en',
+                    locale: props.intl.locale,
+                    messages: props.intl.messages
                 };
             } else {
-                intl = intlInitialState;
+                intl = intlInitialState.intl;
+            }
+            if (props.isPlayerOnly || props.isFullScreen) {
+                mode = {
+                    isFullScreen: props.isFullScreen || false,
+                    isPlayerOnly: props.isPlayerOnly || false
+                };
+            } else {
+                mode = modeInitialState;
             }
 
-            this.store = createStore(reducer, intl, enhancer);
+            this.store = createStore(
+                reducer,
+                {
+                    intl: intl,
+                    mode: mode
+                },
+                enhancer);
         }
         componentDidUpdate (prevProps) {
-            if (prevProps.intl !== this.props.intl) updateIntl(this.props.intl);
+            if (prevProps.intl !== this.props.intl) {
+                this.store.dispatch(updateIntl(this.props.intl));
+            }
+            if (prevProps.isPlayerOnly !== this.props.isPlayerOnly) {
+                this.store.dispatch(setPlayer(this.props.isPlayerOnly));
+            }
+            if (prevProps.isFullScreen !== this.props.isFullScreen) {
+                this.store.dispatch(setFullScreen(this.props.isFullScreen));
+            }
         }
         render () {
             return (
@@ -51,13 +74,12 @@ const AppStateHOC = function (WrappedComponent) {
                     </IntlProvider>
                 </Provider>
             );
-
         }
-
-
     }
     AppStateWrapper.propTypes = {
-        intl: intlShape
+        intl: intlShape,
+        isFullScreen: PropTypes.bool,
+        isPlayerOnly: PropTypes.bool
     };
     return AppStateWrapper;
 };
diff --git a/src/lib/storage.js b/src/lib/storage.js
index 64269e3ede293c6e65c2a36cffc7b89f480d1b39..be7bcef1e6df21e80093f7e713554bcf38364547 100644
--- a/src/lib/storage.js
+++ b/src/lib/storage.js
@@ -2,7 +2,7 @@ import ScratchStorage from 'scratch-storage';
 
 import defaultProjectAssets from './default-project';
 
-const PROJECT_SERVER = 'https://cdn.projects.scratch.mit.edu';
+const PROJECT_SERVER = 'https://projects.scratch.mit.edu';
 const ASSET_SERVER = 'https://cdn.assets.scratch.mit.edu';
 
 /**
diff --git a/src/playground/player.css b/src/playground/player.css
index f5a3096c44d594f5bae77d04b8b9b5d2aaefa517..355eeeecd49ccbaf5f29d8d06eebd676b31c2c57 100644
--- a/src/playground/player.css
+++ b/src/playground/player.css
@@ -1,4 +1,7 @@
-body {
-    padding: 0;
-    margin: 0;
+.stage-only {
+    width: calc(480px + 1rem);
+}
+
+.stage-only * {
+    box-sizing: border-box;
 }
diff --git a/src/playground/player.jsx b/src/playground/player.jsx
index 58bc0a6a73c7b65e5346fb4aa5eaddf63ce74e4d..660851aae52866948ccfb30cf16408193ebef8b9 100644
--- a/src/playground/player.jsx
+++ b/src/playground/player.jsx
@@ -1,74 +1,26 @@
 import React from 'react';
 import ReactDOM from 'react-dom';
-import {connect} from 'react-redux';
 
-import Controls from '../containers/controls.jsx';
-import Stage from '../containers/stage.jsx';
 import Box from '../components/box/box.jsx';
 import GUI from '../containers/gui.jsx';
-import ProjectLoaderHOC from '../lib/project-loader-hoc.jsx';
+import ErrorBoundaryHOC from './error-boundary-hoc.jsx';
 
-import './player.css';
-
-const mapStateToProps = state => ({vm: state.vm});
-
-const VMStage = connect(mapStateToProps)(Stage);
-const VMControls = connect(mapStateToProps)(Controls);
-
-class Player extends React.Component {
-    constructor (props) {
-        super(props);
-        this.handleResize = this.handleResize.bind(this);
-        this.state = this.getWindowSize();
-    }
-    componentDidMount () {
-        window.addEventListener('resize', this.handleResize);
-    }
-    componentWillUnmount () {
-        window.removeEventListener('resize', this.handleResize);
-    }
-    getWindowSize () {
-        return {
-            width: window.innerWidth,
-            height: window.innerHeight
-        };
-    }
-    handleResize () {
-        this.setState(this.getWindowSize());
-    }
-    render () {
-        let height = this.state.height - 40;
-        let width = height + (height / 3);
-        if (width > this.state.width) {
-            width = this.state.width;
-            height = width * .75;
-        }
-        return (
-            <GUI
-                {...this.props}
-                style={{
-                    margin: '0 auto'
-                }}
-                width={width}
-            >
-                <Box height={40}>
-                    <VMControls
-                        style={{
-                            marginRight: 10,
-                            height: 40
-                        }}
-                    />
-                </Box>
-                <VMStage
-                    height={height}
-                    width={width}
-                />
-            </GUI>
-        );
-    }
+if (process.env.NODE_ENV === 'production' && typeof window === 'object') {
+    // Warn before navigating away
+    window.onbeforeunload = () => true;
 }
 
-const App = ProjectLoaderHOC(Player);
+import styles from './player.css';
+const Player = () => (
+    <Box className={styles.stageOnly}>
+        <GUI
+            isPlayerOnly
+            isFullScreen={false}
+        />
+    </Box>
+);
+
+const App = ErrorBoundaryHOC(Player);
 
 const appTarget = document.createElement('div');
 document.body.appendChild(appTarget);
diff --git a/src/reducers/gui.js b/src/reducers/gui.js
index 15218e100f83425f791e1f67a2607f7a3ec2253c..8bb226a9074f6d4681830ce9deb0aa18b26a80a2 100644
--- a/src/reducers/gui.js
+++ b/src/reducers/gui.js
@@ -8,6 +8,7 @@ import hoveredTargetReducer from './hovered-target';
 import intlReducer from './intl';
 import menuReducer from './menus';
 import modalReducer from './modals';
+import modeReducer from './mode';
 import monitorReducer from './monitors';
 import monitorLayoutReducer from './monitor-layout';
 import targetReducer from './targets';
@@ -22,6 +23,7 @@ export default combineReducers({
     colorPicker: colorPickerReducer,
     customProcedures: customProceduresReducer,
     editorTab: editorTabReducer,
+    mode: modeReducer,
     hoveredTarget: hoveredTargetReducer,
     intl: intlReducer,
     stageSize: stageSizeReducer,
diff --git a/src/reducers/mode.js b/src/reducers/mode.js
new file mode 100644
index 0000000000000000000000000000000000000000..b158c95230dcdbd7aef38898908ddfbe690dec06
--- /dev/null
+++ b/src/reducers/mode.js
@@ -0,0 +1,45 @@
+const SET_FULL_SCREEN = 'scratch-gui/mode/SET_FULL_SCREEN';
+const SET_PLAYER = 'scratch-gui/mode/SET_PLAYER';
+
+const initialState = {
+    isFullScreen: false,
+    isPlayerOnly: false
+};
+
+const reducer = function (state, action) {
+    if (typeof state === 'undefined') state = initialState;
+    switch (action.type) {
+    case SET_FULL_SCREEN:
+        return {
+            isFullScreen: action.isFullScreen,
+            isPlayerOnly: state.isPlayerOnly
+        };
+    case SET_PLAYER:
+        return {
+            isFullScreen: state.isFullScreen,
+            isPlayerOnly: action.isPlayerOnly
+        };
+    default:
+        return state;
+    }
+};
+
+const setFullScreen = function (isFullScreen) {
+    return {
+        type: SET_FULL_SCREEN,
+        isFullScreen: isFullScreen
+    };
+};
+const setPlayer = function (isPlayerOnly) {
+    return {
+        type: SET_PLAYER,
+        isPlayerOnly: isPlayerOnly
+    };
+};
+
+export {
+    reducer as default,
+    initialState,
+    setFullScreen,
+    setPlayer
+};
diff --git a/src/reducers/stage-size.js b/src/reducers/stage-size.js
index ea2750e3409917e35cad5cdc4dd1562ca98a0c98..4c4a58a52191c04a1d13781c94610aa6d4675cb3 100644
--- a/src/reducers/stage-size.js
+++ b/src/reducers/stage-size.js
@@ -1,8 +1,6 @@
 const SET_STAGE_SIZE = 'scratch-gui/StageSize/SET_STAGE_SIZE';
-const SET_FULL_SCREEN = 'scratch-gui/StageSize/SET_FULL_SCREEN';
 
 const initialState = {
-    isFullScreen: false,
     stageSize: 'large'
 };
 
@@ -17,14 +15,8 @@ const reducer = function (state, action) {
     switch (action.type) {
     case SET_STAGE_SIZE:
         return {
-            isFullScreen: state.isFullScreen,
             stageSize: action.stageSize
         };
-    case SET_FULL_SCREEN:
-        return {
-            isFullScreen: action.isFullScreen,
-            stageSize: state.stageSize
-        };
     default:
         return state;
     }
@@ -37,19 +29,8 @@ const setStageSize = function (stageSize) {
     };
 };
 
-// `isFullScreen` is a separate value because "stage size" does not
-// actually apply to full screen mode, so they are treated as separate
-// values to be assessed.
-const setFullScreen = function (isFullScreen) {
-    return {
-        type: SET_FULL_SCREEN,
-        isFullScreen: isFullScreen
-    };
-};
-
 export {
     reducer as default,
     setStageSize,
-    setFullScreen,
     STAGE_SIZES
 };