Page

Page Developer Docs

Pages are the top-level assembly unit in FaceFlow.

For technical users, a Page is not a template file. It is a structured runtime record that binds a layout, ordered sections, shared assets, and optional business systems into one publishable experience.

Core Responsibility

The Page layer is responsible for:

  • selecting the layout shell
  • storing ordered section composition
  • binding authored field values to reusable component contracts
  • coordinating embedded systems such as Forms, Reviews, and Lists
  • supporting governed editing, preview, and publish flows

Pages should orchestrate. They should not become the place where layout logic, component schema decisions, and one-off business rules all collapse together.

Page Model

A typical Page combines:

  • one layout
  • an ordered list of component instances
  • optional page-scoped reusable sections
  • optional embedded Form or Review experiences
  • optional dynamic list behavior

Conceptually:

{
  "layout": "default-site",
  "components": [
    {
      "component": "hero-banner",
      "scope": "page",
      "fields": {
        "heading": "Build faster with FaceFlow",
        "subheading": "Reusable sections for scalable websites"
      }
    },
    {
      "component": "testimonial-strip",
      "scope": "layout"
    }
  ]
}

The exact storage implementation is internal. What matters for technical users is the contract: Pages assemble reusable objects instead of owning raw template code directly.

Render Path

At runtime, Page rendering typically follows this flow:

  1. resolve the requested Page
  2. load the assigned Layout
  3. resolve shared site, layout, and page-scoped sections
  4. render ordered Components with their field values
  5. render embedded dynamic systems such as Lists, Forms, or Reviews
  6. return the final assembled output

A simplified structure looks like this:

<body>
  {header}
  {siteComponents}
  <main>
    {content}
  </main>
  {footer}
</body>

The Page owns {content} orchestration. The Layout owns the shell around it.

Assembly Example

A more explicit Page assembly can be reasoned about like this:

{
  "layout": "service-site-shell",
  "components": [
    {
      "component": "hero-banner",
      "scope": "page",
      "fields": {
        "heading": "Enterprise Security",
        "summary": "Structured trust content for SaaS websites",
        "ctaUrl": "/contact/"
      }
    },
    {
      "component": "lead-form",
      "scope": "page",
      "fields": {
        "contactForm": "contact-sales"
      }
    }
  ]
}

This example is useful because it shows the Page owning composition and instance values, while Layout and Component contracts remain separate.

Relationship to Layouts and Components

Keep these boundaries strict:

  • Layout defines the page shell
  • Component defines a reusable section contract
  • Page assembles a sequence of components into a final experience

If a Page starts carrying structural shell logic, the Layout is too weak.

If a Page starts duplicating section rules that should belong to a Component, reuse is breaking down.

Common Page Composition Example

default-site layout
  -> hero-banner component
  -> feature-grid component
  -> lead-form component
  -> faq-accordion component

That composition should remain understandable without reading custom code. If it cannot, the architecture is usually drifting.

Dynamic and Interactive Content

Pages often include more than static sections. Common cases include:

  • a lead capture Component embedding a Form
  • a trust section embedding a Review model
  • a resource archive driven by a List
  • page-aware Variables reused in multiple sections

Example:

<section class="section-contact">
  <div data-form-embed="enterprise-demo-request"></div>
</section>

<section class="section-proof">
  <div data-review-embed="customer-success-reviews"></div>
</section>

This is why Page design review should consider the full runtime path, not only visual composition.

Integration Boundaries

In technical review, keep these boundaries stable:

  • Page chooses which reusable systems participate in the experience
  • Component defines how a reusable section renders
  • Form and Review models own submission behavior
  • List definitions own dynamic archive behavior

If a Page starts carrying too much implementation detail, the object model is drifting.

Page Types and Change Strategy

Not every Page should be treated the same way.

  • campaign pages optimize for speed and controlled variation
  • evergreen service pages optimize for reuse and long-term maintenance
  • list-driven pages optimize for dynamic content growth
  • trust or conversion pages often coordinate multiple systems together

Technical teams should choose the right surrounding assets for each type instead of forcing every Page into the same pattern.

Versioning, Localization, and Portability

Pages are often the unit that teams:

  • localize across languages
  • restore after an unwanted change
  • move between environments
  • review before publication

Treat the Page as an operational asset, not just a visual output target.

Related feature references:

Technical Review Checklist

  • does the Page use the correct Layout for its page family?
  • are Components ordered and scoped intentionally?
  • are Forms, Reviews, or Lists embedded through reusable contracts rather than hard-coded markup?
  • does the Page rely on Variables or shared sections where reuse is expected?
  • would a future editor understand the Page structure without reverse-engineering exceptions?

Anti-Patterns

Avoid these patterns:

  • page-specific shell markup that should belong in the Layout
  • freeform section markup repeated across many Pages
  • business logic hidden in page-only content
  • mixing unrelated objectives into one Page just because it is already live
  • forcing a dynamic archive into a manually maintained Page composition

Example Build Pattern

For a typical service landing page:

Layout: service-site-shell
Page:
  - hero-banner
  - benefits-grid
  - customer-logos
  - review-strip
  - demo-request-form

That pattern stays maintainable because each concern has a clear home.