DynoStaticAdmin sign in
Documentation

Website forms

Website-rendered forms

Contact-form widgets support two delivery modes. Embedded forms continue to use DynoStatic's submission handling. Website Worker forms publish a credential-free definition for a website that owns rendering, spam protection and email delivery.

Select Website Worker in the widget builder, save, then edit the fields, choices, required flags and feedback text. Select the email field to use for reply-to and the name field for notifications. The website retains its design and transport configuration. This mode hides CMS inbox, notification and appearance controls that would not affect the website.

Publishing a widget writes its definition and source text in one database transaction. Saving a draft has no effect on the Content API. The preview is disabled and cannot submit into DynoStatic's inbox. Paused, deleted, unpublished and embedded-mode widgets cannot be fetched as website forms.

Languages and publishing

The form has one source language and optional target languages. Field identifiers, choice values and validation rules are shared; labels, placeholders, help, choice captions and feedback text are translated. Use stable-value | Visible caption for choices. Renaming a caption then preserves existing integration values.

The builder follows the website's Pages language settings automatically. It shows language names and a link to manage the website's translation workflow instead of asking for a separate list of codes. For source-managed Pages, the form uses that policy's source and target languages; otherwise it uses the Pages collection's declared languages. The configured page collection in Site publishing is used, including headless collections without DynoStatic routes.

Language changes apply on the next form save and publication. A stale editor must reload if the website's languages changed. An existing published form's source language cannot be relabelled automatically: align the form and Pages source languages before saving. Saving a draft leaves the published form and its translations unchanged. Without a Pages collection, source-language selection and translation checkboxes remain available under Form languages.

Programmatic imports retain explicit form_source_locale and form_target_locales configuration for compatibility. The published definition always contains a resolved language snapshot; builds never reinterpret old publications against newer website settings. Translation checkbox submissions normalize to the existing stored configuration, so no data migration is needed.

The Translation updates link uses the existing source-managed export/import workflow. Export the queued batch, fill only its translation values manually or using AI, then import it. Import validates identifiers, source revision, placeholders, plain text and nonempty translations atomically. It refuses stale results and changed replays. Visitor answers are never translated.

Changing the source creates translation refresh requests. Every configured language must be complete for a website build to fetch the new form. Until then, cms.form returns HTTP 409 form_translations_pending; the build must fail and leave the previous deployment serving. Imported translation publications use the normal content-publication webhooks. The website's build hook must subscribe to those events.

Language-set changes create a new managed translation catalog. Existing published CMS schemas and history remain intact; obsolete pending requests are superseded. Form rollback refreshes the appropriate catalog. Managed form source entries are read-only in Content; edit their widget instead. Target entries use the normal source-managed translation controls.

This reuses manual and AI-assisted batch translation. It does not configure an external translation provider. Future provider adapters can fulfill the same queued requests without changing the website contract.

Website contract

Fetch with the website's private content:read token during the build:

GET /api/?action=cms.form&id=FORM_WIDGET_ULID
Authorization: Bearer PRIVATE_BUILD_TOKEN

The response has format dynostatic.site-form, version 1, the widget ID/revision, an opaque complete-publication revision, locale list, ordered fields, reply-to/name roles and locale text maps. Responses are scoped to the token's website and marked private, no-store. They contain no draft content, mail credentials or Turnstile secrets.

Bundle the same response into the static frontend and submission handler. Render translated text as text, never raw HTML. Send the bundled revision with submissions. Validate the revision, allowlisted fields, types, required flags, choice values and lengths on the server before verifying Turnstile and sending email. Return stale_form for an older browser tab and ask the visitor to reload. Do not use a local seed as a production fallback. A website with multiple content fetches should compare complete captures before building to detect publication changes during synchronization.

The dependency-free JavaScript example provides definition admission, submission validation and source-language notification labels. Transport, anti-spam and rate limits remain the website's responsibility. It is a reusable adapter, not a second hosted form backend.

Version 1 supports text, email, telephone, URL, number, date, time, datetime, textarea, dropdown, radio, checkbox and plain-text section fields. Limits: 80 fields, 40 options per choice field, 31 target languages. Uploads, arbitrary HTML, hidden/default fields, conditional rules, multiple steps and CMS email/redirect delivery are explicitly rejected.

No database migration is required: managed text uses existing CMS schema, entry, translation, revision and outbox tables. Runtime classes are included in the release allowlist.