Wiki 9Minecraft Wiki 9Minecraft

Add-Ons Explained: Architecture, Packs, and Data-Driven Design

Understand how Behavior Packs and Resource Packs work together to modify Minecraft Bedrock.

6Sections
1Code examples
4Known errors

An Add-On is the official, supported framework for modifying and adding content to Minecraft: Bedrock Edition. Instead of altering the core game executable or decompiling source code, Add-Ons use a data-driven architecture built on JSON files, assets, and optional JavaScript files. You reach for the Add-On system whenever you want to introduce custom blocks, items, entities, recipes, or game mechanics while maintaining cross-platform compatibility across consoles, mobile devices, and Windows.

The Two Halves of an Add-On

Every complete Add-On is divided into two distinct folders: a Behavior Pack (often abbreviated as BP) and a Resource Pack (abbreviated as RP). While a pure texture pack only requires a Resource Pack, and a server-side utility might only require a Behavior Pack, introducing a new tangible object into the game—like a custom mob or a custom block—almost always requires both packs working in tandem.

The Behavior Pack acts as the brain and server-side logic of your project. When a world is loaded, the server reads the Behavior Pack to determine how things function. It dictates how much health an entity has, what AI goals it pursues, what loot tables exist, how crafting recipes are shaped, and how fast a custom block breaks. It also houses your mcfunction files and Script API code. Players joining a multiplayer world do not necessarily need to download the Behavior Pack, because the host server processes all of these rules and sends the results to the connected clients.

The Resource Pack acts as the client-side presentation layer. It has no say over game rules or physics; its sole job is to take the data sent by the server and render it for the player. The Resource Pack holds 2D textures, 3D geometry models, animations, sound effects, particle visuals, and localization files (.lang) that translate raw technical identifiers into readable names. Both packs communicate using shared identifiers—such as a custom namespace and name like mypack:copper_golem—allowing the client to know which model and texture to wrap around the invisible hitbox that the server is moving around.

Pack TypeSideResponsibilitiesTypical File Types
Behavior Pack (BP)Server / HostAI goals, attributes, loot tables, crafting recipes, trade tables, block properties, functions, and scripts..json, .mcfunction, .js
Resource Pack (RP)Client / PlayerTextures, 3D geometry, animations, sounds, particles, UI modifications, and translated text strings..json, .png, .tga, .ogg, .fsb, .lang

Data-Driven Architecture and Components

At its core, Bedrock's Add-On system is built on an Entity-Component-System (ECS) architecture exposed through JSON files. Rather than writing procedural code to explain how a new creature walks or takes damage, you assemble pre-built engine building blocks called components. Minecraft already knows how gravity works, how melee attacks calculate damage, and how inventory slots hold items; your JSON files simply instruct the engine which of these native behaviors to attach to your custom object and how to configure their parameters.

Every data-driven definition file begins with a format_version string. This is one of the most important concepts to grasp before writing your first file. The format_version does not strictly have to match the exact version of Minecraft you are currently playing. Instead, it tells the Bedrock engine which schema rules to use when parsing that specific JSON file. This is how Minecraft maintains backward compatibility: if Mojang changes how item components are structured in version 1.20.50, an older pack whose item files declare a format_version of 1.20.30 will still be read using the 1.20.30 parser rules.

Inside the definition file, you assign your custom object a unique identifier composed of a namespace and a name, separated by a colon (for example, studio:ruby_ore). You must never use the minecraft namespace for new objects you create; that namespace is reserved exclusively for overriding or referencing vanilla game assets. Below the description block, you list the components that define the object's traits, such as minecraft:collision_box to set physical boundaries or minecraft:destructible_by_mining to control how long it takes a pickaxe to break a block.

The Manifest File

Minecraft will not recognize a folder as a Behavior Pack or Resource Pack unless it contains a valid manifest.json file at its root level. The manifest is the identity card of your pack. It tells the game the pack's name, its description, the minimum game version required to run it, and what kind of files it contains.

The most critical fields inside a manifest are the UUIDs (Universally Unique Identifiers). Every manifest requires at least two completely different version-4 UUIDs: one inside the header block to identify the pack itself, and another inside the modules block to identify the specific content module. If two packs in your storage share the exact same header UUID, Minecraft will treat them as duplicates and refuse to load one of them. You must generate fresh UUIDs for every new pack you create, never copying them from tutorials or existing templates.

To make your Behavior Pack and Resource Pack aware of each other, you can add a dependencies array to your Behavior Pack's manifest. By placing the header UUID and version of your Resource Pack into the Behavior Pack's dependencies block, applying the Behavior Pack to a world will automatically activate the matching Resource Pack alongside it.

BP/manifest.json
{
  "format_version": 2,
  "header": {
    "name": "Example Behavior Pack",
    "description": "Demonstrates the core structure of a Bedrock manifest.",
    "uuid": "8f4b2b10-5c7a-4e2b-9d1a-3f6e8c9a1b2d",
    "version": [1, 0, 0],
    "min_engine_version": [1, 20, 80]
  },
  "modules": [
    {
      "description": "Behavior data module",
      "type": "data",
      "uuid": "2a9c4d6e-1b3f-4a8c-8e5d-7c0b9a2f4e6d",
      "version": [1, 0, 0]
    }
  ],
  "dependencies": [
    {
      "uuid": "7d3e9a1c-4b2f-4e6a-9c8d-1f5b3a7e9c0d",
      "version": [1, 0, 0]
    }
  ]
}

Development Folders vs. Packaged Archives

