# @formcentric/client

> Formcentric-Client package for rendering Formcentric-Headless Forms

Latest version **4.6.0** (published 2026-08-17) · UNLICENSED license · 0 weekly downloads

## Install

```sh
npm install @formcentric/client
pnpm add @formcentric/client
yarn add @formcentric/client
bun add @formcentric/client
```

Provides the command `fc-create-theme`.

## Health

**Score 65/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; recently updated; high maintenance score.

Warnings: low downloads; large bundle.

## Facts

| | |
|---|---|
| Version | 4.6.0 |
| Published | 2026-08-17 |
| First published | 2023-01-18 |
| Weekly downloads | 0 |
| License | UNLICENSED |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 0 |
| Unpacked size | 17.3 MB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Formcentric |
| Maintainers | vpappas, fbaser, nmohr, nboehm |

## Links

- npm: https://www.npmjs.com/package/@formcentric/client
- npm.io page: https://npm.io/package/@formcentric/client

## Recent versions

- 4.6.0 (latest) — 2026-08-17
- 3.9.4 (patch) — 2026-08-31
- 4.5.1 — 2026-08-17
- 4.4.0 — 2026-08-17
- 4.3.0 — 2026-08-17
- 4.2.0 — 2026-06-09
- 4.1.1 — 2026-06-09
- 4.1.0 — 2026-06-09
- 4.0.0 — 2026-05-11
- 3.9.3 — 2026-05-11
- 3.9.2 — 2026-04-02
- 3.9.1 — 2026-03-24
- 3.9.0 — 2026-03-05
- 3.8.2 — 2026-03-05
- 3.8.1 — 2026-02-06
- … 59 more at https://npm.io/package/@formcentric/client/versions

## README

# Formcentric Client

Formcentric Client package for rendering Formcentric Headless Forms.

## INSTALLATION

```bash
  npm install @formcentric/client
```

## Further information

For further Formcentric Client integration and development topics, see:

