Server-driven content blocks for React Native, iOS, Android, and Web. Define block types in code, render them natively, then publish, localize, and roll back over the REST API, without an app release.
# install the SDK + CLI $ npm i @contentflow/sdk # wire it up once import { ContentFlow } from '@contentflow/sdk' const cf = new ContentFlow({ key: 'cf_live_xxx', // key → tenant }) await cf.sync() // pull live blocks cf.render('home_hero') ✓ live ▊
Clients for React Native, iOS, Android, and Web. One key resolves your tenant, syncs live block instances, and renders them natively. Lifecycle: init → sync → render. SDK docs →
$ npm i @contentflow/sdk await cf.sync() cf.render('home_hero') ✓
JSON over HTTP at /api/v1, bearer-key auth. Sync blocks, seed instances, push strings, dispatch campaigns, read analytics. API reference →
Block types as code, versioned in git. cf init, cf push. CLI docs →
content.published, campaign.sent, and more. Webhook docs →
Install, authenticate, sync, and render your first block. About five minutes.
Workspace keys, cf_live_ vs cf_test_, bearer tokens, key-to-tenant resolution.
/sdk/sync, /cards/sync, idempotent seeding with externalId, block types.
String extraction, auto-translate, review-gated delivery via /sdk/strings.
Segment dispatch, delivery channels, event subscriptions, audience gotchas.
Gateway and services, multi-tenancy, content lifecycle, glossary, FAQ.
await cf.sync() const hero = cf.block('home_hero') return <CFBlock block={hero} />
$ curl -X POST .../api/v1/cards/sync \ -H "Authorization: Bearer cf_live_xxx" \ -d '{"instances":[{"externalId":"home_hero", ...}]}'
$ curl .../api/v1/sdk/strings?locale=ar \ -H "Authorization: Bearer cf_live_xxx" # only review-approved translations ship
$ npx contentflow push ✓ pushed 3 block types # types live in your repo, reviewed in PRs