Web Development WordPress

How to build modular WordPress websites with ACF Blocks (JSON registration guide)

A guide on building modular WordPress sites with ACF Blocks and JSON registration. How to get faster development, cleaner code, scalable architecture.

thumbnail

Modern WordPress development has moved beyond scattered templates and repetitive code. This guide demonstrates how to build component-driven WordPress websites using ACF Blocks with JSON registration, treating each section (hero banners, pricing tables, FAQs) as a self-contained, reusable module. The approach delivers cleaner code, faster development cycles, and sites that scale across projects. According to ACF’s 2025 Annual Survey, 52.26% of ACF users who work with the block editor actively leverage ACF Blocks, making this the dominant approach for PHP-focused WordPress professionals who need flexibility without JavaScript complexity.

Why organizations are moving to modular WordPress architecture

Traditional WordPress development relied heavily on monolithic themes: massive functions.php files spanning thousands of lines, theme-dependent functionality, and presentation logic tangled with business logic. This monolithic approach bundles all functionality into comprehensive systems where features are tightly coupled with design, creating maintenance nightmares and making code reuse nearly impossible.

The enterprise sector recognized this limitation first. Smaller agencies are now seeing the same benefits and value. Modular WordPress architecture delivers real reusability, maintainability, and scalability for complex environments. Companies managing multi-brand sites, regional microsites, or platforms requiring frequent feature rollouts discovered that modular development transforms logistical hassle into a controlled system.

The business case is straightforward 

  • Dedicated development teams waste fewer hours on repetitive template work
  • Quality assurance becomes more predictable when testing isolated components
  • Client training simplifies because editors work with consistent, visual blocks
  • Technical debt decreases because each module maintains its own scope

According to Atlassian’s 2024 State of Developer Experience report, 69% of developers report losing eight or more hours each week to workflow inefficiencies. In this context, modular ACF Blocks can help reduce friction by keeping teams in familiar PHP-based workflows instead of requiring React expertise and complex build toolchains.

Understanding ACF Gutenberg Blocks: The PHP alternative to React development

WordPress introduced the Gutenberg block editor to modernize content management, but the native block development pathway demands substantial JavaScript knowledge. Most WordPress developers excel at PHP but face some challenges with modern JavaScript frameworks: Gutenberg requires React, ES6+, Webpack, Node.js, and JSX.

ACF Gutenberg Blocks solve this friction. ACF Blocks uses a powerful PHP-based framework to develop custom block types without the thorough knowledge of JavaScript or React required to create WordPress blocks. Development teams already proficient in WordPress theme creation can immediately build custom blocks using the same templating patterns they know.

GetDevDone has implemented ACF Blocks across dozens of client projects because the approach delivers measurable advantages:

The technical distinction matters: ACF Blocks are rendered using a PHP template file or callback function, allowing full control over the HTML output, while native Gutenberg blocks execute client-side rendering with JavaScript. For enterprise applications requiring server-side rendering for SEO performance or teams without dedicated JavaScript engineers, this architectural choice becomes decisive.

Across ACF’s 2023–2025 user surveys, more than half of respondents who create custom blocks report using ACF Blocks, frequently citing the PHP-first workflow and reduced JavaScript requirements as key reasons. The productivity implications become apparent when junior developers can contribute to block development on day one rather than requiring months of React consulting and training.

How to create a production-ready block folder structure

Professional WordPress development demands organization. GetDevDone structures custom themes using a modular block architecture where each component exists as a self-contained unit.

Recommended folder hierarchy

/wp-content/themes/your-theme/
├── blocks/
│   ├── hero/
│   │   ├── hero.php          (Template with rendering logic)
│   │   ├── hero.scss         (Component-scoped styles)
│   │   ├── hero.js           (Optional interactions)
│   │   ├── block.json        (Block metadata and configuration)
│   │   └── preview.png       (Visual preview for block picker)
│   ├── testimonials/
│   ├── pricing-table/
│   └── faq-accordion/
└── functions.php

This structure provides immediate clarity, so the developers know exactly where block logic lives, designers can modify styles without touching PHP, and the preview image helps content editors identify blocks visually when building pages.

Each block contains 

  1. PHP template, which handles data retrieval and HTML output
  2. SCSS/CSS file, a scoped styling that won’t bleed into other components
  3. JavaScript file, providing optional interactive behavior (form validation, animations)
  4. Block.json, with metadata defining how WordPress registers the block
  5. Preview image, a screenshot displayed in Gutenberg’s block inserter

The preview image particularly matters for client usability, because editors browsing available blocks see exactly what each component looks like before insertion, reducing training requirements and preventing layout mistakes.

How to register ACF Blocks using JSON (modern method)

