Getting started

A working form in a few explicit steps

Demetria renders into a target you own. It does not ship styles, manage a server, or require a component framework.

Install

npm install demetria

The package is ESM-only and includes TypeScript declarations. Production code has zero runtime dependencies.

Create a form

Add a mount point to the page:

<div id="signup-form"></div>
<script type="module" src="./app.js"></script>

Then define a schema and mount it:

import { createForm } from 'demetria';

const form = createForm({
  target: '#signup-form',
  schema: {
    id: 'signup',
    steps: [
      {
        id: 'contact',
        title: 'Contact details',
        fields: [
          {
            name: 'fullName',
            type: 'text',
            label: 'Full name',
            required: true
          },
          {
            name: 'email',
            type: 'email',
            label: 'Email',
            description: 'Optional, but validated when provided.'
          }
        ]
      }
    ]
  },
  onComplete(values) {
    console.log(values);
  }
});

form.mount();

Required is opt-in. A field is required only when required: true. Omitting it has the same behavior as required: false.

Use the lifecycle

createForm returns an instance with mount(), destroy(), getState(), getValues(), setValue(), next(), and previous(). User navigation is already wired to rendered buttons.

const values = form.getValues();
const state = form.getState();

// Completion is normally handled by the onComplete callback.
console.log(values, state.currentStepId);

For a multi-page flow, use onStepChange to navigate to another document and restore values there. The persistence guide covers the storage boundary and security implications.

Next steps