@formerie/client

中文文档
0.1.0-alpha.15发布于 2026/11/03MITTypeScriptES Module零依赖近 30 天下载 2808

JavaScript and TypeScript client helpers for the Formerie public API and runtime.

原始使用文档
文档目录14 节
  1. Packages
  2. Framework Entry Points
  3. Custom Element
  4. Submitting From Your Server
  5. Two Languages On One Form
  6. Changelog
  7. Install
  8. API Usage
  9. Runtime Usage
  10. Schema And Form Helpers
  11. CDN Usage
  12. CLI And AI Skills
  13. Framework Examples
  14. License

@formerie/client

JavaScript and TypeScript helpers for the Formerie public API and public runtime.

The package builds URLs for public API routes, clean runtime routes, hosted pages, and embed scripts. It submits form payloads, validates partial form data, fetches public schemas, maps API error codes to default messages, and exposes helpers for multiple validation issues per field.

Packages

This repository contains the public Formerie JavaScript SDK packages:

  • @formerie/client: framework-neutral JavaScript and TypeScript client.
  • @formerie/client/element: the <formerie-form> custom element, for any framework or plain HTML.
  • @formerie/react: React hooks.
  • @formerie/vue: Vue composables.
  • @formerie/svelte: Svelte stores, and @formerie/svelte/kit for SvelteKit form actions.
  • @formerie/solid: Solid primitives.
  • @formerie/angular: Angular service and injection token.
  • @formerie/astro: Astro helpers for Formerie form attributes and client setup.
  • @formerie/next: Next.js server actions and React hooks.
  • @formerie/nuxt: Nuxt server handlers and Vue composables.
  • @formerie/react-router: React Router route actions and React hooks.

Framework packages are thin adapters over @formerie/client. They do not duplicate request routing, response parsing, validation error handling, or API security behavior.

Target objects point at a form by its ID: { form: "fm_t77txbvg43nmar" }. To send through your own hostname, add the endpoint option and keep the same ID.

Framework Entry Points

Project typeSubmit from the browserSubmit from your server
Plain HTML or browser JavaScript@formerie/client/element or @formerie/clientDirect HTTP API or @formerie/client
React@formerie/reactsubmitFormerieRequest from @formerie/client
Next.js@formerie/next in client componentscreateFormerieNextAction from @formerie/next
React Router@formerie/react-router hookscreateFormerieReactRouterAction from @formerie/react-router
Vue@formerie/vuesubmitFormerieRequest from @formerie/client
Nuxt@formerie/nuxt in componentscreateFormerieNuxtSubmitHandler from @formerie/nuxt
Svelte, SvelteKit@formerie/sveltecreateFormerieAction from @formerie/svelte/kit
Solid, SolidStart@formerie/solidsubmitFormerieFormData from @formerie/client
Angular@formerie/angularsubmitFormerieRequest from @formerie/client
Astro@formerie/astro for attributes, @formerie/client/element in a pagesubmitFormerieRequest from @formerie/client
Qwik, Preact, Lit, Web Components@formerie/client/elementsubmitFormerieFormData from @formerie/client

For frameworks without a dedicated Formerie adapter, use @formerie/client directly in server routes, actions, browser scripts, or custom UI components.

Custom Element

<formerie-form> renders a form from its public schema, in any framework or plain HTML:

<script type="module">
  import "@formerie/client/element";
</script>

<formerie-form form="fm_t77txbvg43nmar"></formerie-form>

The form renders in the light DOM, so your site's CSS styles it, and its submit goes straight from the browser, so your site must be in the form's allowed origins. It fires formerie:success and formerie:error, with the response as detail. Add mode="iframe" to show the hosted page instead, with its own branding and steps and no allowed origins to set.

Without a bundler, load dist/browser/formerie-element.js.

In a React TypeScript project, declare the tag once:

import type { FormerieFormAttributes } from "@formerie/client/element";

declare module "react" {
  namespace JSX {
    interface IntrinsicElements {
      "formerie-form": FormerieFormAttributes;
    }
  }
}

