This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Formeo is a zero-dependency, highly configurable drag-and-drop form builder library. It provides two main classes:
- FormeoEditor: Visual form building interface with drag-and-drop capabilities
- FormeoRenderer: Renders form definitions into functional HTML forms
The library is framework-agnostic and provides TypeScript definitions. It's distributed as UMD, ES, and CommonJS modules.
npm start # Build icons and start dev server at http://localhost:5173
npm run dev # Start dev server only
npm run build # Build library and demo (runs build:lib first)
npm run build:lib # Build library for distribution (both minified and unminified)npm test # Run unit tests with Node.js native test runner
npm run test:watch # Run tests in watch mode
npm run test:updateSnapshots # Update test snapshots
npm run playwright:test # Run e2e tests
npm run playwright:test:ui # Run e2e tests with browser UI
npm run playwright:test:report # View Playwright test reportnpm run lint # Lint with Biome
npm run lint:fix # Lint and auto-fix issues
npm run format # Format code with Biomenpm run preview # Preview production build locally
npm run build:icons # Generate SVG sprite from iconsFormeo uses a hierarchical component system with four core levels:
- Stage → top-level container (equivalent to a form/page)
- Row → horizontal sections within a stage
- Column → vertical divisions within a row (enables multi-column layouts)
- Field → individual form controls (input, select, textarea, etc.)
Each component type is managed by dedicated data classes in /src/lib/js/components/:
stages/index.js- StagesDatarows/index.js- RowsDatacolumns/index.js- ColumnsDatafields/index.js- FieldsData
All components extend the base Component class (/src/lib/js/components/component.js), which provides:
- Event system with
addEventListener/removeEventListener - Data management via
get/setmethods - DOM rendering with
render()method - Address-based component lookup (e.g.,
stages.abc-123.rows)
FormData Structure: The canonical form definition is a flat structure with components keyed by ID:
{
id: "form-id",
stages: { "stage-id": { id: "stage-id", attrs: {}, children: ["row-id-1"] } },
rows: { "row-id-1": { id: "row-id-1", children: ["col-id-1"] } },
columns: { "col-id-1": { id: "col-id-1", children: ["field-id-1"] } },
fields: { "field-id-1": { id: "field-id-1", tag: "input", attrs: { type: "text" } } }
}Address System: Components are accessed via dot-notation addresses: stages.{id}.rows or fields.{id}.attrs.label. See splitAddress() in /src/lib/js/common/utils/string.mjs.
Components Singleton: The /src/lib/js/components/index.js exports a singleton Components instance that acts as the central data store. Access it via:
Components.get(type, id)- Get component instanceComponents.getAddress('stages.abc-123')- Get component by addressComponents.formData- Get complete form definition
DOM Utilities (/src/lib/js/common/dom.js):
dom.render(data, tag)- Render data to DOM elementsdom.create({tag, content, attributes})- Create DOM elementsdom.empty(element)- Remove all children- Extensive DOM manipulation helpers
Events System (/src/lib/js/common/events.js):
- Global event bus for component communication
- Component-level events via
Component.addEventListener() - Supports bubbling and custom event data
Actions System (/src/lib/js/common/actions.js):
- Handles user actions (add, remove, clone, edit components)
- Integrates with undo/redo if enabled
Controls (/src/lib/js/components/controls/index.js):
- Extensible control registry for form field types
- Each control type (input, select, textarea, etc.) is defined in
/src/lib/js/components/controls/form/ - Custom controls can be registered via the
controlsconfig option
Edit Panel (/src/lib/js/components/edit-panel/edit-panel.js):
- Sidebar for editing component properties
- Auto-generates edit forms based on control metadata
The FormeoRenderer class (/src/lib/js/renderer/index.js) converts formData into rendered HTML forms:
- Processes conditional logic (show/hide fields based on conditions)
- Handles field attributes, validation, and user data
- Exposes
userDatagetter/setter for form values - Completely separate from editor code (no shared DOM dependencies)
- Formatting: Use Biome (line width 120, single quotes, 2 spaces)
- Module System: ES modules (
.jsand.mjsfiles). Use.mjsfor pure utility modules without DOM dependencies - Imports: Relative paths required, import order enforced by Biome
- Naming: camelCase for variables/functions, PascalCase for classes
- Constants: UPPER_SNAKE_CASE in
/src/lib/js/constants.js - Testing: Use Node.js native test runner with snapshot support
- Commits: Conventional commits enforced (types: feat, fix, chore, docs, style, refactor, test, build, ci, perf, revert)
- Circular Dependencies: Be aware that
Componentshas circular imports with individual component types. The/src/lib/js/components/index.jscarefully manages this with lazy loading. - Event System: Components can define events in their config that fire during lifecycle (onCreate, onRender, onRemove). The Events module in
/src/lib/js/common/events.jscoordinates these. - Internationalization: Uses
@draggable/i18npackage. Language files loaded from CDN by default. See/src/lib/js/config.jsfor i18n config. - Icons: SVG sprite generated at build time from
/src/lib/icons/. Icon references use the pattern#formeo-sprite-{icon-name}. - SessionStorage: Editor can persist formData to sessionStorage. Controlled by
sessionStorageoption. - TypeScript: No TypeScript source files, but type definitions should be maintained for consumers.
Lefthook is configured with:
- pre-commit: Runs Biome linting/formatting on staged files
- pre-push: Runs full test suite
- commit-msg: Validates conventional commit format
The build process produces:
dist/formeo.es.js- ES moduledist/formeo.cjs.js- CommonJS moduledist/formeo.umd.js- UMD bundle (unpkg default)dist/formeo.min.*.js- Minified versionsdist/formeo.min.css- Compiled stylesdist/formeo-sprite.svg- Icon spritedist/formData_schema.json- JSON Schema for form data validation
- Semantic Release: Automated versioning and publishing to npm on main branch
- GitHub Actions: Playwright tests run on PRs, deploy to GitHub Pages on publish
- Conventional Commits: Required for proper semantic versioning
src/
├── lib/ # Core library source
│ ├── js/
│ │ ├── editor.js # FormeoEditor main class
│ │ ├── renderer/ # FormeoRenderer implementation
│ │ ├── components/ # Component hierarchy (stages/rows/columns/fields)
│ │ ├── common/ # Shared utilities (dom, events, actions)
│ │ ├── config.js # Default configuration
│ │ └── constants.js # Global constants
│ ├── sass/ # Styles
│ └── icons/ # SVG icons for sprite generation
└── demo/ # Demo site source
tools/ # Build and development utilities
dist/ # Build output (gitignored)
docs/ # Documentation