Guide

Development guidelines

These guidelines outline best practices and standards for development on the PRC Platform, emphasizing our "block first" mindset. We are, perhaps, one of the most Gutenberg block-heavy WordPress applications in the world, and we aim to leverage the full potential of blocks in everything we do. We aim to be "where the puck is going," not "where it has been." To achieve this, we closely follow the future of the Gutenberg project, and align our practices and roadmap as closely as possibly, as it represents the future of WordPress. Additionally, we strive for high code quality and consistency across our codebase to facilitate contributions and maintenance by developers.

WordPress VIP Optimization

  • Optimize for WordPress VIP infrastructure
  • Consider edge cdn cache, memcached object cache, and varnish page cache.
  • Use VIP-approved functions and avoid restricted functions.

Code Standards

  • PHP: Follow WordPress VIP coding standards
  • JavaScript/TypeScript: Use functional programming patterns, avoid classes.
  • CSS: Use SCSS with BEM methodology where applicable
  • Accessibility: Implement ARIA roles and attributes as priority
  • Performance: Optimize for readability while maintaining efficiency

File Structure

Standard block structure in plugins:

plugins/ File tree
  • prc-{plugin-name}/
    • src/
      • {block-name}/
        • block.json
        • index.js
        • edit.js
        • save.js
        • render.php
        • view.js
        • style.scss
        • editor.scss
Typical block package layout. Metadata lives in block.json; dynamic blocks use render.php.
  • Plugin-specific functionality goes in respective prc-* plugins
  • Shared utilities in prc-platform-core
  • Custom blocks in prc-block-library
  • Each plugin follows WordPress Plugin Boilerplate structure with main PHP file, loader, includes, assets, and tests. See: plugins/.plugin-bootstrap-template for reference.

Related: Gold standard blocks, Plugin docs.


Block Development

"Block First" Architecture Principles

  • Block-first mindset: Every UI component should be evaluated as a potential block or block pattern
  • Block Context API: Use providesContext/usesContext in block.json for parent-child data flow between nested blocks (e.g., Query blocks providing post data to child blocks)
  • Block Supports API: Leverage native block supports (spacing, colors, typography) over custom implementations for consistency
  • WordPress Interactivity API: Use data-wp-interactive, data-wp-context, data-wp-bind directives for frontend state management
  • Editor-Frontend Parity: Maintain 1:1 visual consistency between editor and frontend.

Block Development Patterns

  • Prefer dynamic blocks (render callbacks) for data-driven content
  • Use InnerBlocks for composable block structures
  • Implement block variations over duplicate blocks
  • Follow progressive enhancement: static HTML base, JavaScript enhancement via Interactivity API
  • Share rendering logic between edit.js and save.js/render.php

Block Context Patterns

When developing blocks that share data:

// Parent block's block.json
{
  "providesContext": {
    "prc/postId": "postId",
    "prc/datasetId": "selectedDataset"
  }
}

// Child block's block.json
{
  "usesContext": ["prc/postId", "prc/datasetId"]
}

Common PRC context patterns:

  • prc-quiz-builder → provides quiz state to question, answer, and result blocks and block bindings.
  • Quiz submission recovery (prc-quiz-builder) — On the frontend, the quiz controller Interactivity store (plugins/prc-quiz-builder/src/controller/submission-recovery.js) persists a failed or in-flight submission in browser localStorage under keys prefixed with prc-quiz-builder__pending-submission, scoped by quizId and a per-attempt hash. If the REST submit to /prc-api/v3/quiz/submit errors, the user sees a recovery message and can retry; successful submit clears the pending record and navigates to the stored results URL. REST quizId arguments are validated as positive numeric post IDs (includes/class-rest-api.php, is_valid_quiz_id). When debugging “stuck” quizzes in the field, check private/incognito mode (no prior storage), ad blockers or offline behavior affecting apiFetch, and that the quiz post ID in context matches a real published quiz.
  • prc-block-library/dialog → provides id to inner dialog-element and dialog-trigger blocks for interactivity.
  • prc-religious-landscape-study → provides complex data structure via block context to a variety of project specific blocks for data visualization.

Using block context is also a great way to share data between blocks in the editor. As well as hydrating interactivity API state or context on the frontend.

Block Integration Patterns

Cross-Plugin Block Communication

Many PRC plugins provide blocks that work together through:

  1. Block Context: Parent blocks from one plugin providing data to child blocks from another
  2. Interactivity API Context: Frontend state sharing between blocks via data-wp-context and wp_interactivity_state.
  3. Block Hooks: Using WordPress block filters to extend functionality

Example integrations:

  • prc-elasticpress plugin blocks prc-ep/facets-* utilize form-input-* blocks from prc-block-library for building their interface.

Block-First Development Checklist

When implementing new features:

  1. ✅ Can this be a block or block pattern?
  2. ✅ Does an existing block meet the need?
  3. ✅ Can a block binding for a core block be created and used instead?
  4. ✅ Does it need Block Context for parent-child communication?
  5. ✅ Should it provide context to potential child blocks?
  6. ✅ Does it need frontend interactivity via Interactivity API?
  7. ✅ Can it leverage existing Block Supports (colors, spacing, typography)? If not, what additional colors and styling attributes are needed?
  8. ✅ Is there a need for custom block variations?
  9. ✅ Is there visual parity between editor and frontend?
  10. ✅ Does it follow progressive enhancement principles?

Architecture Decisions

Why Block-First?

  • Composability: Blocks can be combined to create complex layouts
  • Reusability: Block patterns and variations reduce code duplication
  • User Empowerment: Editorial teams can build without developer intervention
  • Consistency: Block Supports ensure design system adherence

Context vs Props vs Attributes

  • Block Attributes: User-configurable settings stored in post content
  • Block Context: Parent-to-child data flow without prop drilling
  • Interactivity API Context: Frontend reactive state management
  • PHP Context: Server-side data passed via render_callback

Was this helpful?