On devices where you have file system access (such as Windows, Android, or dedicated servers), Minecraft allocates specific folders inside its com.mojang directory for loading packs. You will notice two sets of folders: behavior_packs and resource_packs, alongside development_behavior_packs and development_resource_packs. Understanding the difference between the standard folders and the development folders will save you hours of frustration.

When you are actively building and testing an Add-On, you should always place your working folders inside development_behavior_packs and development_resource_packs. When you add a pack from a development folder to a test world, Minecraft links directly to that folder rather than copying its contents into the world save. This means you can edit a JSON file, save it, and either run the /reload command in-game (for behavior files and scripts) or exit to the main menu and re-enter the world (for resource files and definitions) to immediately see your changes.

By contrast, when you double-click a packaged .mcpack or .mcaddon file, Minecraft extracts and installs the files into the standard behavior_packs and resource_packs folders. When you apply a pack from those standard folders to a world, the game copies the entire pack into the world's own internal folder structure. If you later edit the files inside the standard behavior_packs directory, your world will ignore your edits because it is reading from its own cached copy.

Extension / FolderWhat It IsHow Minecraft Handles It
development_behavior_packs / development_resource_packsUncompressed working foldersReferenced directly by the world; edits take effect upon reloading or re-entering the world.
behavior_packs / resource_packsInstalled release foldersCopied into the world folder when applied; requires removing and re-applying the pack to update.
.mcpackA single BP or RP compressed as a ZIP and renamedAutomatically imports the pack into the game's standard folders when opened.
.mcaddonA ZIP archive containing both a BP and an RP (or multiple .mcpack files)Extracts and imports all contained packs into the game simultaneously.

Vanilla Overriding vs. Custom Additions

Add-Ons modify the game in one of two ways: by overriding existing vanilla files or by registering brand-new content. Overriding relies on how Minecraft stacks packs in a priority list. At the bottom of the stack sits the built-in vanilla pack. When you activate your Add-On, it sits on top of the vanilla pack. If your Resource Pack contains a file at textures/blocks/stone.png, or your Behavior Pack contains entities/zombie.json using the identifier minecraft:zombie, the game will ignore its own vanilla file and load yours instead.

While overriding is the quickest way to tweak vanilla mob stats or swap textures, it comes with a major drawback: pack conflicts. If a player loads two different Add-Ons that both modify entities/player.json or entities/zombie.json, only the pack sitting higher in the world's load order will take effect; the lower pack's changes to that file are completely discarded.

Because of this, modern Add-On development favors adding new content under a custom namespace and using the Script API or spawn rules to integrate it into the world. When you create files under your own namespace (such as mypack:emerald_sword), they do not collide with vanilla files or other creators' Add-Ons, allowing players to combine multiple packs in a single world without breaking gameplay.

Going Beyond JSON with the Script API

While JSON components cover the vast majority of standard survival mechanics—like block placement, crafting, mob movement, and basic item consumption—there are times when declarative data is not enough. If you want to trigger custom logic when a player hits a specific block with a specific tool, build custom server-side forms, manipulate scoreboards dynamically, or calculate complex math across multiple entities, you use the Script API.

The Script API allows you to run JavaScript (or TypeScript compiled down to JavaScript) inside a Behavior Pack. Rather than replacing JSON, scripts complement it. You still define your custom blocks, items, and entities in JSON, and then register custom components or listen to world events in JavaScript using native modules like @minecraft/server. Adding scripts to a pack only requires declaring a script module and the appropriate module dependency inside your Behavior Pack's manifest.json.

Which versions this applies to

Applies to all modern versions of Minecraft: Bedrock Edition (1.20.0 and onward). Core JSON definitions for entities, blocks, items, recipes, loot tables, and the stable @minecraft/server Script API do not require any Experimental Toggles to be enabled on the world.

When it does not work

What you seeWhyThe fix
Your pack does not appear in the Available Packs list inside the world creation or edit menu.Minecraft failed to parse your manifest.json due to a syntax error (such as a missing comma or trailing comma), or your manifest.json is nested inside an extra subfolder instead of sitting directly inside your pack's root folder.Validate your manifest.json using a JSON linter, ensure it is at the top level of your pack directory (e.g., development_behavior_packs/MyPack/manifest.json), and enable the Creator Content Log in Settings > Creator to view the exact line number of any parsing errors.
Importing a .mcpack fails with the message 'Failed to import: Duplicate pack detected'.A pack with the exact same header UUID or module UUID already exists in your behavior_packs, resource_packs, or development folders.Generate two brand-new version 4 UUIDs and replace the existing ones in the header and modules sections of your manifest.json, or delete the older version of the pack from your storage settings before importing.
You edit a JSON file in your Behavior Pack, load the world, and none of your changes appear in-game.Your pack was installed into the standard behavior_packs folder rather than development_behavior_packs, causing the world to run a cached copy of the pack stored inside the world's own db/behavior_packs folder.Move your working pack folder into development_behavior_packs (and its resource counterpart into development_resource_packs), remove the old pack from your test world, and apply the development version instead.
The Content Log shows '[Json][error] Failed to parse...' or complains about an unrecognized component name.The format_version at the top of your JSON file is older than the version in which that component was introduced, or you accidentally placed a Resource Pack component inside a Behavior Pack file.Update the format_version string at the top of the file to a modern engine version (such as 1.20.80) and verify that the component belongs to the pack type (BP vs. RP) you are editing.

Reference, straight from the game files

Read out of the game itself, so the ids match the version you are building for.