Skip to content

1101 content planner create the content suggestions blocks#23117

Merged
vraja-pro merged 20 commits intofeature/content-plannerfrom
1101-content-planner-create-the-content-suggestions-blocks
Apr 13, 2026
Merged

1101 content planner create the content suggestions blocks#23117
vraja-pro merged 20 commits intofeature/content-plannerfrom
1101-content-planner-create-the-content-suggestions-blocks

Conversation

@vraja-pro
Copy link
Copy Markdown
Contributor

@vraja-pro vraja-pro commented Mar 30, 2026

Context

  • This PR is the ground work for wiring the backend.
  • It includes the redux slices for getting suggestions and content outline. includes the error savng for future error handling.
  • It includes the functionality to apply the content outline.
  • Currently it is used in the content suggestion just for testing purposes.

Summary

This PR can be summarized in the following changelog entry:

  • Adds the content suggestions block and the functionality to fetch suggestions and apply them to post content.

Relevant technical choices:

Test instructions

Test instructions for the acceptance test before the PR gets merged

Scenario 1: Empty post (no confirmation modal)

  1. Create a new post (leave the content area empty).
  2. Click on the Get content suggestions button in the Yoast sidebar.
  3. Wait for suggestions to load and click on one of the suggestions.
  4. Click the Add outline to post button.
  5. Check the outline is inserted directly into the editor without showing a confirmation modal.
  6. Check the post content includes the 6 headings, paragraphs and content notes, and 1 FAQ block with content notes under it.
  7. Check the post title, SEO title, meta description, focus keyphrase and category are all set from the outline.

