Skip to Content
SdkForms

Forms

Vard Forms are initialized in code using the SDK. Once a form is registered, it appears in the Vard dashboard where clients can customize fields, reorder them, update labels, and configure submit behavior — no redeployments required.

The developer owns the form’s existence. The client owns its content.

How it works

  1. The developer registers a form in their codebase using the SDK (see embed options below). This creates the form and gives it a stable ID.
  2. The form appears in the Vard dashboard under Forms. Clients configure fields, submit settings, and success messages from there.
  3. When the client changes a field label or adds a new field, the live site reflects it within 60 seconds. No git commit. No deploy.

Getting the form ID

After registering a form in code, go to the Vard dashboard under Forms. Each form has a unique ID that looks like f47ac10b-58cc-4372-a567-0e02b2c3d479. Copy it from the embed snippet shown in the table, then use it in your embed.

Embedding the form

There are three ways to embed, depending on your stack. All three use the same form ID and hit the same API.

Script tag — plain HTML, no build step

The simplest option. Works in any HTML page, static site generator, or CMS that lets you add a <script> tag.

contact.html
<script src="https://vard.app/dist/forms.iife.global.js" defer></script> <div data-vard-form="f47ac10b-58cc-4372-a567-0e02b2c3d479"></div>

The script scans for [data-vard-form] elements on DOMContentLoaded and mounts each one automatically. Multiple forms on the same page work — just add multiple data-vard-form divs.

ESM import — bundler-based projects (React, Vue, Svelte, Astro…)

src/contact.ts
import { VardForms } from "@vard-app/sdk/forms"; VardForms.mount("#contact-form", { id: "f47ac10b-58cc-4372-a567-0e02b2c3d479", });
<div id="contact-form"></div>

mount() accepts either a CSS selector string or an HTMLElement reference.

Web component — declarative markup

If you prefer an HTML-first approach, the <vard-form> custom element works in any framework that supports web components (React 19+, Vue, Svelte, Lit, plain HTML).

<vard-form form-id="f47ac10b-58cc-4372-a567-0e02b2c3d479"></vard-form>

Register the custom element before use:

import { VardForms } from "@vard-app/sdk/forms"; VardForms.defineWebComponent();

Or use the script tag build — it registers <vard-form> automatically.

Styling

Forms render into the light DOM using structural class names. Your existing CSS applies directly — no shadow DOM, no CSS-in-JS, no specificity fights.

ClassElement
.vard-formThe <form> element
.vard-fieldWrapper <div> around each field
.vard-field--checkboxWrapper for checkbox fields
.vard-label<label> element
.vard-input<input>, <textarea>, or <select>
.vard-input--checkboxCheckbox <input>
.vard-input--errorAdded to inputs that fail validation
.vard-submitSubmit <button>
.vard-errorPer-field error message <span>
.vard-error--globalForm-level error (e.g. network failure)
.vard-successSuccess message <p> shown after submit

Example using Tailwind:

globals.css
.vard-form { @apply flex flex-col gap-4; } .vard-field { @apply flex flex-col gap-1.5; } .vard-label { @apply text-sm font-medium text-foreground; } .vard-input { @apply rounded-md border border-input bg-background px-3 py-2 text-sm; } .vard-input--error { @apply border-destructive; } .vard-submit { @apply rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground; } .vard-error { @apply text-xs text-destructive; } .vard-success { @apply text-sm text-foreground; }

Framework examples

Next.js (App Router)

Forms are client-side by definition — they need DOM APIs. Use a client component wrapper.

components/contact-form.tsx
"use client"; import { useEffect, useRef } from "react"; import { VardForms } from "@vard-app/sdk/forms"; export function ContactForm({ formId }: { formId: string }) { const ref = useRef<HTMLDivElement>(null); useEffect(() => { if (ref.current) { VardForms.mount(ref.current, { id: formId }); } }, [formId]); return <div ref={ref} />; }
app/contact/page.tsx
import { ContactForm } from "@/components/contact-form"; export default function ContactPage() { return ( <main> <h1>Contact us</h1> <ContactForm formId="f47ac10b-58cc-4372-a567-0e02b2c3d479" /> </main> ); }

Astro

src/pages/contact.astro
--- // No imports needed — script tag handles it --- <html> <body> <h1>Contact us</h1> <div data-vard-form="f47ac10b-58cc-4372-a567-0e02b2c3d479"></div> <script src="https://vard.app/dist/forms.iife.global.js" defer></script> </body> </html>

Vue

ContactForm.vue
<template> <div ref="container" /> </template> <script setup lang="ts"> import { ref, onMounted } from "vue"; import { VardForms } from "@vard-app/sdk/forms"; const props = defineProps<{ formId: string }>(); const container = ref<HTMLElement | null>(null); onMounted(() => { if (container.value) { VardForms.mount(container.value, { id: props.formId }); } }); </script>

Submit behavior

Configure how submissions are handled from the Vard dashboard under the form’s Submit settings:

SettingDescription
Store submissionsAlways on. Every submission is saved and viewable in the dashboard.
Email notificationSend an email to a specified address on each submission.
WebhookPOST submission data as JSON to any URL (Zapier, Make, custom endpoint).
Success messageText shown in place of the form after a successful submit.
Success redirectURL to redirect to instead of showing the success message.

VardForms.mount() options

VardForms.mount(target, { // Required — the form ID from the Vard dashboard id: string; // Optional — override the Vard API host (useful for self-hosting or local dev) apiHost?: string; // Optional — called after the form config is fetched and rendered onSuccess?: (config: FormConfig) => void; // Optional — called if the config fetch fails onError?: (error: Error) => void; })

Field types

Clients can configure any of these field types from the dashboard:

TypeInput rendered
textSingle-line text input
emailEmail input (validated on submit)
phoneTel input
numberNumber input
textareaMulti-line text area (4 rows)
selectDropdown with client-defined options
checkboxSingle checkbox (e.g. “I agree to the privacy policy”)

Validation

Validation runs server-side on every submission. Required fields are enforced, email format is checked, and select values are validated against the configured options. Per-field error messages are returned and displayed inline next to the relevant input.

Client-side HTML5 validation is intentionally disabled (novalidate) so that all error messages come from the server and stay consistent regardless of browser.

Last updated on
Vard SDK Documentation