How Aero Page Builder 2.x stores, edits, and renders a page.

APB-DOCS-ARCH

Aero Page Builder is a paragraph-based composition system for Drupal 11. Editors assemble pages from a fixed set of parent components (apb_pb_*). Most parents hold nested item paragraphs (apb_pi_*). Layout, color, width, and placement come from a shared field vocabulary (taxonomies plus storages shipped by apbuilder), not from one-off theme templates.

This documentation describes APB 2.1.0 as installed on the demo and on this docs site. Do not invent options: every component field on this site was dumped from the live Field API into build/inventory/.

Host field

Content types that should be page-builder hosts get field_apb_pb_paragraphs: unlimited entity_reference_revisions pointing at paragraphs. The widget is Paragraphs Legacy (entity_reference_paragraphs), add mode button, edit mode open. The formatter is entity_reference_revisions_entity_view.

Which parent bundles are allowed is not a static YAML list. Each apb_pb_* module’s hook_install() adds its bundle to handler_settings.target_bundles on every FieldConfig named field_apb_pb_paragraphs. Enable or disable hosts at /admin/config/content/apbuilder.

Parents are a flat list. You cannot nest a parent inside a column. When a brief asks for “an accordion in the right column,” the honest options are two siblings, or target placement into a simple-content region item (see Target placement).

Parent and item

  • Parent apb_pb_<name> — one per component module. Holds layout fields plus a multi-value ERR field of items. Rendered as a section.
  • Item apb_pi_<name> — nested via Inline Entity Form. One row, slide, card, or tab.
  • Exceptions. Views has no item bundle. Simple content has four item types (content, images, background, region). Profiles nest one extra level (apb_pi_profile_social_media). Webform on the demo is the site-local webform_embed paragraph, not an apb_pb_* product component.

Anything needed by more than one component lives in apbuilder. Exclusive fields live in the owning module. Shared storages use persist_with_no_fields: true.

Render path

  1. The node view display renders field_apb_pb_paragraphs.
  2. apbuilder_preprocess_paragraph() (all apb_pb_* parents) sets section-title variables, turns container-settings JSON into scoped CSS, and emits data-apb-target-placement. When the paragraph must move, it also sets data-apb-placement-pending.
  3. Component Twig renders a wrapper #apb-<component>-{id} with data-apb-* config. Component JS must read those attributes, not .field--name-* markup. Init must be idempotent.
  4. PageAttachmentsHooks attaches apbuilder/aero-page-builder-core on canonical node routes that have host content. It is skipped on admin routes so FOUC CSS does not hide the widget.
  5. In the browser: vendor JS (−9) → apb-base.js (−8) → apb-placement.js (−7) → apb-editor.js (−6) → apb-orchestrator.js (−5) → component libraries.
  6. The orchestrator wraps body children in #apb-wrapper (that ID is not in Twig). Placement runs once on setTimeout(0) and moves pending paragraphs into theme drop zones.

JavaScript libraries

The core library vendors Embla, Video.js, Splide, Tippy/Popper, WOW, GSAP, OverlayScrollbars, simpleParallax, and GLightbox. Components must not vendor-copy those. Map: accordion-js (Accordion); Splide (Carousel, Slideshow, Simple content images); Embla + AutoScroll (Infinite logos); GLightbox (Image gallery, Links, Video, Overlay content, Profiles modal); simpleParallax (Simple content backgrounds and container-settings image parallax); custom tabs JS (Tabs). Video.js is vendored for slideshow slide videos — apb_pb_video uses GLightbox, not Video.js.

Text formats

Use apb_full_html for APB body fields written by scripts. apb_basic_html is the restricted subset. Do not use core full_html / basic_html if you want the same editor config as the product.