Scenario 2: Post with existing content (confirmation modal)

  1. Open a post that already has some content (or type some text in a new post first).
  2. Click on the Get content suggestions button in the Yoast sidebar.
  3. Wait for suggestions to load and click on one of the suggestions.
  4. Click the Add outline to post button.
  5. Check the "Replace existing content with this outline?" confirmation modal is shown.
  6. Click Cancel and verify you return to the content outline view.
  7. Click Add outline to post again.
  8. Click Replace content in the confirmation modal.
  9. Check the existing content is replaced with the outline (6 headings, paragraphs, content notes, and 1 FAQ block with content notes).
  10. Check the post title, SEO title, meta description, focus keyphrase and category are all set from the outline.
  11. Click the undo button in the Gutenberg editor and verify the content is reverted. (After a few times, it's a known limitation addressed by this PR).

Scenario 3: Content suggestion blocks

  1. After applying an outline (from either scenario above), check the content note blocks match the design.
  2. Check you can remove a content note block like any other block.
  3. Check you can move up and down the content note block like any other block.
  4. Check you can convert a content note block to a list block.

Relevant test scenarios

  • Changes should be tested with the browser console open
  • Changes should be tested on different posts/pages/taxonomies/custom post types/custom taxonomies
  • Changes should be tested on different editors (Default Block/Gutenberg/Classic/Elementor/other)
  • Changes should be tested on different browsers
  • Changes should be tested on multisite

Test instructions for QA when the code is in the RC

  • QA should use the same steps as above.

QA can test this PR by following these steps:

Impact check

This PR affects the following parts of the plugin, which may require extra testing:

Other environments

  • This PR also affects Shopify. I have added a changelog entry starting with [shopify-seo], added test instructions for Shopify and attached the Shopify label to this PR.
  • This PR also affects Yoast SEO for Google Docs. I have added a changelog entry starting with [yoast-doc-extension], added test instructions for Yoast SEO for Google Docs and attached the Google Docs Add-on label to this PR.

Documentation

  • I have written documentation for this change. For example, comments in the Relevant technical choices, comments in the code, documentation on Confluence / shared Google Drive / Yoast developer portal, or other.

Quality assurance

  • I have tested this code to the best of my abilities.
  • During testing, I had activated all plugins that Yoast SEO provides integrations for.
  • I have added unit tests to verify the code works as intended.
  • If any part of the code is behind a feature flag, my test instructions also cover cases where the feature flag is switched off.
  • I have written this PR in accordance with my team's definition of done.
  • I have checked that the base branch is correctly set.
  • I have run grunt build:images and commited the results, if my PR introduces new images or SVGs.

Innovation

  • No innovation project is applicable for this PR.
  • This PR falls under an innovation project. I have attached the innovation label.
  • I have added my hours to the WBSO document.

Fixes https://github.com/Yoast/reserved-tasks/issues/1101

@vraja-pro vraja-pro added this to the feature/content-planner milestone Mar 30, 2026
@vraja-pro vraja-pro added the changelog: non-user-facing Needs to be included in the 'Non-userfacing' category in the changelog label Mar 30, 2026
@coveralls
Copy link
Copy Markdown

coveralls commented Mar 30, 2026

Coverage Report for CI Build 2

Coverage increased (+0.6%) to 53.397%

Details

  • Coverage increased (+0.6%) from the base build.
  • Patch coverage: 68 uncovered changes across 7 files (56 of 124 lines covered, 45.16%).
  • No coverage regressions found.

Uncovered Changes

File Changed Covered %
packages/js/src/ai-content-planner/initialize.js 20 4 20.0%
packages/js/src/ai-content-planner/store/content-outline.js 27 12 44.44%
packages/js/src/ai-content-planner/store/content-suggestions.js 26 11 42.31%
packages/js/src/ai-content-planner/helpers/build-blocks-from-outline.js 9 0 0.0%
packages/js/src/ai-content-planner/helpers/apply-post-meta-from-outline.js 8 0 0.0%
packages/js/src/ai-content-planner/components/content-suggestion-block.js 4 1 25.0%
packages/js/src/ai-content-planner/components/feature-modal.js 26 24 92.31%

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 65549
Covered Lines: 34819
Line Coverage: 53.12%
Relevant Branches: 16839
Covered Branches: 9174
Branch Coverage: 54.48%
Branches in Coverage %: Yes
Coverage Strength: 45891.06 hits per line

💛 - Coveralls

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR lays the groundwork for the AI Content Planner “content suggestions” flow by adding new store slices for suggestions/outline, introducing a new “Content Suggestion” block, and wiring up “apply outline” behavior from the suggestions modal into the editor.

Changes:

  • Added Redux store slices (state/selectors/actions/controls) for content suggestions and content outline, and registered them in the Content Planner store.
  • Registered a new hidden-in-inserter Gutenberg block (yoast-seo/content-suggestion) and helper utilities to build editor blocks + apply post/Yoast meta from an outline.
  • Wired suggestion selection in the modal to fetch an outline and apply it to the editor, plus updated unit test mocks.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
packages/js/tests/ai-content-planner/components/feature-modal.test.js Extends mocks to cover new dispatch/select usage when applying outlines.
packages/js/src/ai-content-planner/store/index.js Registers new suggestions/outline slices (actions/selectors/controls/reducers/initialState).
packages/js/src/ai-content-planner/store/content-suggestions.js New slice + generator action/control for fetching suggestions.
packages/js/src/ai-content-planner/store/content-outline.js New slice + generator action/control for fetching/holding an outline (currently stubbed).
packages/js/src/ai-content-planner/initialize.js Registers the new yoast-seo/content-suggestion block and transform.
packages/js/src/ai-content-planner/helpers/build-blocks-from-outline.js Creates Gutenberg blocks from an outline (heading/paragraph/notes/FAQ).
packages/js/src/ai-content-planner/helpers/apply-post-meta-from-outline.js Applies outline meta to core editor + Yoast editor stores (title/meta/keyphrase/category).
packages/js/src/ai-content-planner/components/feature-modal.js Wires “select suggestion → fetch outline → apply meta + blocks” into the modal.
packages/js/src/ai-content-planner/components/content-suggestions-modal.js Adds onSuggestionSelect callback support for suggestion buttons.
packages/js/src/ai-content-planner/components/content-suggestion-block.js Adds UI component used as the new content-notes block’s edit view.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +26 to +31
blocks.push( createBlock( "yoast-seo/content-suggestion", { suggestions: outline[ contentNotes ] } ) );
blocks.push( createBlock( "core/paragraph" ) );
}

