Gutenberg Page Creation SOP
A step-by-step standard operating procedure for creating a new WordPress page in Gutenberg, from a blank canvas to a published, styled page.
Who it is for
Content editors and site builders who need a repeatable page-creation checklist.
After reading it
You will be able to create a new page following the same checklist used in production WordPress builds.
_Revision note: updated for paginated Gutenberg block discovery, governed conversion-context fallback, and validation-before-proposal requirements._
Purpose
This SOP standardizes how pages should be created, imported, converted, and refined in a Gutenberg-first workflow.
It is designed for four common use cases:
- Create a page from scratch.
- Import a page from the internet as inspiration or source material.
- Convert custom HTML to Gutenberg-native blocks.
- Rebuild a legacy page into a scalable, editor-friendly Gutenberg system.
The goal is always the same:
- preserve or improve visual quality
- preserve semantic structure
- maximize Gutenberg-native editing
- minimize raw HTML dependence
- keep styling layered and governable
- make future reuse easier through patterns and dynamic blocks
Core operating principles
1. Structure first, styling second
Do not begin by chasing exact visual parity through CSS. First identify the page structure, section hierarchy, reusable patterns, and component types.
2. Gutenberg-native first
Use core blocks whenever they can represent the content cleanly. Use patterns for reusable section compositions. Use custom dynamic blocks only when runtime rendering or domain-specific behavior is required. Use raw HTML only as a temporary migration fallback.
3. Builder settings before CSS
Whenever a sizing, spacing, alignment, or layout behavior can be set in Gutenberg block settings, set it there first. Container width, alignment, columns, spacing, stacking, and layout belong in the builder whenever possible.
4. theme.json before custom CSS
Shared tokens and system-level defaults belong in theme.json. Do not put repeatable design decisions into ad hoc CSS if they can be expressed through tokens or block defaults.
5. CSS only for what the editor and theme.json cannot express cleanly
Use CSS for section-specific behavior, layout refinements, visual parity, and animations that exceed builder/theme.json capabilities.
6. Proposal-first and draft-first for risky work
When reconstructing or converting a page, use a draft or proposal target first. Do not iterate directly on production unless the change is trivial and reversible.
7. Patterns before pages
If a section will likely repeat or should be standardized, build the pattern first or at least model the section as a repeatable pattern candidate.
8. Dynamic blocks replace shortcodes
If a section currently depends on a shortcode and should remain runtime-driven, the long-term target is usually a custom dynamic block with editor preview.
9. Discover blocks through paginated drilldown
Do not request the full Gutenberg block or pattern catalog in one call. Start with category discovery, then list blocks or patterns by category/source, then request detail only for the blocks or patterns that will actually be used.
10. Governed context first, safe read fallback second
For GPT-assisted conversion, use governed conversion context when available. If governed context is blocked by permissions, use safe read-only context for analysis and clearly disclose that the governed conversion context was unavailable.
11. Validate before proposal or update
Always validate final serialized block markup before proposing or applying a page update. Validation is required even when the conversion was assembled from core-only blocks.
Standard page workflow
Phase 1: Intake and target definition
Step 1. Identify the target page and intent
Document:
- page name
- URL or source
- whether this is a new page, rebuild, import, or conversion
- whether the page is static, semi-reusable, or runtime-driven
- whether work should happen in production or in a draft sandbox
Step 2. Classify the source material
Classify the page source into one of these types:
- Gutenberg-native blocks already present
- custom HTML inside WordPress
- source-controlled HTML
- third-party webpage inspiration
- PDF/image mockup
- mixed source
Step 3. Define the output type
Decide whether the final output should be:
- a single Gutenberg page
- a page built from reusable patterns
- a page plus one or more custom blocks
- a new reusable section library
Phase 2: Page decomposition
Step 4. Break the page into section-level hierarchy
For each page, create a section inventory. Typical example:
- page container
- hero
- split explainer section
- card grid
- quote or proof section
- CTA band
- footer transition
Each section should be named by function, not by appearance. Examples:
homepage-herowhy-this-matters-splitresources-gridfinal-dark-cta
Step 5. Create the component hierarchy inside each section
For each section, identify:
- outer section shell
- inner width shell
- primary layout block
- content blocks
- media block(s)
- action block(s)
- list/quote/card/repeater elements
Example hero hierarchy:
- section shell
- width shell
- two-column layout
- copy column
- eyebrow
- H1
- lede
- CTA row
- pill list
- media column
- book cover or product media
Step 6. Mark repeatability and runtime behavior
For each section ask:
- Is this repeated elsewhere?
- Should it become a pattern?
- Does any part require runtime rendering?
- Does any part need editor preview of dynamic data?
Phase 3: Block selection logic
Decision tree for choosing the component type
Use a core block when:
- the content maps cleanly to native Gutenberg semantics
- the author should edit it directly
- no runtime data is required
- no special business logic is needed
Examples:
- headings
- paragraphs
- buttons
- lists
- quotes
- images
- groups
- columns
- separators
Use a pattern when:
- the section is a repeatable composition of blocks
- the layout recurs across pages
- the content is editable but the structure should start from a standardized template
- the section is not primarily data-driven
Examples:
- hero sections
- split content sections
- three-card grids
- CTA bands
- FAQ wrappers
Use a custom static block when:
- the component is structurally unique enough that a pattern is too loose
- authors need a constrained editing UI
- the component still does not require runtime data
Use sparingly.
Use a custom dynamic block when:
- output depends on runtime data
- output depends on products, media, posts, options, or other central data sources
- shortcode-backed behavior is being modernized
- you need consistent frontend output plus editor preview
Examples:
- product panels
- book-cover renderers
- query-driven feature blocks
- data-aware promo modules
Use raw HTML only when:
- the section cannot yet be safely mapped to blocks
- the HTML needs temporary quarantine during migration
- the block conversion path is not complete
Raw HTML is not the target end state.
Phase 3A: Gutenberg block discovery protocol for GPT Actions
This phase applies whenever a Custom GPT, MCP/OpenAPI action, or other AI operator needs to inspect available Gutenberg blocks and patterns.
Step 3A.1. Never request the full catalog in one call
Do not ask for every registered block and pattern at once. Full catalogs can exceed Custom GPT action-response limits and can distract the model with irrelevant block types.
Step 3A.2. Start with category discovery
Call:
blocks.catalog mode=categories
Use the response to identify available categories, sources, counts, and likely drilldown targets.
Step 3A.3. List candidates by category and source
Call:
blocks.catalog mode=list category=<category> source=<source> page_size<=20
Use page_size of 20 or less unless a smaller page is sufficient. Do not broaden the query unless the category result does not contain usable candidates.
Step 3A.4. Continue only as needed
If the response includes next_cursor, continue pagination only until enough candidates are found. Do not exhaust every page by default.
Step 3A.5. Drill into selected blocks only
Call:
blocks.catalog mode=detail name=<block_or_pattern_name>
Use detail mode only for blocks or patterns that will be used in the proposed page, pattern, or conversion plan.
Step 3A.6. Avoid pattern content unless needed
Never request pattern content unless it is required for direct insertion, pattern comparison, or validation. For ordinary planning, pattern metadata and structure are enough.
Step 3A.7. Record discovery decisions
For each selected block or pattern, record:
- why it was selected
- whether it is core, theme, plugin, or custom
- whether it is being used directly, as a pattern candidate, or as a fallback
- whether more detail was requested
Phase 4: Pattern determination
How to determine whether something should become a pattern
Ask these questions:
- Does this section recur across multiple pages or likely will soon?
- Is the layout the reusable asset rather than the exact content?
- Would future editors benefit from inserting the section from a library?
- Is the structure more important than one-off customization?
If yes to most of these, create a pattern candidate.
Pattern categories to standardize
Recommended categories:
- hero
- split sections
- card grids
- quote/proof sections
- CTA bands
- content intro sections
- FAQ wrappers
- media-text sections
Pattern naming convention
Use functional names:
site/homepage-herosite/section-split-proofsite/grid-cards-3site/cta-band-dark
Avoid names based only on color or mood.
Phase 5: Styling layer order
Layer 1: Component/builder settings
Always try here first.
Use builder settings for:
- align (
wide,full, etc.) - content width
- wide width
- layout type
- column widths
- block gap
- margin/padding where available
- stacking behavior on mobile
- image sizing/cropping where supported
- typography and color controls where supported and governed
Rule
If the editor exposes the setting cleanly, use the setting before inventing CSS.
Special rule for containers
Whenever available, container size must be set on the component in the builder. Do not default to CSS for width if the block already exposes width/layout controls.
Layer 2: theme.json
Use theme.json for shared, system-level decisions.
Put these here:
- color palette
- gradients
- typography roles
- spacing scale
- layout sizes
- shadow tokens
- radius tokens
- motion tokens
- global block defaults
- block-level default styling where appropriate
Use theme.json when the decision should apply across many pages or blocks.
Do not use theme.json for:
- complex keyframes
- section-specific choreography
- narrow one-off layout hacks
- highly component-specific behavior that belongs to a custom block asset
Layer 3: Block-local styling
Use block-local styling when a custom block owns its own presentation.
Examples:
style.csseditor.cssview.css- block-scoped assets
Best for:
- dynamic blocks
- custom blocks
- block-specific frontend/editor parity
- block-specific hover/reveal/preview behavior
Layer 4: Theme CSS
Use theme CSS for:
- section-specific layout refinement
- pattern-related visual parity
- classes used across multiple sections but not appropriate for theme.json
- migration namespaces such as
hp-* - advanced interactions and animation rules
Recommended split:
- layout CSS
- style/surface CSS
- motion CSS
Layer 5: Inline styles
Use only when absolutely necessary for per-instance or computed behavior. Avoid using inline styles as a substitute for design tokens or reusable classes.
Phase 6: Motion and interaction rules
Motion token placement
Put motion primitives in theme.json:
- durations
- easings
- distances
- entry opacity
- scale primitives
Animation rule placement
Put actual animation behavior in CSS:
- keyframes
- reveal classes
- delay utilities
- hover choreography
prefers-reduced-motionhandling
Block-specific motion
If motion belongs only to one dynamic/custom block, place it in the block’s viewStyle / block-local CSS.
Motion governance rule
Motion is optional polish, not structural dependency. The page must work with motion disabled.
Phase 7: Import and conversion workflow
A. Building from scratch
- Define page goal.
- Build section hierarchy.
- Decide pattern candidates.
- Assemble sections using core blocks first.
- Set builder/container settings.
- Apply shared tokens via
theme.json. - Add parity/refinement CSS only where needed.
- Preview responsive states.
- Save reusable sections as patterns if confirmed.
B. Importing a page from the internet
- Capture the source page’s structure, not just its styling.
- Break it into sections.
- Identify what is semantic vs decorative.
- Rebuild the structure in Gutenberg using native blocks and patterns.
- Use builder settings for layout widths and columns.
- Map global styles to
theme.jsontokens. - Recreate only the necessary CSS refinements.
- Do not paste entire webpages as raw HTML unless quarantining temporarily.
C. Converting custom HTML to Gutenberg
- Inventory the HTML sections.
- Normalize malformed or nested invalid markup.
- Classify each section:
- core blocks
- pattern
- dynamic block
- temporary HTML fallback
- Convert section by section, not tag by tag.
- Replace shortcode-backed surfaces with dynamic block targets.
- Preserve class namespace temporarily if needed for migration parity.
- Reduce raw HTML over time until only Gutenberg-native structures remain.
D. Rebuilding a live page safely
- Create a draft sandbox page first.
- Rebuild only the first section or first deliverable slice.
- Compare live vs draft.
- Fix structural mismatches first.
- Then fix builder settings.
- Then fix style parity.
- Then handle animation parity.
- Roll section-by-section into the final live page only after validation.
E. GPT-assisted Gutenberg conversion with governed context fallback
Use this workflow whenever a Custom GPT is assisting with Gutenberg conversion, proposal generation, or homepage rebuild planning.
- Resolve the target page/post ID.
- Call
content.block_conversion_contextwithinclude_block_catalog=false. - If
content.block_conversion_contextreturns403, do not stop. - Call
content.block_read_contextfor safe read-only analysis. - Clearly record that governed conversion context was unavailable if the fallback path was used.
- Use
blocks.catalogin paginated mode:
- start with
mode=categories - continue with
mode=listby category/source - use
mode=detailonly for selected blocks or patterns
- Generate proposed serialized Gutenberg markup section by section.
- Validate the final serialized markup with
content.block_validate. - If validation fails, fix the block markup before any proposal or update action.
- Do not call
page.propose_updateunless the user has approved the proposal and the action has the required write/edit permission. - If governed context was unavailable but validation succeeded, state that clearly in the handoff:
Proposed Gutenberg markup validated successfully. Governed conversion context was unavailable due to permissions, so this proposal was prepared from safe read-only page context plus catalog drilldown.
Permission interpretation rule
A 403 from governed conversion context is not automatically a page-analysis failure. It means the action lacks the required edit-level permission for that specific target. Use the read-only fallback for analysis, but do not proceed to proposal/update actions without approval and write capability.
Phase 8: Draft-first iteration protocol
Use a draft page when:
- the page is structurally important
- there is meaningful styling risk
- the page is the homepage or other critical page
- the conversion is partial or phased
Recommended iteration order
- Structure
- Builder settings
- Media preview / content parity
- Shared token alignment
- Styling parity
- Motion parity
- Reusable pattern extraction
- Live rollout
Why this matters
This prevents time being wasted on styling the wrong structure.
Phase 9: Editor parity rules
Goal
The Gutenberg editor should be as representative as practical, but not at the cost of bad architecture.
Acceptable editor preview states
- strong structural preview
- real media preview
- token-driven typography/color preview
- dynamic block preview placeholders or real previews
Ideal editor preview states
- real custom block preview
- block-specific editor styles
- layout parity
- major visual cues preserved
When editor parity requires more than content tools
If true frontend parity requires:
- block-specific
editorStyle - block-specific
viewStyle - dynamic runtime preview
- arbitrary theme CSS asset changes
then this is a code-layer/tooling need, not a page-content need.
Phase 10: Quality control checklist
Structure QA
- Does the page hierarchy make sense?
- Is each section clearly defined?
- Are headings semantically correct?
- Are lists, quotes, and media represented with the right blocks?
Builder QA
- Are widths set in component settings where available?
- Are columns explicitly sized where needed?
- Is mobile stacking correct?
- Are spacing controls being used instead of unnecessary CSS?
Pattern QA
- Should this section be reusable?
- Is the pattern named functionally?
- Can it be inserted again cleanly?
Styling QA
- Are shared decisions in
theme.json? - Is CSS only doing what the builder/theme cannot do?
- Are there too many one-off classes?
Motion QA
- Does the page work without motion?
- Is reduced motion respected?
- Is motion tokenized and governed?
Editor QA
- Does the page reopen without invalid block warnings?
- Are dynamic/media previews acceptable?
- Is the editor usable by future authors?
Responsive QA
- mobile
- tablet
- desktop
- wide desktop
Governance QA
- Is there a rollback path?
- Is the page draft-tested before production?
- Were risky changes isolated first?
- Was governed conversion context available?
- If governed conversion context returned
403, wascontent.block_read_contextused instead? - Was the permission limitation disclosed in the final handoff?
- Was
page.propose_updatewithheld until explicit user approval and write/edit capability were confirmed?
GPT Action QA
- Was the block catalog requested in paginated mode instead of as a full catalog?
- Was
blocks.catalog mode=categoriescalled before list/detail drilldown? - Were list calls filtered by category/source with
page_size <= 20? - Was
next_cursorused only until enough candidates were found? - Was detail mode limited to selected blocks or patterns?
- Was pattern content omitted unless required for direct insertion or comparison?
- Was final serialized block markup validated with
content.block_validate?
Phase 11: Standard rules to carry into future chat sessions
Rule 1
Always identify the target page and whether work is draft-only or production-facing.
Rule 2
Always decompose the page into section hierarchy before writing markup.
Rule 3
Always classify each section as core blocks, pattern, dynamic block, or temporary HTML fallback.
Rule 4
Always set container size in the builder/component settings whenever the control exists.
Rule 5
Always prefer:
- builder settings first
theme.jsonsecond- block-local or theme CSS third
- inline styles last
Rule 6
Always use patterns for repeatable sections.
Rule 7
Always target dynamic custom blocks for shortcode-backed runtime UI.
Rule 8
Always fix structural parity before style parity.
Rule 9
Always fix style parity before animation parity.
Rule 10
Always preserve accessibility, responsive behavior, and editor reusability.
Rule 11
Always discover Gutenberg blocks through paginated catalog drilldown: categories first, filtered list second, selected detail third.
Rule 12
Never request full block or pattern catalogs in one Custom GPT action call.
Rule 13
Always validate final serialized block markup with content.block_validate before proposal or update.
Rule 14
Always try governed conversion context first, but use safe read-only context when governed context returns 403.
Rule 15
Always disclose when governed conversion context was unavailable and the plan was created from read-only context.
Rule 16
Never call page.propose_update until the user approves and write/edit permission is available.
Default prompt template for future chat sessions
Use this as a starting instruction in future sessions:
Follow a Gutenberg-first workflow. First identify the target page and whether changes should happen in a draft or production. Resolve the page/post ID. Try governed conversion context with
include_block_catalog=false; if it returns403, use safe read-only context and disclose that governed context was unavailable. Decompose the page into section hierarchy, classify each section as core block, pattern, custom static block, dynamic custom block, or temporary raw HTML fallback. Discover blocks through paginated catalog drilldown:blocks.catalog mode=categories, thenmode=listby category/source withpage_size <= 20, thenmode=detailonly for selected blocks or patterns. Do not request full block catalogs or pattern content unless needed for direct insertion or comparison. Use builder/component settings first for container widths, alignment, columns, spacing, and layout. Usetheme.jsonsecond for shared tokens and defaults. Use CSS only where builder settings andtheme.jsoncannot express the needed behavior. Prefer patterns for repeatable sections and dynamic custom blocks for shortcode-backed or runtime-driven UI. Fix structure first, then builder settings, then style parity, then motion parity. Validate final serialized block markup withcontent.block_validatebefore proposing or applying updates. Do not callpage.propose_updateunless the user approves and write/edit permission is available. Preserve accessibility, responsive behavior, and editor usability throughout.
Final doctrine
The target is not “make Gutenberg reproduce raw HTML.” The target is:
- represent the page as a clean block hierarchy
- extract repeatable sections into patterns
- replace runtime shortcodes with dynamic blocks
- move shared design decisions into
theme.json - keep component sizing in builder settings whenever possible
- use CSS as a refinement layer, not the foundation
- discover blocks through paginated, category-first drilldown
- separate read-only analysis from governed proposal/update actions
- validate serialized block markup before any proposal or update
- make the page scalable for future authors, future pages, and future iterations