WordPress 5.8 introduced the block.json registration standard, replacing PHP-based registration patterns. ACF Blocks are registered with the standard WordPress function register_block_type(), which loads a block.json file containing configuration.

This JSON approach provides several advantages over legacy PHP registration:

  • Portability: copy the entire block folder to any project and it works immediately
  • Full Site Editing compatibility: JSON-registered blocks integrate seamlessly with FSE
  • Performance: WordPress can parse JSON metadata more efficiently
  • Standards compliance: aligns with WordPress core development patterns

Example block.json for a hero section

 {
  "name": "acf/hero",
  "title": "Hero Block",
  "description": "A full-width hero section with image, overlay, and text.",
  "category": "theme-blocks",
  "icon": "cover-image",
  "keywords": ["hero", "banner"],
  "acf": {
    "mode": "preview",
    "renderTemplate": "hero.php"
  },
  "supports": {
    "align": ["full", "wide"],
    "anchor": true
  },
  "example": {
    "attributes": {
      "mode": "preview",
      "data": {
        "preview_image": "preview.png"
      }
    }
  }
}

Register all blocks automatically in functions.php 

// ACF Blocks registration
add_action('init', function() {
  register_block_type(get_template_directory() . '/template-parts/blocks/hero');
});

// To enable the block preview thumbnail
function theme_get_block_preview_image($block)
{
  $html = '';

  if (is_admin() and isset($_POST['action']) and isset($_POST['block'])) {
    $block_data_str = stripslashes($_POST['block']);
    $block_data_obj = json_decode($block_data_str);

    if (is_object($block_data_obj) and is_object($block_data_obj->data) and isset($block_data_obj->data->preview_image)) {
      if (file_exists($block['path'] . '/' . $block_data_obj->data->preview_image)) {
        $home_url = home_url();
        $path = str_replace(ABSPATH, '', $block['path']);
        $path = "/{$path}/";
        $preview_url = $home_url . $path . $block_data_obj->data->preview_image;
        $html = '<img width="470" src="' . esc_url($preview_url) . '">';
      }
    }
  }
  return $html;
}

This registration pattern scales elegantly; adding a new block requires only creating the folder structure and adding the block name to the array. No cluttered acf_register_block_type() calls scattered throughout the codebase.

How to configure ACF custom blocks with field groups

ACF custom blocks gain power through structured field groups that define exactly what data content editors can input. GetDevDone follows a consistent pattern for creating field configurations.

Step-by-step field group creation 

  1. Navigate to ACF → Add New in WordPress admin
  2. Name the field group descriptively (example: “Hero Block Fields”)
  3. Add relevant field types based on content requirements

Example hero block field structure 

  • hero_title (Text) – Main headline with character limit
  • hero_subtitle (Textarea) – Supporting copy, 2-3 sentences
  • hero_image (Image) – Background image with size validation
  • hero_overlay_color (Color Picker) – Semi-transparent overlay
  • hero_cta_text (Text) – Button label
  • hero_cta_link (URL) – Button destination
  1. Configure the Location rules: Block → is equal to → Hero Block
  2. Set field validation rules (required fields, character limits, allowed file types)

The Location rules automatically bind these fields to the specific block—when editors add a Hero Block to a page, they see exactly these fields in the sidebar. No confusion, no extra options cluttering the interface.

Field validation prevents common content errors 

  • Limit title length to maintain visual consistency across pages
  • Restrict image uploads to optimized file types (WebP, JPEG) under 2MB
  • Provide helpful field instructions that appear below each input
  • Set reasonable defaults, so blocks look acceptable even with minimal input

How to render block fields in PHP templates

The PHP template controls block output. We, at GetDevDone, prioritize clean, semantic HTML with defensive coding practices that prevent display issues when editors leave fields empty.

Example hero.php template 

<?php
/**
 * Hero Block Template
 */

// Preview the block design while browsing blocks
$img = theme_get_block_preview_image($block);
if ($img) {
  echo $img;
  return;
}

// Support custom "anchor" values.
$anchor = '';
if (!empty($block['anchor'])) {
  $anchor = 'id="' . esc_attr($block['anchor']) . '" ';
}
// Create class attribute allowing for custom "className" and "align" values.
$class_name = 'block-' . str_replace(['/', '_'], '-', $block['name']);
if (!empty($block['className'])) {
  $class_name .= ' ' . $block['className'];
}
// Full Site Editing for layouts
if (!empty($block['align'])) {
  $class_name .= ' align' . $block['align'];
}

// Generate unique ID for the block
$block_id = 'id="' . 'block-acf-' . uniqid() . '" ';
$anchor = $anchor ? $anchor : $block_id;

// Get the ACF fields
$hero_title     = get_field('hero_title');
$hero_subtitle  = get_field('hero_subtitle');
$hero_image     = get_field('hero_image');
$overlay_color  = get_field('hero_overlay_color') ?: '#000000';
?>

