# Architecture (https://form.dimah.dev/docs/architecture)



The library owns the protocol, definition snapshots, and submit validation. Your app owns widgets, auth, and the database adapter. Those four boundaries are the architecture.

***

## Principles [#principles]

<Cards>
  <Card title="Headless by Design" description="No widgets, CSS, or component registry. Render fields with the design system you already have." />

  <Card title="Snapshot Invariant" description="A fill freezes the definition at start. Editing the live form does not break in-flight drafts." />

  <Card title="Protocol Single Source of Truth" description="@dimah-form/core defines all routes, payloads, and validators. Server and client never drift." />

  <Card title="Zero-ORM Server Engine" description="@dimah-form/server has no database dependencies. Storage is abstracted through the ResponseStore interface." />
</Cards>

***

## System Flow [#system-flow]

The diagram shows how widgets, HTTP routes, `guard`, validation, and the store fit together:

<ArchitectureDiagram />

<Accordions>
  <Accordion title="View Mermaid Diagram">
    ```mermaid
    flowchart TD
      subgraph Client ["Browser / React App"]
        UI["Your UI Widgets / Stepper"] --> Hook["useFormResponse"]
        Hook --> HTTPClient["createFormClient"]
      end

      subgraph Server ["Backend Runtime (@dimah-form/server)"]
        HTTPClient --> Route["HTTP Handler (Next.js / Hono / Express)"]
        Route --> Guard["guard ({ request, operation, ... })"]
        Guard --> Engine["dimahForm() Router"]
        Engine --> SnapshotVal["Validate vs response.definition Snapshot"]
        SnapshotVal --> PreHooks["on* Pre-Write Lifecycle Hooks"]
      end

      subgraph Storage ["Persistence (ResponseStore)"]
        PreHooks --> Store["memoryAdapter, db, or custom"]
        Store --> Tables[("questionnaire & response rows")]
        Store --> PostHooks["after* Post-Write Lifecycle Hooks"]
      end

      LiveDoc["Code Forms / DB Form"] -.->|"freezes snapshot at start"| Tables
    ```
  </Accordion>
</Accordions>

***

## Package Boundaries [#package-boundaries]

Each package has one job and a one-way dependency graph:

| Package                  | Environment | Responsibility                                                                                         | Key Exports                                                             |
| :----------------------- | :---------- | :----------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------- |
| **`@dimah-form/core`**   | Universal   | Protocol SSOT, Zod schemas, field definitions, answer validation, error codes, and type inference.     | `defineForm`, `defineFieldType`, `APIError`, `FORM_ERROR_CODES`         |
| **`@dimah-form/server`** | Server      | Backend router, HTTP framework adapters, `form.api`, lifecycle hook dispatcher, and `memoryAdapter()`. | `dimahForm()`, `toNextJsHandler`, `toHonoHandler`, `memoryAdapter`      |
| **`@dimah-form/react`**  | Browser     | Headless React client, session state machine, visibility resolver, field bindings, and autosave.       | `createFormClient()`, `useFormResponse()`, `fieldLabel`, `fieldOptions` |
| **`@dimah-form/db`**     | Server      | Optional. Production SQL adapter using FumaDB for Drizzle, Prisma, and Kysely.                         | `DimahFormDB`, `db()`                                                   |

***

## Request Pipeline [#request-pipeline]

Every mutation and query runs the same six stages:

<Flow
  label="Execution Lifecycle"
  steps="[
  { name: &#x22;1. Parse&#x22;, kind: &#x22;protocol&#x22;, note: &#x22;Zod query / body check&#x22; },
  { name: &#x22;2. Guard&#x22;, kind: &#x22;server&#x22;, note: &#x22;Auth & permissions&#x22; },
  { name: &#x22;3. Validate&#x22;, kind: &#x22;protocol&#x22;, note: &#x22;Against snapshot&#x22; },
  { name: &#x22;4. on* Hook&#x22;, kind: &#x22;server&#x22;, note: &#x22;Pre-write mutation&#x22; },
  { name: &#x22;5. Persist&#x22;, kind: &#x22;data&#x22;, note: &#x22;Store write & CAS&#x22; },
  { name: &#x22;6. after* Hook&#x22;, kind: &#x22;server&#x22;, note: &#x22;Side-effects&#x22; },
]"
/>

### 1. Inbound Parse & Schema Validation [#1-inbound-parse--schema-validation]

The HTTP adapter parses the incoming HTTP request and validates query parameters or body payloads against the Zod schemas defined in `@dimah-form/core`. Malformed requests immediately return `400 VALIDATION_ERROR`.

### 2. Security Guard [#2-security-guard]

The optional `guard` hook executes before any database or form logic. You inspect the `request`, `operation`, `formId`, or `responseId`, verify user session cookies/tokens, and enforce permissions. Throwing an `APIError` halts execution and sends a structured error response.

### 3. Snapshot Validation [#3-snapshot-validation]

When saving drafts or submitting responses, answer values are validated **against the frozen `response.definition` snapshot**, never against the live form schema. Submitting verifies that all visible required fields are populated and valid. Hidden fields (per `showWhen`) are automatically stripped.

### 4. Pre-Write Hooks (`on*`) [#4-pre-write-hooks-on]

Pre-persistence hooks (such as `onStart`, `onDraft`, `onSubmit`) run before the database transaction. You can attach user identifiers (`response.respondentId = user.id`) or enrich metadata directly on the in-memory record.

### 5. Persistence & Optimistic Concurrency (CAS) [#5-persistence--optimistic-concurrency-cas]

The `ResponseStore` writes the record to the database. If an `expectedUpdatedAt` timestamp was provided, the store verifies that the row has not been modified by another client in the meantime. If the timestamp differs, a `STALE_UPDATE` (409) conflict is raised.

### 6. Post-Write Hooks (`after*`) [#6-post-write-hooks-after]

After the database write successfully commits, post-persistence hooks (such as `afterSubmit`, `afterDraft`) trigger side-effects, such as sending confirmation emails, posting webhooks, or enqueuing background worker jobs.

***

## Next Steps [#next-steps]

<Cards>
  <Card title="Snapshots" href="/docs/snapshots" description="Learn how snapshots ensure schema immutability and handle draft lifecycles." />

  <Card title="Forms" href="/docs/forms" description="Author schemas with defineForm, configure field types, and enable $Infer." />

  <Card title="React Client" href="/docs/react" description="Deep dive into useFormResponse, visible fields, and draft actions." />

  <Card title="Server" href="/docs/server" description="Mount HTTP adapters across Next.js, Hono, Express, Fastify, and SvelteKit." />
</Cards>
