Place blocks on a page (declarative)
place_blocksArrange blocks on a page layout by merging or replacing entries, setting position, height, and visibility, with overflow detection and dry-run preview.
Instructions
Declaratively manage which blocks a page (layout) shows, in ONE atomic read-modify-write. mode=merge (default): upsert the blocks entries (re-placing updates position) and remove any ids in remove; other blocks on the page are untouched. mode=replace: the page becomes EXACTLY the blocks list (requires confirm:true; customized grid.layouts, hidden flags and geometry of surviving blocks are preserved). Each entry: { block_id, position?, height?, hidden? }. An entry with NEITHER position NOR height keeps an already-placed block's current geometry (safe for hidden-only toggles); a NEW block with no position auto-stacks full-width below existing content in array order; pass position (or height) to re-place explicitly. Blocks are placed, not created (create_block first) and never deleted (delete_resource does that). dry_run:true previews the final grid without writing. GRID BUDGET: every box is a % of the page's grid.layouts.{bp}.height (default 100), and blocks stack by accumulating top — so Σ(heights) must stay <= the grid height or the page CLIPS silently. The auto-place default is 50%, so THREE defaulted blocks already overflow: pass an explicit height for each. Budget guide at 100: filter bar 8-10, KPI band 18-22, chart card 30-35, table 35-40. Pair blocks side by side (same top, width 50 each) to buy vertical room before making the page taller, and aim to land everything above the fold at lg (the portal's header/footer/sidebars already take their share). If it truly won't fit, raise the grid height in increments of 25 (100 -> 125 -> 150) via update_resource. The response reports overflow when content exceeds the grid.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | merge (default) = upsert/remove listed blocks only; replace = page becomes exactly `blocks`. | |
| blocks | No | Blocks the page should show, applied in order (auto-placed entries stack top-to-bottom). | |
| remove | No | Block UUIDs to take OFF the page (merge mode only; the block objects are not deleted). | |
| confirm | No | Required true when mode=replace (it drops every block not in the list). | |
| dry_run | No | Compute the final grid and run every gate without writing. | |
| layout_id | Yes | Layout (page) UUID. | |
| expected_updated_at | No | Optimistic-concurrency token: the layout's updated_at from your read. Refuses with a conflict if the page changed in between (e.g. a parallel loop) — re-read, re-apply, retry. |