Quick start
Get up and running with PWFabric in under 5 minutes.
Prerequisites
- Node.js 22.0 or later
- pnpm 10+ (this monorepo and its SDK are pnpm-only —
npmandyarnare not supported) - A PhiWebs account at account.phiwebs.com/signup — you’ll need a
worldIdand an API token from World settings → Developers. - Basic TypeScript or JavaScript
1. Install the SDK
pnpm add @pwfabric/sdk2. Create a client
createClient() returns a fully-typed PWFabricClient. Configure it with
your World’s API base URL and the bearer token you minted in World
settings.
import { createClient } from '@pwfabric/sdk'
const client = createClient({
baseUrl: process.env.PWFABRIC_BASE_URL ?? 'https://api.phiwebs.com',
token: process.env.PWFABRIC_TOKEN,
})All client methods return a discriminated-union result ({ ok: true, data } | { ok: false, error }) so you pattern-match instead of try/catch.
3. Create your first Surface
client.surfaces.create() mints a new draft Surface inside your World.
The blocks below all come from the first-party block catalog — container,
heading, text, button, grid. (See the
blocks reference for the full 45-block list.)
const result = await client.surfaces.create({
name: 'My Landing Page',
slug: 'landing',
blocks: [
{
type: 'container',
props: { maxWidth: 'lg', padding: 'lg' },
children: [
{ type: 'heading', props: { content: 'Welcome to PWFabric', level: 1, align: 'center' } },
{ type: 'text', props: { content: 'Build beautiful Surfaces in minutes.', align: 'center', color: 'muted' } },
{ type: 'button', props: { label: 'Get started', href: '/developers/quickstart', variant: 'primary' } },
],
},
{
type: 'grid',
props: { columns: 3, gap: 'md' },
children: [
{ type: 'text', props: { content: 'Fast — build in minutes' } },
{ type: 'text', props: { content: 'Flexible — customise everything' } },
{ type: 'text', props: { content: 'Composable — 45 block types' } },
],
},
],
})
if (!result.ok) {
throw new Error(`Surface create failed: ${result.error.message}`)
}
const surface = result.data4. Render the Surface
The renderer lives in @pwfabric/runtime, not the SDK package.
getBlockRegistryForWorld(worldId) loads the block registry the World
has installed (per ADR-131 / ADR-122 the default registry is empty).
import { SurfaceRenderer } from '@pwfabric/runtime'
import { getBlockRegistryForWorld } from '@pwfabric/runtime/blocks'
async function Page() {
const registry = await getBlockRegistryForWorld(surface.worldId)
return <SurfaceRenderer surface={surface} registry={registry} />
}Next steps
- Concepts — Surfaces, Blocks, Composition, Capabilities
- SDK reference — full
PWFabricClientAPI - API reference — REST endpoints under the hood
- Blocks reference — every block PhiCo can summon