ConceptsSurfaces

What is a Surface?

A surface is the runtime render of a Receipt. Reproducible, versioned, capability-bound, and ready to host a PhiSo conversation the moment it ships.

Page vs Surface

Pages are documents you author once and update by hand. Surfaces are the materialised form of a Receipt — a signed, line-numbered recipe of blocks, props, capabilities, and theme tokens that PhiCo proposes and you accept before publish.

PageSurface
Static documentReceipt-materialised render
Hand-authored contentComposable from a typed catalog
One-shot renderReproducible from the Receipt hash
No audit trailPhiSo-ready post-publish

Surfaces exist

Every surface has its own identity within PhiWebs. It’s not just a URL or a file — it’s an entity with:

  • Identity — A unique identifier that persists across the ecosystem
  • Metadata — Title, description, preview image, and SEO properties
  • State — Memory that persists user interactions and context
  • Lifecycle — Birth, publication, versioning, and retirement

How surfaces change over time

Every change is a new Receipt. Nothing publishes until a human accepts the diff.

  • Add capabilities — Declare any of the canonical 5: platform/persistence, platform/entities, platform/navigation, platform/interaction, platform/input. Capability config goes into the Receipt. (Visual appearance is not a capability — it ships as a separate ui-appearance atom kind.)
  • Version history — Every accepted Receipt is an immutable snapshot. Roll back to any previous version with a single API call.
  • Responsive layout — Block layouts declare xs/sm/md/lg breakpoints; the runtime renders the correct grid span per device.
  • PhiSo intelligence — Once published, surfaces host a PhiSo widget that answers visitor questions from the live Surface contract — no extra training, no external scraping.

Surfaces connect

Surfaces don’t exist in isolation. They:

  • Compose — Surfaces can contain other surfaces.
  • Link — Reference and navigate to other surfaces.
  • Share — Publish to the marketplace for others to discover.
  • Inherit — Start from starter surfaces and customize.

Surface composition

Surfaces are composed from blocks — primitive building elements:

Surface
├── Block (container)
│   ├── Block (heading)
│   ├── Block (text)
│   └── Block (button)
├── Block (grid)
│   ├── Block (image)
│   └── Block (image)
└── Capabilities
    ├── auth
    ├── analytics
    └── seo

Learn more about blocks and the composition model.

Surface lifecycle

  • Birth — Created from scratch or from a starter surface.
  • Development — Composed with blocks, enhanced with capabilities.
  • Publication — Deployed to a domain, made accessible.
  • Evolution — Updated, versioned, capabilities added.
  • Retirement — Archived or removed when no longer needed.

Developer reference — surface schema

Every surface has a consistent JSON structure with metadata and content:

{
  "id": "landing-page",
  "name": "Landing Page",
  "slug": "landing",
  "version": 1,
  "blocks": [
    { "type": "container", "children": [] }
  ],
  "settings": {
    "theme": "default",
    "layout": "full-width"
  }
}
PropertyTypeDescription
idstringUnique identifier
namestringHuman-readable display name
slugstringURL-friendly path segment
versionnumberVersion number for tracking changes
blocksBlock[]Array of root-level blocks
settingsobjectTheme, layout, and rendering options

Surface types

  • Page surface — A complete page with its own URL route. Used for landing pages, about pages, and standalone content.
  • Section surface — An embeddable section that can be placed within existing pages. Used for dynamic content areas.
  • Template surface — A reusable template with placeholder content. Used as a starting point for new surfaces.
  • Dynamic surface — Generated from data at runtime. Used for product pages, blog posts, and data-driven content.

Rendering surfaces

Use the SurfaceRenderer component to render a surface:

import { SurfaceRenderer } from '@pwfabric/sdk/react'
 
function Page({ surface }) {
  return (
    <SurfaceRenderer
      surface={surface}
      theme="default"
      components={customComponents}
    />
  )
}

Ready to create your first surface?