DevelopersSDKOverview

SDK reference

The official SDK for building applications with PWFabric. Create, manage, and render surfaces programmatically.

Installation

Install the SDK using pnpm (this monorepo and the SDK are pnpm-only — npm and yarn are not supported):

pnpm add @pwfabric/sdk

Compatibility matrix

PackageMin NodeMin ReactLicense
@pwfabric/sdk22.019.0MIT
@pwfabric/runtime22.019.0MIT
@pwfabric/core22.0MIT
@pwfabric/contracts22.0MIT

The SDK has peer dependencies on React 19. @pwfabric/contracts and @pwfabric/core are environment-agnostic and can be used in non-React codepaths (Node services, edge workers).

Quick start

Initialize the SDK and create your first surface:

import { createClient } from '@pwfabric/sdk'
 
// Initialize the SDK
const client = createClient({
  baseUrl: process.env.PWFABRIC_BASE_URL,
  token: process.env.PWFABRIC_TOKEN, // PAT or session token
})
 
// List surfaces
const { data: surfaces } = await client.surfaces.list()
 
// Create a surface
const surface = await client.surfaces.create({
  name: 'My Landing Page',
  blocks: [
    {
      type: 'heading',
      props: { content: 'Welcome to PWFabric', level: 1 },
    },
    {
      type: 'text',
      props: { content: 'Build beautiful surfaces in minutes', color: 'muted' },
    },
  ],
})

createClient()

The main client factory for interacting with PWFabric.

Configuration

OptionTypeDescription
baseUrlstringBase URL of your PWFabric API instance
tokenstringPersonal Access Token (PAT) or session token

Surface CRUD

Create and manage surfaces with client.surfaces:

// Create a surface
const surface = await client.surfaces.create({
  name: 'Product Page',
  blocks: [
    { type: 'container', props: { maxWidth: 'lg' } },
    { type: 'heading', props: { level: 1, content: 'Our Product' } },
    { type: 'text', props: { content: 'Description here...' } },
    { type: 'button', props: { label: 'Buy Now', variant: 'primary' } },
  ],
})
 
// Get a Surface
const result = await client.surfaces.get('sf_abc123')
 
// List Surfaces
const list = await client.surfaces.list({ limit: 20 })
 
// Delete a Surface (archives it; revisions are preserved)
await client.surfaces.delete('sf_abc123')
 
// Edits happen on the draft; use the REST endpoint until the SDK ships
// dedicated helpers:
await fetch(`/api/surfaces/sf_abc123/draft`, {
  method: 'PUT',
  headers: { 'content-type': 'application/json', authorization: `Bearer ${token}` },
  body: JSON.stringify({ name: 'Updated Product Page' }),
})

React integration

Render surfaces in React applications using the SurfaceRenderer component from @pwfabric/runtime:

import { SurfaceRenderer, BlockRenderer } from '@pwfabric/runtime'
 
// Render a full surface
function App({ surface }) {
  return (
    <SurfaceRenderer
      surface={surface}
      registry={customRegistry} // Optional custom block registry
    />
  )
}
 
// Render individual blocks
function BlockView({ block }) {
  return <BlockRenderer block={block} />
}

SurfaceRenderer props

PropTypeDescription
surfaceRenderableSurfaceThe surface definition to render
registryBlockRegistry?Custom block registry (merged with built-in blocks)
classNamestring?Additional CSS classes

TypeScript types

The SDK is fully typed. Import types from @pwfabric/sdk:

import type {
  Surface,
  Block,
  BlockType,
  PWFabricConfig,
  SurfaceSettings,
} from '@pwfabric/sdk'
 
const surface: Surface = {
  id: 'surface-1',
  name: 'My Surface',
  slug: 'my-surface',
  version: 1,
  blocks: [],
}
 
const block: Block = {
  id: 'block-1',
  type: 'heading',
  props: {
    level: 1,
    content: 'Hello World',
  },
}

Error handling

The SDK does not throw on API errors. Every client method returns a discriminated union you can pattern-match against:

const result = await client.surfaces.create(data)
 
if (result.ok) {
  console.log('created', result.data.id)
} else {
  console.error('failed', result.error.code, result.error.message)
  // result.error.statusCode, result.error.details for richer context
}

Network and SDK-internal failures still throw — wrap calls in try/catch if you need to handle those (DNS failure, body-parse error, etc.).

Two paths to ship custom blocks