Project structure
How FieldCraft is organised, what each package does, and how to structure schemas, components and adapters in your own project.
Package architecture
FieldCraft is a monorepo with strict dependency boundaries. Each package depends only on the one beneath it.
@squaredr/fieldcraft-core Zero UI dependencies. Pure TypeScript.
↑
@squaredr/fieldcraft-react Depends on core. React + shadcn + Tailwind.
↑
@squaredr/fieldcraft-pro Depends on core + react. Commercial licence.
@squaredr/fieldcraft-adapters Depends on core types only. No React.
@squaredr/fieldcraft-templates-free Depends on core types only. No React.| Package | What it contains | Size |
|---|---|---|
fieldcraft-core | Schema types, engine factory (createEngine), state manager, condition evaluator, validation runner, expression parser, draft manager, prefill resolver, schema validator | ~15 KB min |
fieldcraft-react | <FormRenderer />, 44 field components, 4 hooks, 6 theme presets, field registry, UI primitives (shadcn/Radix) | ~45 KB min |
fieldcraft-adapters | HTTP adapter, Supabase adapter, Postgres adapter, webhook adapter. Each with encryption, retry logic | ~8 KB min |
fieldcraft-templates-free | 16 production-ready form schemas across 7 categories | ~12 KB min |
fieldcraft-pro | Visual builder, schema editor, theme editor, response viewer (coming soon) | Commercial |
Recommended project structure
your-app/
├── schemas/ # Form schemas (JSON or TypeScript)
│ ├── contact-form.ts
│ ├── patient-intake.ts
│ └── employee-survey.json
├── components/
│ └── forms/
│ ├── custom-fields/ # Custom field type components
│ │ ├── PainScaleField.tsx
│ │ └── ColorPickerField.tsx
│ └── FormPage.tsx # Wrapper component
├── lib/
│ ├── adapters.ts # Adapter configuration
│ ├── validators.ts # Custom validators
│ └── form-registry.ts # Custom field registry
└── app/
└── forms/
└── [id]/
└── page.tsx # Dynamic form routeSchema files
Schemas can be TypeScript files (with type checking) or JSON files (for schemas stored in a database or CMS).
TypeScript — recommended for static schemas:
import type { FormEngineSchema } from '@squaredr/fieldcraft-react'
export const contactFormSchema: FormEngineSchema = {
id: 'contact-form',
version: '1.0.0',
// ... full schema
}JSON — for dynamic schemas loaded from an API:
{
"id": "contact-form",
"version": "1.0.0",
"title": "Contact Us",
"sections": []
}The engine accepts both formats. TypeScript gives you autocomplete and compile-time validation. JSON is useful when schemas are managed through the Pro visual builder or stored in a database.
Adapter setup
Keep adapter configuration in a dedicated file:
import { createHttpAdapter } from '@squaredr/fieldcraft-core'
import { createSupabaseAdapter } from '@squaredr/fieldcraft-adapters'
import { supabase } from './supabase'
export const httpAdapter = createHttpAdapter({
url: '/api/submissions',
method: 'POST',
headers: { 'X-API-Key': process.env.NEXT_PUBLIC_API_KEY! },
})
export const supabaseAdapter = createSupabaseAdapter({
client: supabase,
table: 'form_submissions',
})Then pass adapters to the renderer:
<FormRenderer
schema={schema}
adapters={[httpAdapter, supabaseAdapter]}
/>Multiple adapters run in parallel — if one fails, the others still execute. Each adapter reports its own success/failure in the SubmitResult.
Custom field registry
If you have custom field types, create a registry file:
import { defaultRegistry } from '@squaredr/fieldcraft-react'
import { PainScaleField } from '@/components/forms/custom-fields/PainScaleField'
import { ColorPickerField } from '@/components/forms/custom-fields/ColorPickerField'
export const registry = {
...defaultRegistry,
pain_scale: PainScaleField,
color_picker: ColorPickerField,
}Then pass it to the renderer:
<FormRenderer
schema={schema}
components={registry}
/>Next steps
- Schema anatomy — understand every property in the schema
- Custom field types — build your own field components
- Adapters overview — configure submission targets