Submitting From Your Server

submitFormerieRequest() and submitFormerieFormData() send a form your server received. They move a Turnstile or reCAPTCHA token out of the answers and into verificationToken, and send the page's Origin with it, because the server compares the token's hostname with Origin. A form with verification therefore needs your site in its allowed origins. With no token they send no Origin, so no allowed origins are needed.

Your server sends the request, so every visitor shares your server's address. The default limit of 30 submissions per visitor every 10 minutes then applies to all of them together. Raise it, or use a deviceToken rate limit and pass metadata: { deviceToken } for each visitor.

With a server key, pass apiKey, from a secret on your server, and visitorIp. They work only on a server: anywhere with a page they throw and send nothing. See Server keys.

Two Languages On One Form

<FormerieForm form="fm_t77txbvg43nmar" locale="fr-CA" />

The server picks the closest language the form offers. Change locale, or call setLocale() on the controller, and the visitor's answers stay. On a server, pass locale to whatever draws the form, since a server can't read <html lang>. In a browser with nothing from a server, the form goes by <html lang>. See Forms in two languages.

Changelog

See CHANGELOG.md for public release notes across the Formerie JavaScript SDK packages.

Install

npm install @formerie/client
pnpm add @formerie/client
yarn add @formerie/client
bun add @formerie/client

Use the same package-manager command shape for framework adapters:

npm install @formerie/react
npm install @formerie/vue
npm install @formerie/svelte
npm install @formerie/astro
npm install @formerie/next
npm install @formerie/nuxt
npm install @formerie/react-router

API Usage

import { FormerieClient } from "@formerie/client";

const forms = new FormerieClient();

const result = await forms.submit("fm_t77txbvg43nmar", {
  fields: {
    name: "Jane Example",
    email: "[email protected]",
    message: "Hello",
  },
  verificationToken: captchaToken,
});

FormerieClient defaults to https://forms.formerie.com, where a form's address is its ID.

Runtime Usage

Use FormerieClient for hosted runtime routes on forms.formerie.com or verified customer hostnames.

Default Formerie runtime host:

import { FormerieClient } from "@formerie/client";

const forms = new FormerieClient();

const hostedUrl = forms.hostedUrl("fm_t77txbvg43nmar");
const embedScriptUrl = forms.embedScriptUrl();

await forms.submit("fm_t77txbvg43nmar", {
  fields: {
    email: "[email protected]",
  },
});

Sending through your own verified hostname takes the same ID:

const forms = new FormerieClient({
  endpoint: "https://forms.customer.com",
});

await forms.submit("fm_t77txbvg43nmar", {
  fields: {
    email: "[email protected]",
  },
});

Schema And Form Helpers

The SDK includes small runtime helpers for custom renderers, native forms, and framework integrations. These helpers are for display, payload shaping, and error presentation; the Formerie runtime API remains authoritative for visibility enforcement, validation, spam checks, routing, and delivery.

Use describeFormerieRenderModel when you want to build your own renderer from a public schema while keeping Formerie's public field metadata, visibility, and step grouping in one place:

import {
  describeFormerieRenderModel,
  FormerieClient,
} from "@formerie/client";

const forms = new FormerieClient();
const schema = await forms.schema("fm_t77txbvg43nmar");

if (schema.ok) {
  const renderModel = describeFormerieRenderModel(schema, {
    preferredContactMethod: "email",
  });

  for (const field of renderModel.fields) {
    console.log(field.path, field.control, field.visibility);
  }
}

The render model exposes fields, fieldsByPath, public steps, and unsteppedFields. Field descriptors include safe browser metadata such as labels, descriptions, placeholders, options, input types, input modes, constraints, names, current values, and visibility state.

import {
  FormerieClient,
  createFormerieSubmitPayload,
  evaluatePublicFieldVisibility,
  listPublicSchemaFields,
  validationMessagesByField,
} from "@formerie/client";

const forms = new FormerieClient();
const schema = await forms.schema("fm_t77txbvg43nmar");

