This guide is for frontend developers building user-facing surfaces against Platform BFF (admin, portal, public, embedded, and other product-mounted screens). You do not need to know Go module internals or storage layout. Admin examples below are the current proof set, not the architectural boundary.
Platform default is renderer-agnostic runtime: BFF contract + your renderer adapter. Vite/Next/React examples below are one adapter path, not the Platform default architecture.
Think of /bff/* like server props or a loader in Next.js:
// App Router server component or loader
const screen = await fetch(`${API}/bff/screens/go-admin/posts`, {
credentials: "include",
}).then((r) => r.json())You receive a UI model, not raw posts[]. The backend already decided:
- view type (
table,form,kanban,dashboard, …); - columns and fields;
- row actions and capabilities;
- nav items for the current user;
- metadata bridges to REST (
list_api,form_action).
| Kind | Owner | Your responsibility |
|---|---|---|
| Data/model hydration | BFF | Rows, pagination, form values, validation, action metadata arrive in /bff/* JSON |
| UI hydration | Your adapter | React hydrate, islands, partial client boot, SSG enhancement |
Do not expect BFF to perform React hydration or island boot. Fetch the model, then activate UI in your renderer.
// vite.config.ts
export default {
server: {
proxy: {
"/bff": "http://127.0.0.1:8080",
"/go-json": "http://127.0.0.1:8080",
"/go-login": "http://127.0.0.1:8080",
},
},
}Use credentials: "include" so session cookies reach the app.
const screen = await bff.getScreen("go-admin/posts")
const nav = await bff.getNav()
const session = await bff.getSession()| Endpoint | Returns |
|---|---|
/bff/screens/go-admin/posts |
ScreenModel |
/bff/nav |
{ items: NavItem[] } |
/bff/session |
{ version, authenticated, principal_id, profile_id, capabilities } |
Auth: 401 = not logged in; 403 = logged in but forbidden. Handle in UI, do
not expect redirect HTML from JSON routes.
Platform provides base view types. Your app registers components:
const viewRegistry: Record<string, ComponentType<{ screen: ScreenModel }>> = {
table: TableScreen,
form: FormScreen,
kanban: KanbanScreen,
dashboard: DashboardScreen,
// product-specific extensions:
chat: ChatScreen,
"telegram-bot": TelegramBotScreen,
}
export function AppScreen({ screen }: { screen: ScreenModel }) {
const View = viewRegistry[screen.view] ?? UnsupportedScreen
return <View screen={screen} />
}You do not wait for Platform changes for every new product screen. Add a
renderer component and have the product module return view: "chat" (or similar).
view |
Typical payload |
|---|---|
table |
columns, rows, row_actions, pagination, metadata.list_api |
form |
fields, form_record, metadata.form_action |
kanban |
grouping metadata, cards (when hydrated) |
dashboard |
sections[], optional widgets[], metric/status/chart/activity payloads |
Use screen.fallback when your renderer lacks a specialized view (e.g. render
kanban as grouped table).
| Task | API |
|---|---|
| Render page/screen structure (any surface) | /bff/screens/... |
| Mutate via declared actions (proof: admin forms) | POST /bff/actions/... per metadata.form_action |
| Load/save records for integrations | /go-json/... per metadata.list_api |
| Show who is logged in | /bff/session |
| Build navigation chrome | /bff/nav |
Stage 6 ships POST /bff/actions/* for AppCMS post create/update/trash. Form
screens expose metadata.form_action, metadata.action_scope, and
metadata.action_token. React FormView submits BFF actions via fetch with
FormData; Templ posts native HTML forms to the same paths.
Official proof screens must match Templ reference semantics:
- AppCMS:
/go-admin/posts - AppCRM:
/go-admin/crm/leads
Same ScreenModel.id, view, resource, columns/fields, metadata, and nav.
Styling may differ; behavior must not.
React/Vite/shadcn DX is deferred until after Platform BFF freeze. Platform stabilizes the contract artifacts below; future frontend adapters build on them without changing Platform core.
| Artifact | Path | Use for future DX |
|---|---|---|
| JSON Schema | schema/bff/v1/*.schema.json |
Validate /bff/* responses |
| TypeScript contract | web/contract (@fastygo/bff-contract) |
Shared types and validators |
| Golden fixtures | pkg/conformance/testdata/bff/v1/ |
Local fixture mode, tests, adapter dev |
| Conformance matrix | pkg/conformance/bffparity/ |
Expected semantics per proof screen |
Adapter authors can implement table/form screens from schema + fixtures today. No official React hooks or shadcn mapping are part of the frozen surface.
Deferred React/Vite/shadcn proof should later provide:
| Capability | Purpose |
|---|---|
| Generated or hand-authored TypeScript types | Stay aligned with @fastygo/bff-contract / schema |
| Typed BFF client | getScreen, getNav, getSession, action posts |
useScreen |
Fetch and cache ScreenModel by path |
useAction |
Submit POST /bff/actions/* with validation handling |
useSession |
Auth and capability projection from /bff/session |
useNavigation |
Capability-filtered nav from /bff/nav |
| shadcn component mapping | Map BFF field/column types to UI primitives |
| Local fixture mode | Render proof screens without a Go server |
| Vite proxy example | Dev workflow against AppCMS/AppCRM :8080 |
| Templ parity | Same proof screens as Pass 5 minimum set |
These are adapter-layer helpers, not Platform core APIs.
- official React package or full frontend SDK;
- Next, Vue, or PHP/Handlebars adapter products beyond existing thin proofs;
create-fastygo-appor app generator;- shadcn component pack as a Platform requirement;
- React-specific assumptions in
pkg/bff,pkg/render, or Platform kernel.
web/react remains an optional compatibility proof, not stabilized Platform DX.
Official compatibility proof lives at web/react in the Platform repo. It is a
proof renderer, not stabilized Platform DX and not the default stack:
cd web/react
npm install
npm run devProof routes (with AppCMS or AppCRM on :8080):
/cms/posts->/bff/screens/go-admin/posts/crm/leads->/bff/screens/go-admin/crm/leads/cms/posts/edit->/bff/screens/go-admin/posts/post-rest/edit
Kit: src/fastygo (Screen, TableView, FormView, Nav, ActionButton).
UI8Kit is not required for JSON BFF renderer adapters.
JSON BFF adapters (React/Vite proof and third-party renderers) must consume the
canonical fixtures under pkg/conformance/testdata/bff/v1, not ad-hoc local
copies. The React proof imports fixtures through web/react/tests/fixtures.ts.
Adapter tests should validate:
validateScreenModel(fixture)passes;- view dispatch (
table/form) matches fixtureview; - metadata semantics (
list_api,form_action,action_scope) render correctly; - volatile
action_tokenis injected at runtime, not baked into fixtures.
Published artifacts for third-party adapters:
| Artifact | Path |
|---|---|
| JSON Schema | schema/bff/v1/*.schema.json |
| TypeScript contract | web/contract (@fastygo/bff-contract) |
| Thin adapter proofs | examples/renderer-adapters |
React imports the shared contract package instead of owning private BFF types.
Standard table and form rendering needs no Go module changes — drop a new
fixture JSON and validate against screen.schema.json.
Step-by-step adapter authoring: renderer-adapter-authoring.md.