Skip to main content

Implementing FormHostProvider

FormHostProvider is a React component you write once in your own project. It connects the Buildocs form to your backend — routing form events through your API and providing an auth token at runtime.

Every integration requires it. Without it, the form cannot load its definition or make any API calls.

How it works

  1. Your backend exposes a token endpoint. FormHostProvider fetches that token on mount.
  2. You call useBuildocsApi(yourBackendUrl, token) to get pre-wired HTTP methods that route to your backend.
  3. You build a HostBridge object mapping each form event to a method call.
  4. You render BuildocsHostProvider with the bridge, wrapping your children.

The form definition is still fetched directly from Buildocs using useBuildocsApi() (no custom URL).

Step 1 — Create the file

Create src/provider/FormHostProvider.tsx and paste in the boilerplate below.

import React, { useEffect, useState } from 'react';

import {
type TLoadForm,
type HostBridge,
type RunEventArgs,
type UploadArgs,
ChunkRequestArgs,
DeleteFileEventArgs,
DownloadFileEventArgs,
FileMetaEventArgs,
GetLinkedFileMetaEventArgs,
BuildocsHostProvider,
useBuildocsApi,
useViewport,
} from '@buildocsdev/sdk';

interface FormHostProviderProps {
readonly children: React.ReactNode;
}

export function FormHostProvider({ children }: FormHostProviderProps) {
const { isMobileDevice, width, height } = useViewport();
const [token, setToken] = useState<string | undefined>(undefined);

const buildocsApi = useBuildocsApi();

const myApiUrl = 'https://your-backend.com/api/v1/formspublic';
const myApi = useBuildocsApi(myApiUrl, token);

useEffect(() => {
fetch(`${myApiUrl}/token`, { method: 'POST' })
.then(r => r.json())
.then((d: { token: string }) => setToken(d.token))
.catch(e => console.error('Failed to fetch token:', e));
}, []);

const hostBridge: HostBridge = {
viewPort: { isMobileDevice, width, height },

runFormEvent: async (args: RunEventArgs) => {
return await myApi.runEvent(args, '/runevent');
},
runFormUploadFiles: async (args: UploadArgs) => {
return await myApi.uploadFiles(args, '/uploadfiles');
},
runFormDeleteFileEvent: async (args: DeleteFileEventArgs) => {
return await myApi.deleteFile(args, '/deletefile');
},
runFormDownloadFileEvent: async (args: DownloadFileEventArgs) => {
return await myApi.downloadFile(args, '/downloadfile');
},
runFormGetLinkedFileEvent: async (args: GetLinkedFileMetaEventArgs) => {
return await myApi.getLinkedFile(args, '/getlinkedfile');
},
runFormGetLinkedFileMetaEvent: async (args: GetLinkedFileMetaEventArgs) => {
return await myApi.getLinkedFileMetaEvent(args, '/getlinkedfilemeta');
},
runFormGetLinkedFileByChunks: async (args: ChunkRequestArgs) => {
return await myApi.getLinkedFileByChunks(args, '/getlinkedfilebychunks');
},
runFormGetPresignedUrl: async (args: FileMetaEventArgs) => {
return await myApi.getPresignedUrl(args, '/getpresignedurl');
},
runLoadFormEvent: async (args: TLoadForm) => {
return await buildocsApi.fetchFormDefinitionWithMeta(args.formCode);
},
};

return (
<BuildocsHostProvider hostBridge={hostBridge}>
{children}
</BuildocsHostProvider>
);
}

Step 2 — Wrap your app

FormHostProvider must be nested inside BuildocsProvider. Place both providers high enough in your tree to cover all Form components.

import { BuildocsProvider } from '@buildocsdev/sdk';
import { Form } from '@buildocsdev/sdk/form';
import { FormHostProvider } from './provider/FormHostProvider';

function App() {
return (
<BuildocsProvider apiKey="your-api-key">
<FormHostProvider>
<Form params={{ formCode: "your-form-code", guid: "new" }} />
</FormHostProvider>
</BuildocsProvider>
);
}

Token authentication

The token is fetched from your backend on mount and passed to useBuildocsApi as its second argument. All subsequent event calls include it automatically.

const myApi = useBuildocsApi(myApiUrl, token);

Your backend's /token endpoint should return:

{ "token": "<your-auth-token>" }

useBuildocsApi — two instances

Notice the boilerplate uses useBuildocsApi twice:

InstancePurpose
useBuildocsApi()Fetches the form definition directly from Buildocs
useBuildocsApi(myApiUrl, token)Routes all form events through your own backend

The form definition (runLoadFormEvent) is always fetched directly from Buildocs. All other events go through your backend.

Pre-populating form data

Pass existing data as the second argument to fetchFormDefinitionWithMeta. Keys must match the Name of each field in the Form Builder exactly.

runLoadFormEvent: async (args: TLoadForm) => {
const existingData = await myDb.getRecord(args.guid);
return await buildocsApi.fetchFormDefinitionWithMeta(args.formCode, existingData);
},

HostBridge methods

Each method maps to a form action and must have a corresponding endpoint implemented in your own backend. The final URL for each call is myApiUrl + customPath.

HostBridge methodDefault pathAction
runFormEvent/runeventButton and field events
runFormUploadFiles/uploadfilesFile uploads
runFormDeleteFileEvent/deletefileFile deletion
runFormDownloadFileEvent/downloadfileFile downloads
runFormGetLinkedFileEvent/getlinkedfileLinked file retrieval
runFormGetLinkedFileMetaEvent/getlinkedfilemetaLinked file metadata
runFormGetLinkedFileByChunks/getlinkedfilebychunksChunked file download
runFormGetPresignedUrl/getpresignedurlPresigned URL generation
runLoadFormEventForm definition load (direct to Buildocs)

See the FormHostProvider API reference for request payload details for each method.