blocks.push( createBlock( "yoast-seo/content-suggestion", { suggestions: outline.faqContentNotes } ) );
blocks.push( createBlock( "yoast/faq-block" ) );
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The block insertion order here doesn’t match the function docblock (and likely the intended UX of having the notes under their corresponding paragraph/FAQ). Currently each section inserts heading → content-suggestion → paragraph, and FAQ inserts content-suggestion → FAQ block. Consider swapping the order to heading → paragraph → content-suggestion, and FAQ block → FAQ content-suggestion, so the notes appear beneath the content they relate to.

Suggested change
blocks.push( createBlock( "yoast-seo/content-suggestion", { suggestions: outline[ contentNotes ] } ) );
blocks.push( createBlock( "core/paragraph" ) );
}
blocks.push( createBlock( "yoast-seo/content-suggestion", { suggestions: outline.faqContentNotes } ) );
blocks.push( createBlock( "yoast/faq-block" ) );
blocks.push( createBlock( "core/paragraph" ) );
blocks.push( createBlock( "yoast-seo/content-suggestion", { suggestions: outline[ contentNotes ] } ) );
}
blocks.push( createBlock( "yoast/faq-block" ) );
blocks.push( createBlock( "yoast-seo/content-suggestion", { suggestions: outline.faqContentNotes } ) );

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

heading → content-suggestion → paragraph and content-suggestion → FAQ block is correct ✅ as per the design