- [Formcentric Developer Documentation General](<https://help.formcentric.com/en/cloud/client-(generell)/>)
- [Formcentric Developer Documentation SDK](https://help.formcentric.com/en/cloud/client-sdk/)
- [Formcentric Developer Documentation Static](https://help.formcentric.com/en/cloud/client-static/)

Local copies of these documents ship with the package under [`docs/en`](./docs/en): [General](./docs/en/01-general.md), [SDK](./docs/en/03-client-sdk.md), [Static](./docs/en/02-client.md).

## USAGE & EXAMPLES

To implement a form on your Page, two things are needed:

- A `div` with the data-attribute `fc-id`
- Execution of the `@formcentric/client` Script

The Client-Script needs to load the `formapp.js`, because of this the said file has to be served and reachable.

## SPA / Module Usage

For SPA integrations, import the module and mount explicitly. In this mode there are no side effects on import.

`mount()` is config-authoritative. Module/SDK integrations must pass `embedId` or `formDefinition` via the config object. Static `data-fc-*` attributes and `data-fc-watch` on the target element are not part of the SDK contract.

```ts
import { configure, mount } from '@formcentric/client'

configure({
    srcUrl: 'https://formcentric.dev',
    themeDir: '/themes',
    theme: 'geneva',
    requestHeaders: {
        'X-App': 'my-app',
    },
})

const instance = mount('#my-form', {
    embedId: '...',
    formappUrl: '/formapp.js',
    debug: true,
})

// Optional cleanup
await instance.unmount()
```

If your bundler already injects the theme CSS/templates, you can skip runtime theme loading:

```ts
const instance = mount('#my-form', {
    embedId: '...',
    skipThemeLoad: true,
    skipTemplatesLoad: true,
    themeVariables: {
        primaryColor: '#0f62fe',
    },
})
```

## Theming

The Theme consists of:

- one CSS-File `styles.css` containing all styles with custom properties
- one JS-File `script.js` defining the templates for the input fields
- CSS-Custom-Properties `_variables.json` defined on the body or the embed-div itself

The client does not contain any theme information, and will only work if you are providing these requirements.

### Customization

To create a custom theme, follow these steps in your app's root directory. This command generates a new theme, based on our default Formcentric theme, in the fc-themes folder. Optionally, you can base your custom theme on any of the other provided Formcentric themes by specifing its directory name in the second argument.

```bash
// npm
npm run fc-create-theme [fcThemeName]

// yarn
yarn fc-create-theme [fcThemeName]

// pnpm
pnpm fc-create-theme [fcThemeName]

```

#### Custom theme usage

To use your custom theme, bundle its `templateEntry` file to a single file `script.js` in your custom theme's root directory and specify the path on your formDiv (see example below).

#### Field widths

If you want to customize field widths you can do so in `_field.scss` or any other css file included in your website. Please keep in mind that row calculations depend on these values, so if you decide to change them you should make sure that **CORS** is configured correctly. Formcentric client should be able to read the relevant css file programatically to extract your customized field widths.

## EXAMPLE FORM-CONTAINER

```html
<div
    data-fc-id="..."
    data-fc-data-url="https://formcentric.com/headless-server"
    data-fc-formapp-url="assets/formapp.js"
    data-fc-theme-dir="fc-themes"
    data-fc-theme="formcentric"
></div>
```

## Further form div attributes

1. **data-fc-form-definition=""** Parse an encrypted form definition to the client application (stringified JSON)
2. **data-fc-data-url=""** Define the general asset url
3. **data-fc-formapp-url=""** Define the url of the client js `formapp.js`
4. **data-fc-template-url** Define the url of the template js file `script.js`
5. **data-fc-theme-url** Define the url of the style css file `styles.css`
6. **data-fc-theme-variable-url** Define the url of your css variables json file `_variables.json`
7. **data-fc-vars** Define a variables object that should be send in the initial request (stringified JSON)
8. **data-fc-params** Override window parameters that should be send in the initial request (stringified JSON)
9. **data-fc-refs** Define a refs payload string that is sent as-is in the initial request (for example encrypted refs payloads)
10. **data-fc-parent-url** Define a parent url that should be send in DOI (double optin) emails (see Double optin)

## Configuration

Most of the configuration is done via the data-attributes on the embed-div,
but some scenarios may call for mor advanced control over the rendering app.
This is done via the `window.formcentric` Object. It follows the following interface.

Most of the options are readonly and should not be touched.

```typescript
declare interface Window {
    formcentric?: {
        initFormcentric?: () => void
        stopAll?: () => Promise<void>
        unmountAll?: () => Promise<void>
        getInstance?: (id: string) => fcInstance | undefined
        setInstanceOptions?: (instance: string, options: fcInstance['options']) => void
        formapp?: {
            templates?: fcTemplates
            start?: Start
            instances?: {
                [embedId: string]: {
                    reSetFormDefinition?: (reSetFormDef: fcClientFormDefinition) => void
                    initElement?: HTMLElement
                    options?: {
                        baseUrl: string
                        embedId: string
                        instanceId: string
                        formDefinition?: fcClientFormDefinition
                        debug?: boolean
                        locale?: string
                    }

                    stop?: () => Promise<void>
                    unmount?: () => Promise<void>
                    reload?: () => Promise<void>
                    requestOptions?: {
                        initial?: {
                            headers?: Record<string, string>
                        }
                    }
                }
            }
        }
    }
}
```

Static integrations using `formcentric.js` (including SPA-style route changes with `initFormcentric()`) remain compatible with fire-and-forget lifecycle calls.

For new module/SDK integrations (`mount()`), awaiting `stop/unmount/reload/stopAll/unmountAll` is recommended for stricter lifecycle sequencing.

Global defaults now have a public API:

- Module / SDK: use `configure(...)`
- Static first-load embedding: keep using top-level `window.formcentric.*` assignments before loading `formcentric.js`
- Static post-load/manual re-init flows: `window.formcentric.configure(...)` is also available after the script has loaded

`configure(...)` and `window.formcentric.configure(...)` use the same global config shape as `MountConfig`, except these per-form-only keys are excluded:

- `embedId`
- `formDefinition`
- `instanceId`
- `formName`
- `vars`
- `params`
- `refs`
- `conflictBehavior`

Global defaults are overridden by per-form config.

Custom initial request headers are now public too:

- Static page embedding, global: `window.formcentric.requestHeaders = { ... }`
- Static page embedding, per form: `data-fc-request-headers='{"X-App":"example"}'`
- SDK `mount()`: `requestHeaders`
- React / Vue components: `requestHeaders` prop

`requestHeaders` only applies to the initial form request.

### Advanced Static Example for custom initial request headers

```html
<script>
    window.formcentric ??= {}
    window.formcentric.formapp ??= {}
    window.formcentric.formapp.instances ??= {}
    window.formcentric.formapp.instances['b1265a82-0eab-47ac-hhhh-948b18e423c5'] = {
        requestOptions: {
            initial: {
                headers: { testHeader: '123' },
            },
        },
    }
</script>
```

If `requestOptions.initial.headers` is set this way, it is still the final low-level override for the initial request. Use this only as an advanced escape hatch.

### Example Client script tag

```html
<script
    src="./formcentric.js"
    defer
></script>
```

Everytime `formcentric.js` gets executed, every Form-Container (identified by `data-fc-id`) gets initialized as a form.
You can manually call `window.formcentric.initFormcentric()` to setup and start the client for all divs with and fc-id data-attribute.

### Double optin

No configuration is needed if the embedded form is present during initial page loads. However, if the form is embedded in a single page application and only rendered when certain states are set. The following configuration is necessary to enable double optin.

Configure `data-fc-parent-url` attribute on the form div. This attribute can be used to parameterize the internal state of embedding single page applications. For example if the client is running in a modal open modal state when users click on the opt in link can be restored by storing the neccessary information as parameters in the parent url attribute. The embedding app should then be configured in a way that it restores the states necessary to render the form.

### Example Double optin in SPA using React

```js
const FormModal = () => {
    const [open, setOpen] = useState(false)

    useEffect(() => {
        const urlParams = new URLSearchParams(window.location.search)
        const formOpen = urlParams.get('formopen')
        if (formOpen) {
            setOpen(true)
        }
    }, [])

    return (
        <div
            data-fc-id='...'
            data-fc-parent-url='https://admiralcorp.com/?formopen=true'
        />
    )
}
```

---
_Source: https://npm.io/package/@formcentric/client · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
