Skip to main content
Minecraft Creator Tools provides comprehensive tools for packaging add-ons and worlds into distributable formats (.mcpack, .mcaddon, .mcworld).

Packaging Overview

The ProjectExporter class handles all export operations:
  • Building projects before export
  • Creating .mcpack and .mcaddon files
  • Generating .mcworld files with embedded packs
  • Deploying to Minecraft folders
  • Syncing from GitHub repositories
Reference: app/src/app/ProjectExporter.ts:1

Export Formats

.mcpack

Single behavior or resource packContains: One pack folder

.mcaddon

Complete add-on (BP + RP)Contains: Both packs

.mcworld

World with embedded packsContains: World + packs

Building Before Export

Always prepare projects before packaging:

Project Preparation

import ProjectExporter from "./app/ProjectExporter";
import ProjectBuild from "./app/ProjectBuild";

const projectBuild = await ProjectExporter.prepareProject(project);

if (!projectBuild) {
  console.error("Project has errors");
  project.errorMessages?.forEach(err => {
    console.error(err.message);
  });
  return;
}

if (projectBuild.isInErrorState) {
  console.error("Build failed");
  return;
}
  1. Runs automated project updates (module versions, etc.)
  2. Saves the project
  3. Builds the project (compiles scripts, processes assets)
  4. Validates the build output
  5. Returns ProjectBuild or undefined if errors

Exporting Add-ons

Export as .mcaddon

Create a complete add-on package:
async function exportAddon(project: Project) {
  const zipBytes = await ProjectExporter.generateMCAddonAsZip(
    creatorTools,
    project,
    false // returnAsBlob - false for Uint8Array
  );
  
  if (!zipBytes) {
    console.error("Export failed");
    return;
  }
  
  // Save to file
  const file = storage.rootFolder.ensureFile(`${project.name}.mcaddon`);
  file.setContent(zipBytes);
  await file.saveContent();
  
  console.log(`Exported to ${project.name}.mcaddon`);
}

Export as Blob (Browser)

For web-based downloads:
async function downloadAddon(project: Project) {
  const blob = await ProjectExporter.generateMCAddonAsZip(
    creatorTools,
    project,
    true // returnAsBlob
  ) as Blob;
  
  if (!blob) return;
  
  // Trigger browser download
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = `${project.name}.mcaddon`;
  a.click();
  URL.revokeObjectURL(url);
}

What Gets Packaged

The exporter includes:
1

Behavior Pack

  • manifest.json
  • All behavior pack content (entities, items, etc.)
  • Compiled scripts (built from TypeScript)
  • Excluded: TypeScript source files (*.ts)
2

Resource Pack

  • manifest.json
  • All resource pack content (textures, models, etc.)
  • Optimized assets
3

Structure

Uses FolderDeploy.noFolders to create flat structure:
addon.mcaddon/
├── pack_name_bp/
│   └── (behavior pack files)
└── pack_name_rp/
    └── (resource pack files)

Exporting Worlds

Generate World with Packs

Create a new world with your add-ons embedded:
import { Generator } from "./minecraft/WorldLevelDat";

async function exportWorldWithPacks(project: Project) {
  const worldSettings = {
    generator: Generator.flat,
    betaApisExperiment: true,
    gameType: 1, // Creative
    difficulty: 0 // Peaceful
  };
  
  const mcworld = await ProjectExporter.generateWorldWithPacks(
    creatorTools,
    project,
    worldSettings
  );
  
  if (!mcworld) return;
  
  // Get as bytes
  const worldBytes = await mcworld.getBytes();
  
  if (!worldBytes) return;
  
  // Save to file
  const file = storage.rootFolder.ensureFile(`${project.name}.mcworld`);
  file.setContent(worldBytes);
  await file.saveContent();
}

Deploy Existing World with Packs

Add your packs to an existing world:
async function exportExistingWorld(
  project: Project,
  worldProjectItem: ProjectItem
) {
  const worldBytes = await ProjectExporter.deployAsWorldAndTestAssets(
    creatorTools,
    project,
    worldProjectItem,
    true // returnZipBytes
  );
  
  if (!worldBytes) return;
  
  // Save or distribute
  const fileName = `${worldProjectItem.name}.mcworld`;
  const file = storage.rootFolder.ensureFile(fileName);
  file.setContent(worldBytes);
  await file.saveContent();
}

World Export Options

