Should I merge it now? Yes.
The public template and the new loader agree.
I compared every ngSwitchCase in the old preview with MARKETING_PAGE_LAYOUT_LOADERS and getMarketingPageLayoutInputs. The header is the one layout that stays a real template. The other 53 cases from that switch are loaders, and each extra input is the same expression as before. The add-section picker still reads the layout constants. This commit does not touch it.
I would merge 3645b6d5. The size numbers in the pull request description are the author's. I did not rebuild.
The inputs match the old switch
- Every lazy layout still gets
data. - The 14 editing layouts still get
isEditingModefromcmsPreviewMode. - Pinned horizontal scroll still gets
disablePinnedScrollon the mobile preview viewport. - Vertical card carousel, comparison, and the comparison full table still get
forceMobileViewon that same viewport. - Vertical card snap scroll still gets
isEditingModefrom the mobile viewport, which is what the old template did. - Footer still gets
syncWhitelabelLogoandpreviewBranding.
I checked those input names against each component class. Every one is an @Input on the class the loader returns. All 53 loader files export the class they name.
The header bindings are copied onto app-header-layout, including #headerLayout, the user menu template, and the welcome video modal. That is why the header is in STATIC_MARKETING_PAGE_LAYOUT_IDS and is not a dynamic import. ngComponentOutlet cannot project those two pieces of content.
LAYOUT_IDS has 55 keys. PRO_CONTACT_FORM_LAYOUT was already missing from the old switch, so a page that uses it still renders an empty slot. This pull request does not change that.
How a page loads layouts
Visible section ids are deduped. The header is skipped. Ids that already have a class are skipped. The rest import together. PendingTasks stays open until that batch finishes, including when the import throws, so server rendering does not wait forever. After a successful batch the classes are stored and markForCheck runs. The preview is OnPush.
A newer resolve, or ngOnDestroy, bumps layoutLoadGeneration. A stale batch does not write classes. Viewport, branding, and preview-mode changes rebuild layoutInputs without importing again. NgComponentOutlet applies those inputs on the existing component.
Angular's ViewContainerRef.createComponent looks up a server-rendered view by component id. The pending task is what keeps the app unstable until the class is assigned and change detection is scheduled, which is the window that lookup needs. I did not watch a browser for a hydration error.
One sharp edge. The batch is Promise.all. If one chunk rejects, none of that batch is stored, and the void call leaves an unhandled rejection. A missing chunk should fail one section. I would not hold the merge for it.
What I did not run
I did not build TopFans, compare SSR titles or app-*-layout counts, or open /, /athletes, /music-artists, /topfan-vs-patreon, or /creators-home. The test plan on the pull request is still unchecked. GitHub reports the pull request open and mergeable, with no status checks.
The useful check after merge is the one in that plan. Compare the server HTML for those routes, confirm unused layouts are absent, and confirm the header menu, welcome video, and editor picker still behave, with no hydration error in the console.