The Dual-Pack Architecture
Bedrock add-ons are split into two distinct folder structures: the Behavior Pack (commonly abbreviated as BP) and the Resource Pack (RP). This separation mirrors the internal client-server architecture of the game. Even when you play a single-player world, Bedrock runs an internal logical server alongside the visual client. Understanding which pack handles which responsibility is the first step in add-on development.
The Behavior Pack runs on the logical server. It dictates the rules of the world: how much health an entity has, what loot a chest generates, how a custom block interacts with redstone, and what JavaScript code executes through the Script API. If you change a pig so that it flies and shoots fireballs, that logic lives entirely within the Behavior Pack.
The Resource Pack runs on the client. It is responsible for everything the player sees and hears. This includes PNG textures, 3D geometry models, animations, particle effects, sound definitions, and localized text strings in `.lang` files. A custom entity defined in a Behavior Pack will still function in the world without a Resource Pack, but it will be completely invisible and silent until a Resource Pack tells the client how to render it.
| Pack Type | Module Type | Primary Responsibilities | Example Directories |
|---|---|---|---|
| Behavior Pack (BP) | data | Entity AI, block mechanics, item behaviors, loot tables, recipes, functions | entities/, blocks/, items/, loot_tables/, functions/ |
| Behavior Pack (BP) | script | TypeScript/JavaScript execution via the Script API | scripts/ |
| Resource Pack (RP) | resources | Textures, 3D models, animations, sounds, UI, localization | textures/, models/, animations/, texts/, sounds/ |
Anatomy of a Manifest File
Neither a Behavior Pack nor a Resource Pack will be recognized by Minecraft unless it contains a valid `manifest.json` file at its root directory. The manifest acts as the identity card for your pack. It tells the game the pack's name, its version, the minimum version of Minecraft required to run it, and what kind of content it holds.
The most critical elements inside a manifest are the Universally Unique Identifiers (UUIDs). Every pack requires at least two separate UUIDv4 strings: one inside the `header` object to identify the pack itself, and another inside the `modules` array to identify the specific content module. You must generate fresh UUIDs for every new pack you create, and the header UUID must never match the module UUID.
If you are building an add-on that uses both a Behavior Pack and a Resource Pack, you can link them together using the `dependencies` array. By placing the Resource Pack's `header` UUID into the Behavior Pack's `dependencies` array, you instruct Minecraft to automatically activate the Resource Pack whenever a player applies the Behavior Pack to a world.
{
"format_version": 2,
"header": {
"name": "My First Behavior Pack",
"description": "Adds custom mechanics and items to the world.",
"uuid": "a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d",
"version": [1, 0, 0],
"min_engine_version": [1, 20, 80]
},
"modules": [
{
"description": "Behavior data module",
"type": "data",
"uuid": "f6e5d4c3-b2a1-4f5e-8d9c-0b1a2f3e4d5c",
"version": [1, 0, 0]
}
],
"dependencies": [
{
"uuid": "12345678-1234-4321-8765-1234567890ab",
"version": [1, 0, 0]
}
]
}Development Workspace and File Locations
Minecraft Bedrock loads packs from a specific storage directory on your device, commonly referred to as the `com.mojang` folder. While players normally install finished add-ons using packaged `.mcpack` or `.mcaddon` archives, doing so during active development is slow. Instead, you should place your unzipped pack folders directly into the development directories.
Inside the `com.mojang` directory, you will find `development_behavior_packs` and `development_resource_packs`. Any folder you place here is read directly by the game without needing to be imported. When you make changes to your JSON files or textures in these folders, you can simply exit to the main menu and reload the world—or use the `/reload` command for functions and scripts—to see your updates immediately.
contrasted with the standard `behavior_packs` and `resource_packs` folders, the development folders do not cache pack contents aggressively. On Windows, the `com.mojang` folder is located deep within your user `AppData\Local\Packages` directory under the `Microsoft.MinecraftUWP_8wekyb3d8bbwe\LocalState\games\com.mojang` path. Creating a desktop shortcut to this location will save you significant time.
Namespaces, Identifiers, and Format Versions
Every custom asset you create—whether it is a block, an item, an entity, or a particle effect—must have a unique identifier formatted as `namespace:name`. The namespace is a short prefix representing your team or project (for example, `my_addon:copper_dagger`). You must always use lowercase letters, numbers, and underscores. Never use `minecraft` as your namespace unless you are intentionally overriding a vanilla file, as the game reserves that namespace for official content.
Alongside the identifier, almost every JSON file in a Bedrock add-on begins with a `format_version` key. This version string (such as `"1.20.80"`) does not need to match the exact version of Minecraft you are currently running. Instead, it tells the game's JSON parser which schema rules to apply when reading that specific file.
This versioning system is how Bedrock maintains backward compatibility. If Mojang updates how item components work in version 1.21.0, an older item file with a `format_version` of `"1.20.50"` will still be parsed using the 1.20.50 rules. When writing new files, you should generally set the `format_version` to match the `min_engine_version` declared in your pack's manifest.
{
"format_version": "1.20.80",
"minecraft:item": {
"description": {
"identifier": "my_addon:copper_coin",
"menu_category": {
"category": "items"
}
},
"components": {
"minecraft:max_stack_size": 64,
"minecraft:icon": "copper_coin",
"minecraft:display_name": {
"value": "item.my_addon:copper_coin.name"
}
}
}
}Enabling the Content Log
Writing JSON by hand inevitably leads to missing commas, unclosed brackets, or misspelled component names. By default, Minecraft fails silently when it encounters a broken file: your custom block or item simply fails to appear in the game. To see what went wrong, you must enable the Content Log before testing your work.
Open Minecraft's main Settings menu and navigate to the Creator tab. Turn on both 'Enable Content Log File' and 'Enable Content Log GUI'. With these settings active, pressing `Ctrl + H` while inside a world will open an on-screen history of every warning and error the game encountered while loading your packs. If a JSON file fails to parse or a texture path is incorrect, the Content Log will print the exact file path and line number causing the issue.
Which versions this applies to
Applies to all modern Minecraft Bedrock versions (1.16.0 and above). Manifest format_version 2 and data-driven items/blocks shown here are fully stable in 1.20.80+ and require no experimental toggles.
When it does not work
| What you see | Why | The fix |
|---|---|---|
| Pack does not appear in the Available Packs list in world settings at all. | Your manifest.json contains a syntax error (such as a trailing comma), or it is nested inside an extra subfolder rather than sitting at the immediate root of your pack folder. | Validate your manifest.json using a JSON linter and ensure the file path is `development_behavior_packs/your_pack_name/manifest.json`. |
| Content Log shows: ' Duplicate UUID detected' or 'Failed to load pack'. | You copied an existing manifest.json without generating new UUIDs, or you used the exact same UUID for both the `header` and the `modules` section within the same file. | Generate two brand-new version 4 UUIDs and replace the strings in both `header.uuid` and `modules[0].uuid`. |
| Error when applying pack: 'This pack requires a newer version of the game'. | The `min_engine_version` array in your manifest's header is set to a version number higher than the version of Minecraft you currently have installed. | Lower `min_engine_version` in `manifest.json` (for example, to `[1, 20, 80]`) so it is less than or equal to your client's current version. |
Reference, straight from the game files
Read out of the game itself, so the ids match the version you are building for.
