diff --git a/package-lock.json b/package-lock.json
index 17c2de0..77595d1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,22 +1,24 @@
 {
   "name": "vcs-game-maker",
-  "version": "0.1.0",
+  "version": "0.4.0",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
-      "version": "0.1.0",
+      "version": "0.4.0",
       "dependencies": {
         "@vue/composition-api": "^1.0.0-rc.13",
         "batari-basic": "^0.0.1",
         "blockly": "^6.20210701.0",
         "core-js": "^3.6.5",
+        "file-saver": "^2.0.5",
         "handlebars": "^4.7.7",
         "lodash": "^4.17.21",
         "vue": "^2.6.11",
         "vue-code-highlight": "^0.7.8",
         "vue-router": "^3.2.0",
-        "vuetify": "^2.4.0"
+        "vuetify": "^2.4.0",
+        "yaml": "^1.10.2"
       },
       "devDependencies": {
         "@vue/cli-plugin-babel": "~4.5.0",
@@ -6463,6 +6465,11 @@
         "node": ">= 8.9.0"
       }
     },
+    "node_modules/file-saver": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz",
+      "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA=="
+    },
     "node_modules/filesize": {
       "version": "3.6.1",
       "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz",
@@ -14847,6 +14854,14 @@
       "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
       "dev": true
     },
+    "node_modules/yaml": {
+      "version": "1.10.2",
+      "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
+      "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
+      "engines": {
+        "node": ">= 6"
+      }
+    },
     "node_modules/yargs": {
       "version": "16.2.0",
       "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
@@ -20592,6 +20607,11 @@
         "schema-utils": "^2.5.0"
       }
     },
+    "file-saver": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz",
+      "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA=="
+    },
     "filesize": {
       "version": "3.6.1",
       "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz",
@@ -27585,6 +27605,11 @@
       "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
       "dev": true
     },