if (schema.ok) {
  const fields = listPublicSchemaFields(schema);
  const visibility = evaluatePublicFieldVisibility(schema, {
    preferredContactMethod: "email",
  });
}

const formElement = document.querySelector<HTMLFormElement>("form");
if (!formElement) {
  throw new Error("Form is not ready.");
}

const payload = createFormerieSubmitPayload(new FormData(formElement), {
  schema: schema.ok ? schema : undefined,
  verificationToken: captchaToken,
});

const result = await forms.submit("fm_t77txbvg43nmar", payload);
const messages = validationMessagesByField(result);

For a plain browser mount, let the SDK load the public schema and submit through the runtime client:

import {
  FormerieClient,
  mountFormerieRuntimeForm,
} from "@formerie/client";

const forms = new FormerieClient();

await mountFormerieRuntimeForm("#contact-form", {
  client: forms,
  target: {
    form: "fm_t77txbvg43nmar",
  },
  resetOnSuccess: true,
});

mountFormerieRuntimeForm loads the public schema for the selected runtime target, renders public schema fields, preserves public steps and object groups as fieldsets, keeps public visibility rules in sync as answers change, disables hidden controls so they stay out of submit payloads, renders public verification hooks when the schema requires them, loads the browser verification provider script, shapes submit payloads, disables the submit button while requests are pending, and displays server validation errors. If your app already has a schema, use mountFormerieForm directly. If your page already renders a <form data-formerie-form> shell, use bindFormerieForm to attach the same submit, validation, status, verification token collection, and visibility behavior without replacing the existing HTML. Server-rendered pages that include a public schema JSON script can use bindFormerieHostedForm() as the one-call version for existing HTML; it reads <script type="application/json" data-formerie-schema> and binds the rendered form. Generated hosted shells can call mountFormerieForm() with the same public schema plus a backend-owned submitUrl. These helpers collect Turnstile/reCAPTCHA response tokens from browser-safe verification attributes, reset widgets after submit attempts, and can add a safe pageUrl containing only the current origin and path (never query parameters or fragments). They can submit through an explicit submitUrl or a rendered data-formerie-submit-path attribute. Use syncFormerieFormVisibility when building a custom renderer around Formerie data attributes. Use collectFormerieVerificationToken, applyFormerieVerificationError, and resetFormerieVerificationWidget when a custom renderer wants to own verification UI directly. Use renderFormerieVerificationHtml when a custom hosted page needs browser-safe Turnstile or reCAPTCHA widget markup from the public schema. Generated form shells accept public render options for heading output, CSS class hooks, and an optional honeypot field when your server is configured to check one. Pass an explicit verificationToken provider only when your custom UI does not expose the standard Formerie verification attributes and response fields. The public schema includes only browser-safe verification data such as the provider and site key. Final validation, spam checks, verification, delivery, and acceptance stay with the Formerie runtime API.

CDN Usage

The package publishes browser bundles in dist/browser. Browser snippets can load Formerie from immutable Formerie CDN URLs or from npm CDNs such as jsDelivr.

Classic script tag:

<script src="https://cdn.formerie.com/client/v0.1.0-alpha.15/formerie.iife.js"></script>
<script>
  const forms = new Formerie.FormerieClient({
    endpoint: "https://forms.customer.com",
  });

  forms.submit("fm_t77txbvg43nmar", {
    fields: {
      email: "[email protected]",
    },
  });
</script>

Browser ESM:

<script type="module">
  import { FormerieClient } from "https://cdn.formerie.com/client/v0.1.0-alpha.15/formerie.es.js";

  const forms = new FormerieClient({
    endpoint: "https://forms.customer.com",
  });
</script>

Custom iframe mount:

<script src="https://cdn.formerie.com/client/v0.1.0-alpha.15/formerie.iife.js"></script>
<div id="contact-frame"></div>
<script>
  Formerie.mountFormerieEmbed({
    endpoint: "https://forms.customer.com",
    form: "fm_t77txbvg43nmar",
    target: "#contact-frame",
  });
</script>

