-
Notifications
You must be signed in to change notification settings - Fork 0
Anti Patterns
Concrete bad-code / good-code pairs. Read this before editing if uncertain. Most of these are caught by python3 bin/check.py, but the lessons are worth internalizing.
- "core/time-to-read": { ... } // not a real block
+ "core/post-time-to-read": { ... } // verified
- "core/comments-link": { ... } // not a real block
+ "core/post-comments-link": { ... } // verified
- "core/term-query": { ... } // not a real block
+ "core/terms-query": { ... } // verifiedAlways run python3 bin/validate-theme-json.py after editing theme.json. The script verifies every block name against the live Gutenberg and WooCommerce sources.
- "color": { "background": "#FAFAF7" }
+ "color": { "background": "var(--wp--preset--color--base)" }
- "spacing": { "padding": { "top": "24px" } }
+ "spacing": { "padding": { "top": "var:preset|spacing|lg" } }
- "typography": { "fontSize": "1.5rem" }
+ "typography": { "fontSize": "var(--wp--preset--font-size--md)" }Why: hardcoded values defeat the entire design-token system. Project clones can't restyle without editing every file.
To discover tokens: python3 bin/list-tokens.py
- /* in the css escape hatch */
- color: var(--wp--preset--color--accent) !important;
+ /* fix the specificity at the source: scope the rule narrower, or move it into theme.json's per-block styles */!important is a sign the design tokens or block scope are wrong. Fix the cause, not the symptom. The check script will fail any commit that introduces an !important anywhere.
- assets/css/custom.css
- add_action('wp_enqueue_scripts', 'obel_enqueue_styles');
+ // Move the styling into theme.json → styles.blocks.<block-name>Obel has zero CSS files except style.css (which is just the theme header). The block style engine handles everything.
- register_block_type(__DIR__ . '/blocks/my-card');
+ // Build the layout as a pattern instead. patterns/<your-card>.php
+ // Or compose existing blocks: core/group + core/columns + core/imageCustom blocks require JS, which means a build step, which violates the "pure PHP + JSON + HTML" rule.
- add_action('wp_enqueue_scripts', static function () {
- wp_enqueue_style('obel-extras', get_template_directory_uri() . '/assets/extras.css');
- wp_enqueue_script('obel-js', get_template_directory_uri() . '/assets/main.js');
- });
+ // Don't. The theme has no CSS files and no JS bundles.
+ // For new visual behavior, use core blocks that ship the interactivity (Accordion, Details, Modal, etc.).- <!-- wp:acme/fancy-hero -->
+ <!-- wp:cover --> + child blocks
- <!-- wp:my-plugin/product-grid -->
+ <!-- wp:woocommerce/product-collection -->Run python3 bin/check.py to scan for forbidden namespaces.
- esc_html_e( 'This season\u2019s picks', 'obel' ); // renders literally as: This season\u2019s picks
+ esc_html_e( 'This season\'s picks', 'obel' ); // renders as: This season's picksIn PHP single-quoted strings, only \\ and \' are processed as escapes. \u2019 becomes the literal four characters.
- "A robust, comprehensive solution that seamlessly leverages WordPress's powerful tapestry..."
+ "A block-only WooCommerce starter theme. Pure PHP + JSON + HTML, no build step."bin/check.py will flag the words: leverage, robust, comprehensive, seamless, delve, tapestry, and em-dashes (—) in README.md, readme.txt, and style.css.
The wiki is not subject to this rule (so this very page contains the offending words to make the point clear).
{
+ "$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"title": "Dark",
"settings": { ... }
}Without $schema, your editor cannot autocomplete or validate the file in real time. Always include it for theme.json and every file in styles/.
- // functions.php
- register_block_style('core/button', [
- 'name' => 'outline',
- 'label' => 'Outline',
- ]);
+ // theme.json → styles.blocks.core/button.variations.outlineSingle source of truth: theme.json. PHP block-style registration creates a second source the design system has to track.
- add_editor_style('assets/editor.css');
+ // Don't. theme.json automatically syncs styles to the block editor.
+ // There is no separate editor stylesheet to load.- // theme.json palette additions
- { "slug": "Gold-Accent", "name": "Gold", "color": "#D4AF37" } // wrong: capitals + reserved suffix
- { "slug": "gold_accent", "name": "Gold", "color": "#D4AF37" } // wrong: underscore
+ { "slug": "gold", "name": "Gold", "color": "#D4AF37" } // lowercase, hyphen-separated, no role suffixSlug rules:
- All lowercase.
- Hyphens only as separators.
- Don't append the category to the slug name (
gold, notgold-color).
- {
- // primary color used for buttons
- "primary": "#1A1A1A"
- }
+ // JSON does not allow comments. If a value needs explanation, document it in the wiki.bin/check.py will fail JSON parsing if you do this.
<!-- wp:group {"layout":{"type":"constrained"}} -->
<div class="wp-block-group">
<!-- wp:paragraph -->
<p>...</p>
- <!-- /wp:paragraph --> // missing
+ <!-- /wp:paragraph -->
</div>
<!-- /wp:group -->The block parser is strict. A missing closing comment breaks the entire template silently in the editor.
For self-closing blocks (no inner content), use /-->:
<!-- wp:site-title /-->theme.json supports a css field on styles.blocks.* entries (and a top-level styles.css). It's an escape hatch — and it's a code smell if you're using it more than 2-3 times.
- "core/post-comments-form": {
- "css": ".comment-form-field { display: flex; gap: 8px; }"
- }
+ // The form layout is a CSS layout problem the block doesn't expose attributes for.
+ // Solution 1: accept the default browser layout. Comments forms don't need to be art.
+ // Solution 2: if it really matters, write the CSS — but use design tokens.
+ "core/post-comments-form": {
+ "css": ".comment-form-field { display: flex; gap: var(--wp--preset--spacing--xs); }"
+ }The escape hatch exists because the block style engine doesn't cover everything (negative margins, complex form layouts, third-party WC default styles). Use it, but use design tokens inside it.
- add_theme_support('post-thumbnails'); // FSE themes get this automatically
- add_theme_support('automatic-feed-links'); // automatic in WP 5.5+
- add_theme_support('title-tag'); // automatic in FSE themes
+ // functions.php should only contain things FSE themes don't get for free.Look at the existing functions.php before adding anything. If it's already there, don't duplicate. If WordPress already provides it, don't add it.
Fifty on GitHub · Live demos · GPL-2.0-or-later · Block-only WooCommerce themes, zero CSS files, zero JS, zero build step