Comment thread packages/js/src/ai-content-planner/components/feature-modal.js Outdated
Comment on lines +41 to +46
/**
* @param {string} endpoint The endpoint to fetch content suggestions from.
* @returns {Object} Success or error action object.
*/
export function* getContentSuggestions( { endpoint } ) {
yield{ type: `${ FETCH_CONTENT_SUGGESTIONS_ACTION_NAME }/${ ASYNC_ACTION_NAMES.request }` };
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JSDoc doesn’t match the actual function signature: getContentSuggestions takes a single object argument ({ endpoint }), not a string endpoint. Updating the JSDoc will prevent confusion for callers and tooling.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still work in progress, it will be updated once we have the real endpoint.

Comment thread packages/js/src/ai-content-planner/store/content-outline.js
Comment thread packages/js/src/ai-content-planner/store/content-outline.js
Comment thread packages/js/src/ai-content-planner/initialize.js Outdated
key={ suggestion.title }
{ ...suggestion }
onClick={ noop }
onClick={ onSuggestionSelect }
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SuggestionButton uses onClick as a normal button handler, so passing onSuggestionSelect directly means it will receive the click event (not the suggestion object). That will break handleApplyOutline (it expects suggestion fields). Wrap the handler to pass the suggestion (e.g., onClick={ () => onSuggestionSelect( suggestion ) }) or change SuggestionButton to call onClick with the suggestion data.

Suggested change
onClick={ onSuggestionSelect }
onClick={ () => onSuggestionSelect( suggestion ) }

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still work in progress.

@JorPV
Copy link
Copy Markdown
Contributor

JorPV commented Mar 31, 2026

Code Review — PR #23117

Overview

This PR adds the groundwork for the content suggestions flow: Redux store slices for suggestions and outline, a new yoast-seo/content-suggestion Gutenberg block, and the wiring to apply an outline to the editor. Solid foundation — I have some concerns below.


Architecture & Data Flow

  1. select() vs useSelect() in handleApplyOutline (feature-modal.js:32-36) — The handler uses the non-reactive select( STORE_NAME ).selectContentOutline() immediately after await getContentOutline(). This works because it's in an imperative callback, but it creates a tight coupling to the synchronous dispatch completing before select() reads. If the generator action's control ever becomes truly async (right now it's a stubbed immediate return), there could be a race. Consider having getContentOutline return the outline directly rather than reading it back from the store.

  2. Missing error handling in handleApplyOutline — Copilot flagged the missing await on applyPostMetaFromOutline, which is correct. Beyond that, there's no user-facing error state if the outline fetch or apply fails. The modal just stays open or closes silently. Consider at minimum a try/catch with a console.error, and eventually a user-facing error message.

  3. onSuggestionSelect receives a click event, not the suggestion (content-suggestions-modal.js:220) — Copilot caught this too. SuggestionButton spreads the suggestion props but its onClick fires with the browser event. The handler needs to be () => onSuggestionSelect( suggestion ) or SuggestionButton needs to call onClick with its suggestion data.

Store Slices

  1. Hardcoded mock data in contentOutlineControls (content-outline.js:93-140) — The stubbed control returns a hardcoded sourdough bread outline. This is fine for development, but the commented-out real implementation above it and the // TODO make it clear. Just flag: the apiFetch import has an eslint-disable for no-unused-vars because of this — remove both when swapping to the real endpoint.

  2. Generator action pattern — Both getContentOutline and getContentSuggestions use the same generator pattern with yield/return. The return at the end of the try block dispatches the success action, but the generator won't dispatch it — return just resolves the generator, it doesn't dispatch. In WordPress data store generators, you need to yield the success action, not return it:

    // Current (may not dispatch):
    return { type: `${NAME}/${ASYNC_ACTION_NAMES.success}`, payload };
    
    // Should be:
    yield { type: `${NAME}/${ASYNC_ACTION_NAMES.success}`, payload };

    Same issue in the catch block. Please verify this works correctly with the WordPress data store's generator runtime.

Block Registration

  1. Unused title attribute (initialize.js:109) — The block defines a title attribute and uses it in the transform, but buildBlocksFromOutline never sets it. The transform will create an empty paragraph from title. Either remove title from the block attributes/transform, or populate it in buildBlocksFromOutline.

  2. Block order in buildBlocksFromOutline (build-blocks-from-outline.js:25-27) — Current order is heading → content-suggestion → paragraph. The test instructions say content notes should appear under headings/paragraphs. Verify this matches the intended design — should it be heading → paragraph → content-suggestion instead?

Content Suggestion Block Component

  1. List key uses index (content-suggestion-block.js:30) — key={\${index}-${note}`}is fine since notes are static and won't be reordered, but ifnote` strings could be duplicated, consider using just the index.

  2. yst-mr-1 in RTL (content-suggestion-block.js:17) — The EyeIcon uses yst-mr-1 which won't flip in RTL layouts. Consider using yst-me-1 (margin-end) for RTL support, consistent with how other components use logical properties (e.g., yst-ms-4 elsewhere).

Tests

  1. Heavy mocking of @wordpress/data (feature-modal.test.js) — The test mocks useDispatch, select, dispatch, resolveSelect, combineReducers, createReduxStore, and register. This is fragile — any internal change to how the store is consumed will break tests. Consider using @wordpress/data's test utilities or a lighter approach. That said, this may be necessary given the test setup.

  2. No unit tests for new helpers or store slicesbuildBlocksFromOutline, applyPostMetaFromOutline, content-outline.js, and content-suggestions.js are all untested. These are pure-ish functions that would benefit from unit tests, especially buildBlocksFromOutline which has specific ordering requirements.

CI Status

All checks passing ✅

Summary

Aspect Status
Store architecture ✅ Clean slice pattern, follows existing conventions
Generator actions ⚠️ return vs yield for dispatching success/error — verify this works
onClick handler ❌ Passes event instead of suggestion data (Copilot also flagged)
Error handling ⚠️ No error handling in apply flow
Block registration ✅ Good — hidden from inserter, has transform
Block order ⚠️ Verify heading → suggestion → paragraph matches design intent
RTL support ⚠️ yst-mr-1 should be yst-me-1
Tests ⚠️ No tests for new helpers/store slices
CI ✅ All green

@vraja-pro
Copy link
Copy Markdown
Contributor Author

vraja-pro commented Apr 1, 2026

I think most of the Copilot comments can be ignored since it's still work in progress. (2,3,4,10,11)
One think that I'm re thinking is that the headings should probably be saved as array rather than an object, so that when user reorders the array it would be easy to save it, and also loop over it when appling.

JorPV added 2 commits April 1, 2026 11:18
… and content notes. Update block building logic to accommodate new structure.
…ng in FeatureModal, and yield actions in content outline and suggestions store functions
@JorPV
Copy link
Copy Markdown
Contributor

JorPV commented Apr 1, 2026

TLDR of my changes:

  1. Headings as array — Refactored the flat heading1/paragraph1ContentNotes object into a sections array of { heading, contentNotes } in the store and mock data as per @vraja-pro suggestion. Simplified buildBlocksFromOutline to iterate outline.sections directly, removing the PARAGRAPH_KEYS lookup table.
  2. await applyPostMetaFromOutline — Added the missing await in feature-modal.js so meta is fully applied before blocks are reset and the modal closes.
  3. JSDoc fix — Updated content-suggestion-block.js JSDoc to document the props object shape (props.contentNotes) instead of a bare parameter.
  4. return → yield in generators — Changed both content-outline.js and content-suggestions.js to yield success/error actions so the WP data store runtime actually dispatches them to the reducers (currently masked because the mock control returns immediately and the code reads from the store right after with select() but it would become a real problem once the real async apiFetch endpoint is wired up.
  5. RTL fix — Changed yst-mr-1 to yst-me-1 on the EyeIcon in content-suggestion-block.js for proper RTL margin flipping.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 3, 2026

A merge conflict has been detected for the proposed code changes in this PR. Please resolve the conflict by either rebasing the PR or merging in changes from the base branch.

Resolve conflicts: keep base branch's UI flow (SuggestionsPanel,
ContentOutlineModal, skipTransitions) while preserving feature branch's
store integration, content-suggestion block, and outline application logic.
Remove deleted banner store slice references.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 9, 2026

A merge conflict has been detected for the proposed code changes in this PR. Please resolve the conflict by either rebasing the PR or merging in changes from the base branch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@leonidasmi leonidasmi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CR: ✅ for the commits added after @JorPV original CR.

Acceptance: 🏗️

Sorry if the below points were intentional omissions from this PR for the sake of velocity! I even ignored some issues that looked like they were supposed to be fixed in later PRs, but even so, I thought it might be useful to flag some of them here, so we can have them documented to fix them later on, I hope that's alright.

Feel free to create separate tasks for the below instead of fixing them here, for the sake of velocity (apologies if tasks are already created for those, I couldn't find any from a quick glance):

  • Clicking the Add outline to post button inserts different hardcoded data in the post title, SEO title, meta description, focus keyphrase and category than the hardcoded data that exist in the content outline view
    • Maybe this is intentional, but I would assume that it would be responsibility of this PR to do this specific wiring. If not, ignore
  • Clicking the Add outline to post button in a post with existing content and then clicking cancel on the "Replace existing content with this outline?" confirmation modal indeed returns you to the content outline view 👍 BUT, if you then click to go back to the Content Suggestion modal, all modals close
  • A greater question about the behavior of the content note blocks that are being added:
    • Once they are added, should they persist in the post content even after the post is saved? What about when the post is published?
    • I'm thinking that we need to doublecheck with product on what happens with those blocks, because I'm under the impression they must be temporary and be cleaned out at some point (I guess upon publishing the post)
  • Clicking the Add outline to post button while category is toggled off, has no effect, the category is still being applied to the post
  • Clicking the Add outline to post button has a weird UX flow:
    • You click the button but the modal stays open for some seconds
    • While the modal is open, in the background the outline is getting added in the post content
    • After a while the modal closes
    • I find this as something that needs to be definitely improved, maybe with a loading state while the outline is getting added in the post?
    • The same UX thing is true when you click to replace the existing content, in the "Replace existing content with this outline?" confirmation
  • When the content outline view is still loading data and skeletons loaders are still shown, clicking the Add outline to post button should be disabled, as per the designs.
  • About the "Click the undo button in the Gutenberg editor and verify the content is reverted" test instruction, I'm not sure what's the expected behavior, but for me I have to click multiple times the undo button until I see my original content fully reverted. I think that each undo button click reverts a single addition of the content note block - might be ok, but wanted to flag that too
  • Not sure if intended (the designs have this in one case, but dont have it in other cases) but I see that for between every section (h2+content note block) we add, a blank paragraph is also added:
image
  • Similarly, I'm not sure why we are always adding a blank paragraph before the FAQ block as well, I dont see the same behavior in the designs. In fact there are a lot of things that I am not sure they are as intended, in the way we're dealing with FAQ blocks in buildBlocksFromOutline().
    • We currently hardcode a yoast/faq-block to always be created, regardless of whether it exists in the suggested outline
    • We use outline.faqContentNotes in the paragraph above the FAQ instead of using it in the FAQ block itself
    • We might need some logic to not do anything with yoast/faq-blocks, if this has been unregistered from the site (although I do see a graceful Your site doesn’t include support for the "yoast/faq-block" block. You can leave it as-is or remove it. block warning if that's the case)
  • Not sure what we expect when we convert the content note to a paragraph, but I see that the listed suggestions:
image

become separate paragraphs instead of listed items, which is what I would expect:
image

If we think it's ok to merge with this issues documented here and dealt with later on, by all means.

@JorPV
Copy link
Copy Markdown
Contributor

JorPV commented Apr 10, 2026

Thank you @leonidasmi for pointing out all the issues. Below is an update on each of your points:

  • Clicking the Add outline to post button inserts different hardcoded data in the post title, SEO title, meta description, focus keyphrase and category than the hardcoded data that exist in the content outline view
  • Clicking the Add outline to post button while category is toggled off, has no effect, the category is still being applied to the post

Are tackled with this commit . Now the data from the Content Outline is wired with the Outline blocks in the editor. What remains is to wire it with the real API for which I added a Temorary comment.

  • Clicking the Add outline to post button in a post with existing content and then clicking cancel on the "Replace existing content with this outline?" confirmation modal indeed returns you to the content outline view 👍 BUT, if you then click to go back to the Content Suggestion modal, all modals close. > * When the content outline view is still loading data and skeletons loaders are still shown, clicking the Add outline to post button should be disabled, as per the designs.

I will address those in the other discrepancies issues as they kind of fall under the scope Fix loading state discrepancies in Content Planner modals

Clicking the Add outline to post button has a weird UX flow:
- You click the button but the modal stays open for some seconds
- While the modal is open, in the background the outline is getting added in the post content
- After a while the modal closes
- I find this as something that needs to be definitely improved, maybe with a loading state while the outline is getting added in the post?
- The same UX thing is true when you click to replace the existing content, in the "Replace existing content with this outline?" confirmation

I've created this issue to tackle that point ☝️

The remaining points need some Product/UX feedback before we can address them:

  1. Once the suggestions blocks are added, should they persist in the post content even after the post is saved? What about when the post is published?

  2. About the "Click the undo button in the Gutenberg editor and verify the content is reverted" should the undo button click revert a single addition of the content note block or the whole post additions?

  3. Not sure if intended (the designs have this in one case, but dont have it in other cases) but I see that for between every section (h2+content note block) we add, a blank paragraph is also added. (Confirm with UX)

  4. We are always adding a blank paragraph before the FAQ block as well. (Confirm with UX)

  5. When we convert the content note to a paragraph, the listed suggestions become separate paragraphs (instead of listed items).

@manuelaugustin
Copy link
Copy Markdown
Contributor

Once the suggestions blocks are added, should they persist in the post content even after the post is saved? What about when the post is published?

They should ideally persist if the post is saved, and I'd argue also when the post is published. However they should only be visible in the editor, but never be output on the front-end. Is that possible?

About the "Click the undo button in the Gutenberg editor and verify the content is reverted" should the undo button click revert a single addition of the content note block or the whole post additions?

Ideally the whole addition of the post, but I'm not sure that's possible (I think we had a similar issue with AI Optimize). If the only option is to revert single additions, that's also fine.

Not sure if intended (the designs have this in one case, but dont have it in other cases) but I see that for between every section (h2+content note block) we add, a blank paragraph is also added. (Confirm with UX)

I think those are intended so that users can easily add content, right @ux-tom ?

We are always adding a blank paragraph before the FAQ block as well. (Confirm with UX)

I think for that we don't need a blank paragraph (since users aren't expected to add anything) but also checking with @ux-tom .

When we convert the content note to a paragraph, the listed suggestions become separate paragraphs (instead of listed items).

List items would make more sense, but if that's difficult to achieve we can also make it a nice-to-have.

@ux-tom
Copy link
Copy Markdown

ux-tom commented Apr 13, 2026

  1. Agreed with Manuel.
  2. Agreed with Manuel.
  3. The design consistently does this after every section (H2+content note). The reason is to easily add content for users and to create spacing, in otherwise, a wall of text.
  4. We aren't adding a blank paragraph before the FAQ section; we're adding it after every section (H2+content note). Effectively, the same result but different logic. This would look like: H2 > Content note > Blank paragraph > Break > FAQ Block.
  5. Agreed with Manuel

@JorPV
Copy link
Copy Markdown
Contributor

JorPV commented Apr 13, 2026

They should ideally persist if the post is saved, and I'd argue also when the post is published. However they should only be visible in the editor, but never be output on the front-end. Is that possible?

Yes it is, in fact that's already the current behavior. And the user can delete them one by one same as with other Gutenberg blocks.

Ideally the whole addition of the post, but I'm not sure that's possible (I think we had a similar issue with AI Optimize). If the only option is to revert single additions, that's also fine.

Indeed, that's a tricky one. We dispatch different entries for the post but WordPress doesn't seem to have an API to group multiple dispatches into a single undo step. I'm creating a new issue #1152 to address it in a later phase.

The design consistently does this after every section (H2+content note). The reason is to easily add content for users and to create spacing, in otherwise, a wall of text.

Alright, then the current implementation already adds the paragraph after each H2 + Content note.

We aren't adding a blank paragraph before the FAQ section; we're adding it after every section (H2+content note). Effectively, the same result but different logic. This would look like: H2 > Content note > Blank paragraph > Break > FAQ Block.

Thanks for the clarification! That's also the current behavior.

When we convert the content note to a paragraph, the listed suggestions become separate paragraphs (instead of listed items).
List items would make more sense, but if that's difficult to achieve we can also make it a nice-to-have.

I'm applying that change in my last commit.

JorPV and others added 5 commits April 13, 2026 13:26
…dren and update tests to validate the new transformation behavior.
This fixes a problem where stylesheet would be missing after page load.
@vraja-pro
Copy link
Copy Markdown
Contributor Author

CR and AC ✅

  • No need for registering the block in PHP because it's content is only saved to the editor.

@vraja-pro vraja-pro merged commit 804c865 into feature/content-planner Apr 13, 2026
20 checks passed
@vraja-pro vraja-pro deleted the 1101-content-planner-create-the-content-suggestions-blocks branch April 13, 2026 12:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog: non-user-facing Needs to be included in the 'Non-userfacing' category in the changelog

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants