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:
-
prc-{plugin-name}/-
src/-
{block-name}/-
block.json -
index.js -
edit.js -
save.js -
render.php -
view.js -
style.scss -
editor.scss
-
-
-
- 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/usesContextin 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-binddirectives 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 browserlocalStorageunder keys prefixed withprc-quiz-builder__pending-submission, scoped byquizIdand a per-attempthash. If the REST submit to/prc-api/v3/quiz/submiterrors, the user sees a recovery message and can retry; successful submit clears the pending record and navigates to the stored results URL. RESTquizIdarguments 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 affectingapiFetch, 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:
- Block Context: Parent blocks from one plugin providing data to child blocks from another
- Interactivity API Context: Frontend state sharing between blocks via
data-wp-contextandwp_interactivity_state. - Block Hooks: Using WordPress block filters to extend functionality
Example integrations:
prc-elasticpressplugin blocksprc-ep/facets-*utilize form-input-* blocks from prc-block-library for building their interface.
Block-First Development Checklist
When implementing new features:
- ✅ Can this be a block or block pattern?
- ✅ Does an existing block meet the need?
- ✅ Can a block binding for a core block be created and used instead?
- ✅ Does it need Block Context for parent-child communication?
- ✅ Should it provide context to potential child blocks?
- ✅ Does it need frontend interactivity via Interactivity API?
- ✅ Can it leverage existing Block Supports (colors, spacing, typography)? If not, what additional colors and styling attributes are needed?
- ✅ Is there a need for custom block variations?
- ✅ Is there visual parity between editor and frontend?
- ✅ 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