Start here
Getting started
By the end of this page you will have a form built visually, rendered in your framework, and validated on your server — all from the same file. It takes one install and about twenty lines of code.
Install
Section titled “Install”Pick the package matching your app. The framework wrappers pull in the Web Components and the core transitively.
npm install @streamline-pulse/formkrafter-reactbun add @streamline-pulse/formkrafter-reactpnpm add @streamline-pulse/formkrafter-reactyarn add @streamline-pulse/formkrafter-reactnpm install @streamline-pulse/formkrafter-vuebun add @streamline-pulse/formkrafter-vuepnpm add @streamline-pulse/formkrafter-vueyarn add @streamline-pulse/formkrafter-vuenpm install @streamline-pulse/formkrafter-wcbun add @streamline-pulse/formkrafter-wcpnpm add @streamline-pulse/formkrafter-wcyarn add @streamline-pulse/formkrafter-wcBuild and render a form
Section titled “Build and render a form”The builder produces a spec; the renderer consumes it. Wiring the two together is the whole integration:
-
Mount the builder and keep the spec it emits. Every edit fires
specChangewith the new spec — plus the RFC 6902 patches that produced it, if you want undo/redo or an audit trail. -
Feed that spec to the renderer. It is plain JSON: store it, version it, fetch it back later.
-
Import the stylesheet once. It is opt-in and about 6 KB — skip it and style the
.fk-*classes yourself if you prefer.
import { useState } from 'react'import { FkFormBuilder, FkFormRender } from '@streamline-pulse/formkrafter-react'import '@streamline-pulse/formkrafter-wc/styles.css'import type { BrickSpec } from '@streamline-pulse/formkrafter-core'
export function FormStudio() { const [spec, setSpec] = useState<BrickSpec>()
return ( <> <FkFormBuilder onSpecChange={(e) => setSpec(e.detail.spec)} />
{spec && ( <FkFormRender spec={spec} onFormSubmit={(e) => console.log(e.detail.data)} /> )} </> )}<script setup lang="ts">import { ref } from 'vue'import { FkFormBuilder, FkFormRender } from '@streamline-pulse/formkrafter-vue'import '@streamline-pulse/formkrafter-wc/styles.css'import type { BrickSpec } from '@streamline-pulse/formkrafter-core'
const spec = ref<BrickSpec>()
function onSubmit(data: Record<string, unknown>) { console.log(data)}</script>
<template> <FkFormBuilder @spec-change="spec = $event.detail.spec" />
<FkFormRender v-if="spec" :spec="spec" @form-submit="onSubmit($event.detail.data)" /></template><fk-form-builder></fk-form-builder><fk-form-render></fk-form-render>
<script type="module"> import '@streamline-pulse/formkrafter-wc/dist/formkrafter-wc/formkrafter-wc.esm.js' import '@streamline-pulse/formkrafter-wc/styles.css'
const builder = document.querySelector('fk-form-builder') const preview = document.querySelector('fk-form-render')
builder.addEventListener('specChange', (e) => { preview.spec = e.detail.spec })
preview.addEventListener('formSubmit', (e) => { console.log(e.detail.data) })</script>Validate on the server
Section titled “Validate on the server”The browser verdict is a convenience for your users; the server verdict is the one that counts. Both come from the same spec:
import { validateFormData } from '@streamline-pulse/formkrafter-core'import type { BrickSpec } from '@streamline-pulse/formkrafter-core'
export async function submit(spec: BrickSpec, payload: unknown) { const { valid, errors } = validateFormData(spec, payload, 'en')
if (!valid) { // { fullName: 'This field is required', 'contacts[0].email': 'Invalid email' } return { status: 422, errors } }
return { status: 200, data: payload }}Next steps
Section titled “Next steps”A project by Streamline Pulse