Formerie.mountFormerieEmbed(...) reads the same public data-formerie-form, data-formerie-target, data-formerie-title, and data-formerie-height attributes used by Formerie runtime embed scripts when it receives a script element.

Pinned snippets should use immutable versioned paths:

<script src="https://cdn.formerie.com/client/vX.Y.Z/formerie.iife.js"></script>

The /client/latest/ alias is a moving convenience alias for demos and manual testing. Production pages should pin an immutable versioned path.

npm CDN fallback:

<script src="https://cdn.jsdelivr.net/npm/@formerie/client/dist/browser/formerie.iife.js"></script>

CLI And AI Skills

Installing @formerie/client exposes the formerie CLI command in package-manager scripts and local binary resolution.

pnpm exec formerie ai detect
pnpm exec formerie ai setup

For npm projects:

npm exec -- formerie ai setup

To run the installer without adding the package first:

npx --package @formerie/client formerie ai setup

The CLI can detect supported AI tooling and install the bundled Formerie skill for Codex or Claude Code:

pnpm exec formerie skills install codex
pnpm exec formerie skills install codex --project
pnpm exec formerie skills install codex --path .codex/skills/formerie
pnpm exec formerie skills install claude
pnpm exec formerie skills install claude --project

The installed skill teaches AI coding agents the Formerie security boundary: public clients submit fields, verification tokens, and safe metadata only; recipients, provider credentials, templates, and delivery rules stay server-side.

Framework Examples

import { FormerieForm } from "@formerie/react"; // Also @formerie/next and @formerie/react-router

<FormerieForm form="fm_t77txbvg43nmar" />
<script setup>
import { FormerieForm } from "@formerie/vue"; // Auto-imported with the @formerie/nuxt/module module
</script>

<template><FormerieForm form="fm_t77txbvg43nmar" /></template>
<script>
  import { FormerieForm } from "@formerie/svelte";
</script>

<FormerieForm form="fm_t77txbvg43nmar" />
import { FormerieForm } from "@formerie/solid";

<FormerieForm form="fm_t77txbvg43nmar" />
import { FORMERIE_COMPONENTS } from "@formerie/angular";

@Component({ imports: [FORMERIE_COMPONENTS], template: `<formerie-form form="fm_t77txbvg43nmar" />` })
export class ContactPage {}
---
import FormerieForm from "@formerie/astro/FormerieForm.astro";
---

<FormerieForm form="fm_t77txbvg43nmar" />

Each package's README shows replacing a part of the form, and keeping your own markup.

---
import { createFormerieFormAttributes } from "@formerie/astro";

const attrs = createFormerieFormAttributes({
  form: "fm_t77txbvg43nmar",
});
---

<form {...attrs}>
  <input name="email" type="email" />
</form>

License

MIT.

版本与发布记录

@formerie/client 共发布 14 个版本,首次发布于 2026/06/26;过去 12 个月发布了 14 个版本。

版本发布日期距今
0.1.0-alpha.15latest2026/11/0312 天前
0.1.0-alpha.142026/11/0312 天前
0.1.0-alpha.132026/11/0313 天前
0.1.0-alpha.122026/11/0313 天前
0.1.0-alpha.112026/11/0313 天前
0.1.0-alpha.102026/11/0213 天前

其他发布通道:alpha → 0.1.0-alpha.9。

关于 @formerie/client 的常见问题

@formerie/client 是什么?

JavaScript and TypeScript client helpers for the Formerie public API and runtime.

如何安装 @formerie/client?

在项目目录运行 npm install @formerie/client,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 formerie,可以用 npx formerie 直接运行。

@formerie/client 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@formerie/client 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@formerie/client 可以商用吗?

@formerie/client 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@formerie/client 的下载量有多少?

根据 npm 官方下载统计,@formerie/client 在 2026/10/16 – 2026/11/14 这 30 天内被下载 2,808 次,日均约 94 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@formerie/client 还在维护吗?

最新版本 0.1.0-alpha.15 发布于 2026/11/03(12 天前);至今共发布 14 个版本,其中过去 12 个月发布了 14 个;首次发布于 2026/06/26。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。