diff --git a/src/components/sprite-selector/sprite-list.jsx b/src/components/sprite-selector/sprite-list.jsx
index c10362a44797f876322f4c133290c16b0c712154..17ba2dc215345c14ddc3f4291ca7cc2700927e20 100644
--- a/src/components/sprite-selector/sprite-list.jsx
+++ b/src/components/sprite-selector/sprite-list.jsx
@@ -57,7 +57,8 @@ const SpriteList = function (props) {
                     DragConstants.COSTUME,
                     DragConstants.SOUND,
                     DragConstants.BACKPACK_COSTUME,
-                    DragConstants.BACKPACK_SOUND].includes(draggingType);
+                    DragConstants.BACKPACK_SOUND,
+                    DragConstants.BACKPACK_CODE].includes(draggingType);
 
                 return (
                     <SortableAsset
diff --git a/src/containers/stage-selector.jsx b/src/containers/stage-selector.jsx
index e8f0fc9df0b2fefbb31f1c18ba52bc56f48bdc2f..08ffd3730a520da9a16a92af68fde070d8e3a1ee 100644
--- a/src/containers/stage-selector.jsx
+++ b/src/containers/stage-selector.jsx
@@ -12,6 +12,7 @@ import DragConstants from '../lib/drag-constants';
 import DropAreaHOC from '../lib/drop-area-hoc.jsx';
 import {emptyCostume} from '../lib/empty-assets';
 import sharedMessages from '../lib/shared-messages';
+import {fetchCode} from '../lib/backpack-api';
 
 import StageSelectorComponent from '../components/stage-selector/stage-selector.jsx';
 
@@ -22,7 +23,8 @@ const dragTypes = [
     DragConstants.COSTUME,
     DragConstants.SOUND,
     DragConstants.BACKPACK_COSTUME,
-    DragConstants.BACKPACK_SOUND
+    DragConstants.BACKPACK_SOUND,
+    DragConstants.BACKPACK_CODE
 ];
 
 const DroppableStage = DropAreaHOC(dragTypes)(StageSelectorComponent);
@@ -99,6 +101,12 @@ class StageSelector extends React.Component {
                 md5: dragInfo.payload.body,
                 name: dragInfo.payload.name
             }, this.props.id);
+        } else if (dragInfo.dragType === DragConstants.BACKPACK_CODE) {
+            fetchCode(dragInfo.payload.bodyUrl)
+                .then(blocks => {
+                    this.props.vm.shareBlocksToTarget(blocks, this.props.id);
+                    this.props.vm.refreshWorkspace();
+                });
         }
     }
     setFileInput (input) {
diff --git a/src/containers/target-pane.jsx b/src/containers/target-pane.jsx
index 6f9ed6ae70cd7e9691ed9d07729375ecec0d96ef..b48e3d232acd59d6a7428b3df89aa3e4404cd594 100644
--- a/src/containers/target-pane.jsx
+++ b/src/containers/target-pane.jsx
@@ -19,6 +19,7 @@ import {handleFileUpload, spriteUpload} from '../lib/file-uploader.js';
 import sharedMessages from '../lib/shared-messages';
 import {emptySprite} from '../lib/empty-assets';
 import {highlightTarget} from '../reducers/targets';
+import {fetchSprite, fetchCode} from '../lib/backpack-api';
 
 class TargetPane extends React.Component {
     constructor (props) {
@@ -166,8 +167,7 @@ class TargetPane extends React.Component {
         } else if (dragInfo.dragType === DragConstants.BACKPACK_SPRITE) {
             // TODO storage does not have a way of loading zips right now, and may never need it.
             // So for now just grab the zip manually.
-            fetch(dragInfo.payload.bodyUrl)
-                .then(response => response.arrayBuffer())
+            fetchSprite(dragInfo.payload.bodyUrl)
                 .then(sprite3Zip => this.props.vm.addSprite(sprite3Zip));
         } else if (targetId) {
             // Something is being dragged over one of the sprite tiles or the backdrop.
@@ -192,6 +192,12 @@ class TargetPane extends React.Component {
                     md5: dragInfo.payload.body,
                     name: dragInfo.payload.name
                 }, targetId);
+            } else if (dragInfo.dragType === DragConstants.BACKPACK_CODE) {
+                fetchCode(dragInfo.payload.bodyUrl)
+                    .then(blocks => {
+                        this.props.vm.shareBlocksToTarget(blocks, targetId);
+                        this.props.vm.refreshWorkspace();
+                    });
             }
         }
     }
diff --git a/src/lib/backpack-api.js b/src/lib/backpack-api.js
index 8a5231843aeb409727407b0817178c55d7933a43..550d37d43d6bebfc7c329b4c49f62f38e2ad3490 100644
--- a/src/lib/backpack-api.js
+++ b/src/lib/backpack-api.js
@@ -73,6 +73,22 @@ const deleteBackpackObject = ({
     });
 });
 
+// Two types of backpack items are not retreivable through storage
+// code, as json and sprite3 as arraybuffer zips.
+const fetchAs = (responseType, uri) => new Promise((resolve, reject) => {
+    xhr({uri, responseType}, (error, response) => {
+        if (error || response.statusCode !== 200) {
+            return reject();
+        }
+        return resolve(response.body);
+    });
+});
+
+// These two helpers allow easy fetching of backpack code and sprite zips
+// Use the curried fetchAs here so the consumer does not worry about XHR responseTypes
+const fetchCode = fetchAs.bind(null, 'json');
+const fetchSprite = fetchAs.bind(null, 'arraybuffer');
+
 export {
     getBackpackContents,
     saveBackpackObject,
@@ -80,5 +96,7 @@ export {
     costumePayload,
     soundPayload,
     spritePayload,
-    codePayload
+    codePayload,
+    fetchCode,
+    fetchSprite
 };