Block metadata used to live in three places — PHP registration, JavaScript registration and an enqueue call — and block.json is all three.
{
"apiVersion": 2,
"name": "turkerdev/notice",
"title": "Notice",
"category": "text",
"attributes": {
"tone": { "type": "string", "default": "info" }
},
"editorScript": "file:./index.js",
"style": "file:./style.css"
}
// register_block_type( __DIR__ ); ← that is the whole PHP
apiVersion: 2 is the one that matters for markup: it opts into the block wrapper being applied by useBlockProps rather than by the editor, which removes a div and makes the editor markup match the front end. The file: prefix makes WordPress handle registration and versioning of the asset, so the enqueue call disappears. It also means the block can be read by tooling — the block directory and the pattern of scaffolding tools both depend on it.