Creates a new world with your packs embedded.Use when:
  • You want a fresh world for testing
  • Creating a template world
  • Packaging a sample world for distribution
Result: New world with default terrain + your packs
Exports an existing world from your project.Use when:
  • You have a pre-built world in your project
  • World has custom terrain/structures
  • Preserving existing world data
Result: Copy of existing world + updated packs
Exports world with both your packs and Creator Tools assets.Use when:
  • Testing with in-game tools
  • Need debugging utilities
  • Development workflows
Result: World + your packs + Creator Tools pack

Deployment Workflows

Local Minecraft Deployment

Deploy directly to Minecraft’s folder:
async function deployToMinecraft(project: Project) {
  const deployTarget = creatorTools.defaultDeploymentTarget;
  
  if (!deployTarget) {
    console.error("No deployment target configured");
    return;
  }
  
  const success = await ProjectExporter.deployProject(
    creatorTools,
    project,
    deployTarget.deployBehaviorPacksFolder!
  );
  
  if (success) {
    console.log("Deployed to Minecraft!");
  }
}

Export to Custom Location

Deploy to any folder:
async function exportToFolder(
  project: Project,
  targetFolder: IFolder
) {
  const projectBuild = await ProjectExporter.prepareProject(project);
  if (!projectBuild) return;
  
  await ProjectExporter.deployProjectPacks(
    project,
    projectBuild,
    targetFolder,
    undefined,
    FolderDeploy.developmentFolders
  );
  
  await targetFolder.saveAll();
}

Forbidden Files

Certain files are automatically excluded from packages:
export const ProjectImportExclusions = [
  "build",           // Build output
  "node_modules",    // NPM dependencies  
  "dist",            // Distribution folder
  "lib",             // Library folder
  ".env",            // Environment variables
  "*/.*",            // Hidden files
  "out",             // Output folder
  
  "*just.config*",   // Build configs
  "*package-lock*",  // Lock files
  "*.mjs*"           // Module files
];
Never include sensitive files like .env or credentials in packages!

GitHub Import/Export

Import from GitHub

Sync a project from a GitHub repository:
async function importFromGitHub(
  owner: string,
  repo: string,
  branch: string,
  folder?: string
) {
  const project = await ProjectExporter.syncProjectFromGitHub(
    true, // isNewProject
    creatorTools,
    repo,
    owner,
    branch,
    folder,
    undefined, // projName (auto-generated)
    undefined, // project (creates new)
    undefined  // fileList
  );
  
  if (project) {
    console.log(`Imported ${project.name} from GitHub`);
  }
}

Update from GitHub

Update an existing project from GitHub:
async function updateFromGitHub(project: Project) {
  if (!project.originalGitHubOwner || !project.originalGitHubRepoName) {
    console.error("Project not linked to GitHub");
    return;
  }
  
  await ProjectExporter.syncProjectFromGitHub(
    false, // isNewProject
    creatorTools,
    project.originalGitHubRepoName,
    project.originalGitHubOwner,
    project.originalGitHubBranch,
    project.originalGitHubFolder,
    project.name,
    project,
    project.originalFileList,
    undefined, // messageUpdater
    true       // dontOverwriteExistingFiles
  );
  
  console.log("Updated from GitHub");
}

Practical Examples

Example 1: Complete Export Workflow

async function completeExport(project: Project) {
  console.log("Starting export...");
  
  // 1. Validate project
  const infoSet = new ProjectInfoSet(
    project,
    ProjectInfoSuite.sharing
  );
  await infoSet.generateForProject();
  
  if (infoSet.errorAndFailCount > 0) {
    console.error("Project has errors, cannot export");
    return;
  }
  
  // 2. Update modules to latest
  const runner = new ProjectUpdateRunner(project);
  await runner.updateProject(["SCRIPTMODULE"]);
  
  // 3. Export as .mcaddon
  const addonBytes = await ProjectExporter.generateMCAddonAsZip(
    creatorTools,
    project,
    false
  );
  
  if (!addonBytes) {
    console.error("Export failed");
    return;
  }
  
  // 4. Export test world
  const worldBytes = await ProjectExporter.generateFlatBetaApisWorldWithPacksZipBytes(
    creatorTools,
    project,
    `${project.name} Test World`
  );
  
  // 5. Save files
  const addonFile = storage.rootFolder.ensureFile(`${project.name}.mcaddon`);
  addonFile.setContent(addonBytes);
  await addonFile.saveContent();
  
  if (worldBytes) {
    const worldFile = storage.rootFolder.ensureFile(`${project.name}_test.mcworld`);
    worldFile.setContent(worldBytes);
    await worldFile.saveContent();
  }
  
  console.log("Export complete!");
}