+    "yaml": {
+      "version": "1.10.2",
+      "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
+      "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="
+    },
     "yargs": {
       "version": "16.2.0",
       "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
diff --git a/package.json b/package.json
index cb61e71..22a62c4 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "vcs-game-maker",
-  "version": "0.4.0",
+  "version": "0.5.0",
   "private": true,
   "scripts": {
     "serve": "vue-cli-service serve",
@@ -12,12 +12,14 @@
     "batari-basic": "^0.0.1",
     "blockly": "^6.20210701.0",
     "core-js": "^3.6.5",
+    "file-saver": "^2.0.5",
     "handlebars": "^4.7.7",
     "lodash": "^4.17.21",
     "vue": "^2.6.11",
     "vue-code-highlight": "^0.7.8",
     "vue-router": "^3.2.0",
-    "vuetify": "^2.4.0"
+    "vuetify": "^2.4.0",
+    "yaml": "^1.10.2"
   },
   "devDependencies": {
     "@vue/cli-plugin-babel": "~4.5.0",
diff --git a/src/App.vue b/src/App.vue
index 0391d3c..b2efe31 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -121,6 +121,19 @@
             <v-list-item-title>Generated</v-list-item-title>
           </v-list-item-content>
         </v-list-item>
+
+        <v-list-item
+          to="/project"
+          link
+          class="project-item"
+        >
+          <v-list-item-icon>
+            <v-icon>mdi-pencil-ruler</v-icon>
+          </v-list-item-icon>
+          <v-list-item-content>
+            <v-list-item-title>Project</v-list-item-title>
+          </v-list-item-content>
+        </v-list-item>
       </v-list>
 
     </v-navigation-drawer>
@@ -216,4 +229,11 @@ export default {
   color: rgb(39, 176, 136) !important;
   border-left-color: rgb(39, 176, 136) !important;
 }
+
+.project-item,
+.project-item > .v-list-item__icon > .theme--light.v-icon,
+.project-item > .v-list-item__content {
+  color: rgb(39, 136, 176) !important;
+  border-left-color: rgb(39, 136, 176) !important;
+}
 </style>
diff --git a/src/components/ActionEditor.vue b/src/components/ActionEditor.vue
index ca6a338..04710a0 100644
--- a/src/components/ActionEditor.vue
+++ b/src/components/ActionEditor.vue
@@ -21,7 +21,7 @@ import '../blocks/input';
 import '../blocks/sprites';
 import blocklyToolbox from 'raw-loader!./blockly-toolbox.xml';
 import BlocklyBB from '../generators/bbasic';
-import {useLocalStorage} from '../hooks/storage';
+import {useWorkspaceStorage} from '../hooks/project';
 import {useGeneratedBasic} from '../hooks/generated';
 
 export default {
@@ -40,7 +40,7 @@ export default {
       },
       toolbox: blocklyToolbox,
     },
-    workspaceStorage: useLocalStorage('vcs-game-maker.workspace'),
+    workspaceStorage: useWorkspaceStorage(),
   }),
   methods: {
     showCode() {
diff --git a/src/components/BlocklyComponent.vue b/src/components/BlocklyComponent.vue
index 299d8d1..d99e8a2 100644
--- a/src/components/BlocklyComponent.vue
+++ b/src/components/BlocklyComponent.vue
@@ -63,7 +63,7 @@ export default {
     },
     handleChange() {
       const xml = Blockly.Xml.workspaceToDom(this.workspace);
-      const text = Blockly.Xml.domToText(xml);
+      const text = Blockly.Xml.domToPrettyText(xml);
       this.lastSavedWorkspace = text;
       this.$emit('input', text, {
         workspace: this.workspace,
diff --git a/src/hooks/project.js b/src/hooks/project.js
new file mode 100644
index 0000000..17ca53e
--- /dev/null
+++ b/src/hooks/project.js
@@ -0,0 +1,4 @@
+import {useLocalStorage} from '../hooks/storage';
+
+export const useProjectStorage = (type) => useLocalStorage(`vcs-game-maker.${type}`);
+export const useWorkspaceStorage = () => useProjectStorage('workspace');
diff --git a/src/router/index.js b/src/router/index.js
index 2ed1c2b..1b9ea4c 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -24,6 +24,11 @@ const routes = [
     name: 'Generated',
     component: () => import('../views/GeneratedCode.vue'),
   },
+  {
+    path: '/project',
+    name: 'Project',
+    component: () => import('../views/Project.vue'),
+  },
 ];
 
 const router = new VueRouter({
diff --git a/src/views/Project.vue b/src/views/Project.vue
new file mode 100644
index 0000000..e129bfc
--- /dev/null
+++ b/src/views/Project.vue
@@ -0,0 +1,84 @@
+<template>
+  <v-card>
+    <v-card-title>Project</v-card-title>
+    <v-card-text>
+        <v-file-input
+            accept=".vcsgm"
+            label="Project to import."
+            v-model="data.fileToImport"
+            @change="handleLoadProject"
+        ></v-file-input>
+    </v-card-text>
+    <v-card-actions>
+      <v-btn
+        color="primary"
+        @click="handleSaveProject"
+      >
+          Save Project
+      </v-btn>
+    </v-card-actions>
+  </v-card>
+</template>
+<script>
+import {defineComponent, reactive} from '@vue/composition-api';
+import {saveAs} from 'file-saver';
+import YAML from 'yaml';
+
+import {useWorkspaceStorage} from '../hooks/project';
+
+const FORMAT_TYPE = 'VCS Game Maker Project';
+const FORMAT_VERSION = 1.0;
+
+export default defineComponent({
+  setup(props, context) {
+    const data = reactive({fileToImport: null});
+    const router = context.root.$router;
+    const workspaceStorage = useWorkspaceStorage();
+    return {data, router, workspaceStorage};
+  },
+  methods: {
+    handleSaveProject() {
+      const projectYaml = YAML.stringify({
+        'type': FORMAT_TYPE,
+        'format-version': FORMAT_VERSION,
+        'generation-time': new Date(),
+        'blockly-workspace': this.workspaceStorage,
+      });
+
+      const projectBlob = new Blob([projectYaml], {type: 'text/yaml'});
+      saveAs(projectBlob, 'project.vcsgm');
+    },
+
+    handleLoadProject() {
+      if (!this.data.fileToImport) {
+        console.warn('No file to import.');
+        return;
+      }
+
+      console.info('Importing file', this.data.fileToImport);
+      const reader = new FileReader();
+      reader.readAsText(this.data.fileToImport, 'UTF-8');
+      reader.onload = (evt) => {
+        const projectYaml = evt.target.result;
+        console.info('YAML', projectYaml);
+        const project = YAML.parse(projectYaml);
+
+        if (project.type !== FORMAT_TYPE) {
+          throw new Error('This file does not seem to be a valid project.');
+        }
+
+        if (project['format-version'] > FORMAT_VERSION) {
+          throw new Error(
+              `This project's version (${project['format-version']}) is newer than the supported version (${FORMAT_VERSION})`);
+        }
+
+        this.workspaceStorage = project['blockly-workspace'];
+
+        this.router.push('/');
+      };
+      reader.onerror = (evt) => console.error('Error while loading project', evt);
+      this.data.fileToImport = null;
+    },
+  },
+});
+</script>