How Bedrock Splits Block Files
When you create a custom block, you work across both the Behavior Pack (BP) and the Resource Pack (RP). The Behavior Pack holds the main block definition inside the BP/blocks/ folder. One file per block is the standard convention. This JSON file assigns the block its unique identifier, puts it into the Creative inventory, and lists components that control hardness, collision, light emission, and even which geometry and textures to use.
The Resource Pack does not need a matching file per block. Instead, it uses a single master registry at RP/blocks.json (for vanilla-style cube blocks) and a texture atlas at RP/textures/terrain_texture.json. The terrain atlas assigns short string names to your actual PNG files so that either RP/blocks.json or the BP's material instances component can reference them without typing out full file paths.
The Behavior Pack Definition
Every custom block starts with a JSON file in BP/blocks/. At the top of the file, format_version tells the game which parser rules to use; stick to a modern version like 1.20.80 so you have access to stable components without needing experimental toggles. Inside minecraft:block, the description object sets the identifier and optionally places the block in the Creative menu.
Your identifier must have a namespace followed by a colon and the block name, all in lowercase. Never use minecraft as your namespace for custom blocks—the game rejects or breaks custom content that tries to register under the reserved vanilla namespace.
{
"format_version": "1.20.80",
"minecraft:block": {
"description": {
"identifier": "my_pack:slate_tile",
"menu_category": {
"category": "construction",
"group": "itemGroup.name.stoneBrick"
}
},
"components": {
"minecraft:destructible_by_mining": {
"seconds_to_destroy": 2.0
},
"minecraft:destructible_by_explosion": {
"explosion_resistance": 6.0
},
"minecraft:light_emission": 0,
"minecraft:map_color": "#3b3d42"
}
}
}Core Gameplay Components
Without any components, a custom block uses default fallbacks: it breaks almost instantly, has a standard 16x16x16 unit collision box, and emits no light. You customize this behavior by adding entries to the components object. If you have looked at older packs, you might see names like minecraft:destroy_time or minecraft:block_light_emission; those were experimental names from the 1.16 to 1.18 era and have been replaced by stable equivalents.
The table below covers the foundational components you will put on almost every block you make.
| Component | What it does | Notes |
|---|---|---|
| minecraft:destructible_by_mining | Sets how long the block takes to break by hand, or makes it unbreakable. | Pass a boolean false to make it unbreakable like bedrock, or an object with seconds_to_destroy. |
| minecraft:destructible_by_explosion | Controls whether TNT and creepers can destroy the block. | Pass false to make it blast-proof, or an object with explosion_resistance. |
| minecraft:light_emission | Makes the block glow. | Takes an integer from 0 to 15, just like vanilla light levels. |
| minecraft:light_dampening | Controls how much sky and block light is blocked when passing through. | Takes an integer from 0 (transparent like glass) to 15 (fully opaque). |
| minecraft:friction | Controls how slippery the surface is when entities walk on it. | Takes a float from 0.0 to 0.9. Default stone is 0.4; ice is 0.98. |
| minecraft:loot | Overrides what items drop when the block is broken. | Takes a string path relative to the BP root, such as "loot_tables/blocks/slate_tile.json". By default, a block drops itself. |
Applying Textures and Sounds
There are two ways to texture a block in Bedrock. The first—and simplest for a standard six-sided cube—is to register the block inside RP/blocks.json in your Resource Pack. There you assign a sound preset and a texture shortname, either one for the whole block or an object specifying up, down, north, south, east, and west.
That shortname is then mapped to a real PNG file inside RP/textures/terrain_texture.json. Always omit the .png file extension in your JSON; the game resolves extensions automatically.
{
"format_version": "1.20.80",
"my_pack:slate_tile": {
"textures": "slate_tile_tex",
"sound": "stone"
}
}Registering the Terrain Texture
Once RP/blocks.json knows the shortname slate_tile_tex, you must define that shortname inside RP/textures/terrain_texture.json. If your PNG is located at RP/textures/blocks/slate_tile.png, your atlas file looks like this.
If you later want a custom 3D model made in Blockbench instead of a plain cube, you can skip the textures line in RP/blocks.json and instead put the minecraft:geometry and minecraft:material_instances components directly inside your Behavior Pack block file. Even when you do that, you still register the texture shortname in terrain_texture.json the exact same way.
{
"resource_pack_name": "my_pack",
"texture_name": "atlas.terrain",
"padding": 8,
"num_mip_levels": 4,
"texture_data": {
"slate_tile_tex": {
"textures": "textures/blocks/slate_tile"
}
}
}Naming the Block
When you load into a world and pull your new block out of the Creative menu, its hover tooltip will read tile.my_pack:slate_tile.name. Bedrock automatically builds this localization key by putting tile. in front of your full identifier and .name at the end.
To give it a clean display name, open or create RP/texts/en_US.lang and add a single line matching that key.
tile.my_pack:slate_tile.name=Slate TileWhich versions this applies to
Applies to Minecraft Bedrock 1.20.80 and newer. Everything shown on this page is part of the stable API and requires no experimental toggles on the world.
When it does not work
| What you see | Why | The fix |
|---|---|---|
| The block places in the world as a dirt block with the word "UPDATE!" written on every side. | The game recognizes the block ID on the server side, or in a saved chunk, but the Behavior Pack definition failed to parse—usually because of a syntax error, a typo in a component name, or a format_version that does not support one of the components you used. | Turn on the Content Log in Settings > Creator. Load the world and read the red error line naming your BP/blocks/ file to see which component or JSON line was rejected. |
| The block has a purple and black checkerboard texture in the inventory and when placed. | The shortname you wrote in RP/blocks.json (or in minecraft:material_instances) does not match any key inside RP/textures/terrain_texture.json, or the file path inside terrain_texture.json points to a PNG that does not exist. | Check that the shortname is spelled identically in both files, and verify the PNG is actually saved at the exact path listed under textures (with no .png extension in the JSON). |
| The block can be placed with /setblock, but it does not show up anywhere in the Creative inventory. | Either the menu_category object was left out of description, or category was set to "none", or the group string is not a valid vanilla item group identifier. | Add a menu_category block inside description with a valid category such as "construction", "nature", "equipment", or "items". If you are unsure of the group name, omit the group key entirely so the block lands at the bottom of the main category tab. |
Reference, straight from the game files
Read out of the game itself, so the ids match the version you are building for.