<!-- Render the block HTML -->
<section <?php echo $anchor ?> class="<?php echo $class_name ?> hero-block" style="background-image:url('<?php echo esc_url($hero_image['url']); ?>')">
  <div class="hero-overlay" style="background-color:<?php echo esc_attr($overlay_color); ?>"></div>
  <div class="hero-content">
    <h1><?php echo esc_html($hero_title); ?></h1>
    <p><?php echo esc_html($hero_subtitle); ?></p>
  </div>
</section>

Professional template practices demonstrated 

  • Defensive defaults: Every field includes a fallback value using the ternary operator
  • Conditional rendering: Subtitle only displays when editors provide content
  • Security escaping: All output passes through esc_html(), esc_url(), or esc_attr()
  • Semantic HTML: Uses appropriate heading hierarchy and ARIA-friendly structure
  • Performance considerations: Minimal inline styles, most styling deferred to CSS

This approach prevents the dreaded “blank sections” problem where editors forget to fill required fields—the block still renders with reasonable default content.

How to style blocks with scoped CSS and SCSS

Component-scoped styling prevents the CSS cascade problems that plague monolithic themes. Each block’s styles live alongside its template, making maintenance predictable.

Example hero.scss

// Hero block styles
.hero-block {
  position: relative;
  background-size: cover;
  background-position: center;
  color: #fff;
  padding: 6rem 2rem;
  text-align: center;


  .hero-overlay {
    position: absolute;
    inset: 0;
    opacity: 0.5;
  }


  .hero-content {
    position: relative;
    z-index: 2;
    max-width: 800px;
    margin: 0 auto;
  }
}

Enqueue the compiled CSS in functions.php 

function enqueue_block_styles() {
    wp_enqueue_style(
        'hero-block-styles',
        get_template_directory_uri() . '/blocks/hero/hero.css',
        [],
        filemtime(get_template_directory() . '/blocks/hero/hero.css')
    );
}
add_action('wp_enqueue_scripts', 'enqueue_block_styles');

The filemtime() function generates cache-busting version numbers automatically—when styles update, browsers fetch the new version immediately without requiring manual cache clearing.

How to make blocks reusable across multiple projects

The modular architecture pays dividends when launching new projects. GetDevDone maintains an internal block library that accelerates delivery timelines significantly.

Reusability workflow 

  1. Version control blocks individually: Each block folder is a git submodule
  2. Document field requirements: README.md explains what fields the block expects
  3. Maintain consistent naming: Use predictable field names across all projects
  4. Test in isolation: Blocks should function independently without theme dependencies
  5. Package field definitions: Export ACF field groups as JSON, store in /acf-json

Field group JSON export eliminates repetitive configuration

ACF automatically synchronizes field groups stored in the theme’s /acf-json folder. When deploying a block to a new project, the field configuration imports automatically—no manual field recreation required.

Project deployment becomes 

# Copy block folder to new theme

cp -r /library/blocks/hero /new-project/wp-content/themes/client-theme/blocks/

# Register block in functions.php

# Field groups auto-import from /acf-json

# Block appears immediately in Gutenberg

This approach transforms block development from project-specific work into asset creation, and each block built becomes a permanent library resource that reduces future development time.

Gutenberg “Add Block” panel preview

Front-end preview

Advanced techniques: Adding dynamic logic to ACF Blocks

Static blocks serve many use cases, but complex websites often require context-aware behavior. PHP templates can include conditional logic that adapts block output based on page context.

Example: Homepage-specific styling

php<?php
// Detect homepage and adjust hero height
$is_homepage = is_front_page();
$hero_height = $is_homepage ? '100vh' : '60vh';
?>
<section
class="hero-block <?php echo $is_homepage ? 'hero-homepage' : ''; ?>"
style="min-height: <?php echo $hero_height; ?>;"
>
<!-- Template content -->
</section>

Example: Dynamic content from custom post types

php<?php
// If this hero is on a service page, pull related case studies
if (is_singular('service')) {
$related_cases = new WP_Query([
'post_type' => 'case-study',
'posts_per_page' => 3,
'meta_key' => 'related_service',
'meta_value' => get_the_ID()
]);


if ($related_cases->have_posts()) {
echo '<div class="hero-related-cases">';
while ($related_cases->have_posts()) {
$related_cases->the_post();
// Display case study cards
}
echo '</div>';
wp_reset_postdata();
}
}
?>

Example: A/B testing variations

php<?php
// Randomly select hero variant for conversion testing
$hero_variant = (rand(1, 2) === 1) ? 'variant-a' : 'variant-b';
$cta_text = ($hero_variant === 'variant-a')
? 'Start Free Trial'
: 'See How It Works';
?>