Example 2: Multi-format Export

async function exportAllFormats(project: Project) {
  const outputFolder = storage.rootFolder.ensureFolder("exports");
  await outputFolder.ensureExists();
  
  // Export addon
  const addonBytes = await ProjectExporter.generateMCAddonAsZip(
    creatorTools,
    project,
    false
  );
  
  if (addonBytes) {
    const addonFile = outputFolder.ensureFile(`${project.name}.mcaddon`);
    addonFile.setContent(addonBytes);
    await addonFile.saveContent();
  }
  
  // Export test world
  const worldSettings = {
    generator: Generator.flat,
    betaApisExperiment: true
  };
  
  const mcworld = await ProjectExporter.generateWorldWithPacks(
    creatorTools,
    project,
    worldSettings
  );
  
  if (mcworld) {
    const worldBytes = await mcworld.getBytes();
    if (worldBytes) {
      const worldFile = outputFolder.ensureFile(`${project.name}.mcworld`);
      worldFile.setContent(worldBytes);
      await worldFile.saveContent();
    }
  }
  
  // Export to folder (unzipped)
  const folderExport = outputFolder.ensureFolder(project.name);
  await folderExport.ensureExists();
  
  const projectBuild = await ProjectExporter.prepareProject(project);
  if (projectBuild) {
    await ProjectExporter.deployProjectPacks(
      project,
      projectBuild,
      folderExport,
      undefined,
      FolderDeploy.noFolders
    );
    await folderExport.saveAll();
  }
  
  console.log(`Exported to ${outputFolder.fullPath}`);
}

Example 3: Batch Export Multiple Projects

async function batchExport(projects: Project[]) {
  const results = [];
  
  for (const project of projects) {
    try {
      console.log(`Exporting ${project.name}...`);
      
      const bytes = await ProjectExporter.generateMCAddonAsZip(
        creatorTools,
        project,
        false
      );
      
      if (bytes) {
        const file = storage.rootFolder.ensureFile(
          `${project.name}.mcaddon`
        );
        file.setContent(bytes);
        await file.saveContent();
        
        results.push({
          name: project.name,
          success: true,
          size: bytes.length
        });
      } else {
        results.push({
          name: project.name,
          success: false,
          error: "Export returned no bytes"
        });
      }
    } catch (error) {
      results.push({
        name: project.name,
        success: false,
        error: error.message
      });
    }
  }
  
  // Print summary
  console.log("\nExport Summary:");
  for (const result of results) {
    if (result.success) {
      console.log(`✓ ${result.name} (${result.size} bytes)`);
    } else {
      console.log(`✗ ${result.name}: ${result.error}`);
    }
  }
}

Optimizing Exports

Minimize Package Size

1

Remove development files

Ensure ProjectImportExclusions are applied (automatic)
2

Optimize textures

Compress textures before export
3

Strip comments

Remove comments from JSON files (if desired)
4

Validate content

Remove unused assets flagged by validation

Pre-export Checklist

  • Run validation suite
  • Update script modules to latest
  • Test in development environment
  • Verify manifest.json UUIDs are unique
  • Check pack_icon.png exists
  • Ensure format_version is current
  • Review file exclusions

Best Practices

Always validate first

Run validation before exporting to catch issues early.

Update dependencies

Keep script modules and versions current before export.

Test exports

Import and test exported packages before distribution.

Version your exports

Include version numbers in export filenames.

Troubleshooting

Check:
  • Project build completed successfully
  • Files are saved before export
  • Storage folder is loaded (await folder.load())
  • No file exclusion rules blocking content
Verify:
  • Scripts were compiled (check projectBuild)
  • Script modules in manifest.json are correct
  • TypeScript files are excluded (they should be)
  • JavaScript files are included in scripts/
Ensure:
  • Pack references added to world manifests
  • Pack UUIDs match between manifest and world
  • Experiments are enabled if needed
  • Packs are in correct world folders
Optimize:
  • Use FolderDeploy.noFolders when possible
  • Exclude large unnecessary files
  • Clear project cache before export
  • Process files in batches for large projects

Build docs developers (and LLMs) love