Build classic and block WordPress themes from scratch: the template hierarchy, The Loop, the_title() and the_content(), template parts, menus, the Customizer, child themes and theme.json.
Lessons
A block theme builds every template out of blocks and configures its design in a single theme.json file, so the site owner can edit the whole site — header, footer, templates and styles — visually in the Site Editor.
gdc-blocks/
├── style.css Theme header (same as a classic theme)
├── theme.json Design settings and styles
├── templates/
│ └── index.html Required: the fallback template
└── parts/
├── header.html
└── footer.htmlThere is no index.php, no header.php, and usually only a tiny functions.php. WordPress recognises the theme as a block theme because templates/index.html exists.
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"settings": {
"appearanceTools": true,
"layout": {
"contentSize": "720px",
"wideSize": "1200px"
},
"color": {
"defaultPalette": false,
"palette": [
{ "slug": "base", "name": "Base", "color": "#ffffff" },
{ "slug": "contrast", "name": "Contrast", "color": "#1e293b" },
{ "slug": "accent", "name": "Accent", "color": "#6c63ff" }
]
},
"typography": {
"fluid": true,
"fontSizes": [
{ "slug": "small", "name": "Small", "size": "0.9rem" },
{ "slug": "medium", "name": "Medium", "size": "1.125rem" },
{ "slug": "large", "name": "Large", "size": "2rem", "fluid": { "min": "1.5rem", "max": "2.5rem" } }
]
},
"spacing": {
"units": [ "px", "rem", "%", "vw" ]
}
},
"styles": {
"color": {
"background": "var(--wp--preset--color--base)",
"text": "var(--wp--preset--color--contrast)"
},
"typography": {
"fontSize": "var(--wp--preset--font-size--medium)",
"lineHeight": "1.7"
},
"elements": {
"link": {
"color": { "text": "var(--wp--preset--color--accent)" }
},
"h1": {
"typography": { "fontSize": "var(--wp--preset--font-size--large)" }
}
}
},
"templateParts": [
{ "name": "header", "title": "Header", "area": "header" },
{ "name": "footer", "title": "Footer", "area": "footer" }
]
}| Key | What it does |
|---|---|
settings | Decides which options exist — the colour palette shown in the editor, available font sizes, whether custom colours are allowed. |
styles | Applies default styling — the site background, body font size, link colour, per-block styles. |
templateParts | Registers template parts and which area of the Site Editor they belong to. |
Every palette colour becomes a CSS custom property: accent becomes --wp--preset--color--accent. Use those variables in any extra CSS, and the whole site follows when the owner changes a colour in Styles.
| Choose a block theme when | Choose a classic theme when |
|---|---|
| The client wants to edit headers, footers and layouts themselves | Heavy PHP logic decides what appears on each page |
| You are starting a brand-new site | You are maintaining an existing classic site |
| Design consistency through presets matters | A plugin you rely on only supports classic templates |
Tip: Classic themes can adopt theme.json too. Adding one to GDC Starter gives you the editor colour palette and font sizes without converting a single template.gdc-blocks folder with style.css, theme.json and an empty templates/index.html, and activate it.theme.json and watch links update.In accordance with Section 6 & Section 7 of the DPDP Act 2023, third-party analytics and marketing trackers are strictly gated behind your affirmative consent. You may withdraw consent at any time under Section 6(4).
Essential for session authentication (ci_session), Cross-Site Request Forgery security (csrf_cookie_name), and Cloudflare DDoS/bot prevention. Cannot be disabled.
Gated under DPDP Section 7. Allows Google Analytics 4 (Google Consent Mode v2) to measure aggregate, anonymized tool usage.
Enables browser local storage to preserve your theme selection (dark/light mode) and code editor layout between visits.
Used to display developer sponsorships and native tool partner notices.