<section class="hero-block <?php echo $hero_variant; ?>">
<!-- Variant-specific content -->
<a href="<?php echo $cta_link; ?>"
data-variant="<?php echo $hero_variant; ?>">
<?php echo $cta_text; ?>
</a>
</section>

These patterns demonstrate how ACF Blocks transcend simple content containers. They become intelligent components that adapt to context, integrate with business logic, and support more refined website functionality.

Benefits of ACF Blocks for professional WordPress development

According to the published ACF’s 2025 Annual Survey, 52.26% of ACF users who work with the block editor choose to build custom blocks with ACF Blocks rather than writing JavaScript. This majority adoption among professional developers reflects the approach’s practical advantages in production environments.

The ROI becomes particularly evident for agencies managing multiple client websites. According to industry analysis, PHP-experienced developers create production-ready ACF blocks within 4-6 hours of initial learning, and development time decreases significantly as teams build reusable block libraries. That efficiency compounds, as clients receive better value, project margins improve, and developers spend more time solving critical issues rather than rewriting testimonial sections.

Production deployment checklist for ACF Blocks

Before launching ACF Blocks to production environments, GetDevDone follows a systematic quality assurance process:

Technical validation 

  • All blocks register successfully and appear in the Gutenberg inserter
  • Field groups bind correctly to their respective blocks
  • Default values prevent blank sections when fields are empty
  • Responsive behavior verified across mobile, tablet, and desktop viewports
  • Accessibility testing confirms keyboard navigation and screen reader compatibility
  • Performance testing shows no significant layout shift or render blocking

Content editor validation 

  • Block previews display accurately in the editor
  • Field instructions provide clear guidance for content entry
  • Validation rules prevent common input errors
  • Block patterns and reusable blocks function as expected
  • Undo/redo operations work correctly without data loss

Browser compatibility 

  • Verified in Chrome, Firefox, Safari, Edge
  • Admin interface functions on both desktop and mobile devices
  • No console errors in any supported browser

Security verification 

  • All output properly escaped (esc_html, esc_url, esc_attr)
  • File upload restrictions are configured appropriately
  • User capability checks restrict block management to appropriate roles

This systematic approach prevents the common deployment issues that erode client confidence: broken layouts, confusing interfaces, or security vulnerabilities.

 Getting started: How to build your first ACF Block 

The transition to modular WordPress development doesn’t require rebuilding an entire website. GetDevDone recommends starting with a single, high-value component.

Recommended first blocks for new adopters 

  1. Testimonial block with simple structure, high visual impact
  2. Call-to-action banner with frequent use case, consistent styling
  3. Team member profile containing structured data, repeatable pattern
  4. FAQ accordion with interactive behavior, content organization

Implementation timeline 

  • Week 1: Build one block, test thoroughly, deploy to staging
  • Week 2: Create field documentation, train editors on usage
  • Week 3: Monitor editor feedback, refine field structure if needed
  • Week 4: Build the second block, reusing patterns from the first implementation

Within one month, development teams establish the patterns, documentation, and confidence needed to accelerate future block creation. The investment pays returns immediately and continues delivering value across every subsequent project.

Why this approach defines professional WordPress development

The WordPress space has matured beyond hobby projects and simple brochure sites. In our white label web development practice, GetDevDone builds client sites using component-driven architecture as the standard for delivering maintainable, scalable, and efficient websites. This approach separates frontend presentation, backend logic, and content workflows into self-contained modules that align technical structure with business objectives.

According to ACF’s 2024 Annual Survey, hybrid development methods now represent 50.15% of implementations, proving the industry’s move toward flexible, modular systems. This shift reflects real business needs: marketing teams require fast content iteration, development teams need predictable maintenance costs, and organizations demand websites that adapt to their strategy rather than periodic rebuilds.

ACF Blocks with JSON registration create the technical foundation for this approach. The methodology minimizes the false choice between developer control and editor flexibility: fully-featured websites can offer both. Content creators get intuitive visual tools, while developers maintain clean, version-controlled code that scales to production demands.

The key advantage of this approach is that it lets teams ship projects faster, maintain codebases more easily, and scale sites more efficiently. It doesn’t sacrifice capability or performance; it offers a more practical way to structure custom WordPress development when professional results matter.

Anup Tamang

Meet Anup K. Tamang, a seasoned Full-Stack Developer at GetDevDone. With a wealth of experience in web development under his belt, Anup has successfully honed his skills to master both front-end and back-end processes.

But Anup's passion extends beyond coding and developing innovative websites.

An enthusiastic blog writer, he loves to share his knowledge with others. His mission is to empower those who are eager to excel in web development by sharing his insights, experiences, and best practices.

For more professional insights from Anup, connect with him on LinkedIn.