diff --git a/source/funkin/ui/debug/charting/ChartEditorImportExportHandler.hx b/source/funkin/ui/debug/charting/ChartEditorImportExportHandler.hx
index 9ac903e38..f116ad3f1 100644
--- a/source/funkin/ui/debug/charting/ChartEditorImportExportHandler.hx
+++ b/source/funkin/ui/debug/charting/ChartEditorImportExportHandler.hx
@@ -116,10 +116,10 @@ class ChartEditorImportExportHandler
 
   /**
    * @param force Whether to force the export without prompting the user for a file location.
-   * @param tmp If true, save to the temporary directory instead of the local `backup` directory.
    */
-  public static function exportAllSongData(state:ChartEditorState, force:Bool = false, tmp:Bool = false):Void
+  public static function exportAllSongData(state:ChartEditorState, force:Bool = false):Void
   {
+    var tmp = false;
     var zipEntries:Array<haxe.zip.Entry> = [];
 
     for (variation in state.availableVariations)
@@ -133,9 +133,9 @@ class ChartEditorImportExportHandler
       if (variationId == '')
       {
         var variationMetadata:Null<SongMetadata> = state.songMetadata.get(variation);
-        if (variationMetadata != null) zipEntries.push(FileUtil.makeZIPEntry('${state.currentSongId}-metadata.json', SerializerUtil.toJSON(variationMetadata)));
+        if (variationMetadata != null) zipEntries.push(FileUtil.makeZIPEntry('${state.currentSongId}-metadata.json', variationMetadata.serialize()));
         var variationChart:Null<SongChartData> = state.songChartData.get(variation);
-        if (variationChart != null) zipEntries.push(FileUtil.makeZIPEntry('${state.currentSongId}-chart.json', SerializerUtil.toJSON(variationChart)));
+        if (variationChart != null) zipEntries.push(FileUtil.makeZIPEntry('${state.currentSongId}-chart.json', variationChart.serialize()));
       }
       else
       {
diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx
index b94041afd..38c14bb08 100644
--- a/source/funkin/ui/debug/charting/ChartEditorState.hx
+++ b/source/funkin/ui/debug/charting/ChartEditorState.hx
@@ -1609,6 +1609,7 @@ class ChartEditorState extends HaxeUIState
     addUIClickListener('menubarItemSaveChartAs', _ -> ChartEditorImportExportHandler.exportAllSongData(this));
     addUIClickListener('menubarItemLoadInst', _ -> ChartEditorDialogHandler.openUploadInstDialog(this, true));
     addUIClickListener('menubarItemImportChart', _ -> ChartEditorDialogHandler.openImportChartDialog(this, 'legacy', true));
+    addUIClickListener('menubarItemExit', _ -> quitChartEditor());
 
     addUIClickListener('menubarItemUndo', _ -> undoLastCommand());
 
@@ -1795,7 +1796,7 @@ class ChartEditorState extends HaxeUIState
     // Auto-save to local storage.
     #else
     // Auto-save to temp file.
-    ChartEditorImportExportHandler.exportAllSongData(this, true, true);
+    ChartEditorImportExportHandler.exportAllSongData(this, true);
     #end
   }
 
@@ -3032,10 +3033,16 @@ class ChartEditorState extends HaxeUIState
     // CTRL + Q = Quit to Menu
     if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.Q)
     {
-      FlxG.switchState(new MainMenuState());
+      quitChartEditor();
     }
   }
 
+  function quitChartEditor():Void
+  {
+    autoSave();
+    FlxG.switchState(new MainMenuState());
+  }
+
   /**
    * Handle keybinds for edit menu items.
    */
@@ -3920,6 +3927,8 @@ class ChartEditorState extends HaxeUIState
    */
   public function testSongInPlayState(minimal:Bool = false):Void
   {
+    autoSave();
+
     var startTimestamp:Float = 0;
     if (playtestStartTime) startTimestamp = scrollPositionInMs + playheadPositionInMs;