Releases
This timeline reads published releases directly from GitHub for the FormForge backend and client repositories.
✨ Highlights
🔒 Reliable read-only rendering
Using :disabled="true" now correctly disables all rendered fields, including composite fields such as address inputs.
🐛 Bug Fixes
- Renderer: apply the global
disabledprop to every rendered field (5675103)
❤️ Contributors
- @EvanSchleret
Full Changelog: https://github.com/EvanSchleret/FormForgeClient/compare/v2.3.0...v2.3.1
✨ Highlights
📦 Configurable file upload constraints
File fields now support accepted types, per-file size limits, maximum file counts, and cumulative size limits.
{
type: 'file',
multiple: true,
accept: ['.pdf', 'image/*'],
max_size: 5_000_000,
max_files: 3,
max_total_size: 10_000_000
}
🧹 Cleaner paginated rendering
Obsolete page titles and descriptions are no longer rendered by FormForgeRenderer, matching the current builder experience.
🚀 Features
- File uploads: add client-side validation for accepted types, file count, per-file size, and cumulative size (
65d4399)
🐛 Bug Fixes
- Renderer: remove obsolete page headings and descriptions from rendered pages (
0af8c55)
❤️ Contributors
- @EvanSchleret
Full Changelog: https://github.com/EvanSchleret/FormForgeClient/compare/v2.2.0...v2.3.0
✨ Highlights
📦 Advanced file upload validation
File fields now support accepted types, maximum file counts, per-file size limits, and cumulative size limits through the DSL and backend validation.
Form::define('documents')
->version('1')
->file('attachments')
->multiple()
->accept(['.pdf', 'image/*'])
->maxSize(5_000_000)
->maxFiles(3)
->maxTotalSize(10_000_000);
🛡️ Optional ClamAV scanning
Managed and staged uploads can be scanned through a remote ClamAV REST service such as ajilaag/clamav-rest, with optional HTTPS Basic Authentication.
FORMFORGE_CLAMAV_ENABLED=true
FORMFORGE_CLAMAV_ENDPOINT=https://clamav.example.com/v2/scan
FORMFORGE_CLAMAV_USERNAME=clamav-client
FORMFORGE_CLAMAV_PASSWORD=secret
FORMFORGE_CLAMAV_TIMEOUT=30
🚀 Features
- Uploads: add file limits and optional ClamAV REST antivirus scanning (
0e52645)
❤️ Contributors
- @EvanSchleret
Full Changelog: https://github.com/EvanSchleret/FormForge/compare/v2.0.0...v2.1.0
✨ Highlights
📄 Single-view renderer mode
FormForgeRenderer now supports pagination="none" to display all visible form fields on a single view.
The default pagination="auto" behavior remains unchanged. In single-view mode, navigation controls and the progress indicator are hidden while validation, payload structure, and conditional rules continue to work as before.
🚀 Features
- Renderer: add
autoandnonepagination modes (0d07d2d)
❤️ Contributors
- @EvanSchleret
Full Changelog: https://github.com/EvanSchleret/FormForgeClient/compare/v2.1.0...v2.2.0
✨ Highlights
🧩 Clearer conditional logic
Conditional rules now support requiring questions in the current block, use clearer labels, provide more consistent deletion controls, and handle empty operators correctly.
🏠 Readable address responses
Address answers are now displayed as readable, comma-separated values instead of raw JSON.
🐛 Bug Fixes
- Conditional logic: allow requiring questions in the current block (
9725d05) - Conditional logic: clarify deletion controls (
ebe78c6) - Conditional logic: clarify conditional rule labels (
8090efb) - Conditional logic: handle empty condition operators correctly (
4f3073c) - Responses: format address answers as readable text (
1a895b6)
❤️ Contributors
- @EvanSchleret
Full Changelog: https://github.com/EvanSchleret/FormForgeClient/compare/v2.0.3...v2.1.0
✨ Highlights
🧩 Safer field type changes
FormForgeBuilder now resets type-specific field state when changing types, preventing stale validation rules and incompatible properties from being carried over.
🧱 Add new blocks from the builder
The builder now includes an Add page action in both layouts. New blocks are created with their first question and automatically selected for editing.
🚀 Features
- Builder: add new blocks/pages directly from the form editor (
a126109)
🐛 Bug Fixes
- Renderer: hide the submit button by default when using
v-model(1435cb5) - Builder: reset field-specific properties when changing field types (
d32cab3)
❤️ Contributors
- @EvanSchleret
Full Changelog: https://github.com/EvanSchleret/FormForgeClient/compare/v2.0.2...v2.0.3
✨ Highlights
🧩 Automatic v-model mode detection
FormForgeRenderer now automatically hides the submit button when used with v-model. The button can still be explicitly re-enabled with :show-submit="true".
🐛 Bug Fixes
- Renderer: hide the submit button by default with
v-modelwhile preserving the default behavior without an external model (1435cb5)
❤️ Contributors
- @EvanSchleret
Full Changelog: [v2.0.1...v2.0.2](https://github.com/EvanSchleret/FormForgeClient/compare/v2.0.1...v2.0.2)
What's Changed
- fix(lang): add missing lang keys by @EvanSchleret in https://github.com/EvanSchleret/FormForgeClient/pull/16
- chore: update deps by @EvanSchleret in https://github.com/EvanSchleret/FormForgeClient/pull/17
Full Changelog: https://github.com/EvanSchleret/FormForgeClient/compare/v2.0.0...v2.0.1
v2.0.0
We are thrilled to announce FormForge v2.0.0, a major release that brings a more reliable, schema-driven foundation to exports, imports, and form resolution.
Added
- Introduced a schema-driven exportable field model for stable CSV template generation, import mapping, and column validation
- Added explicit flattening for composite fields, with
addressexpanded into exportable leaf fields - Added public form resolution by
form_uuid, with deterministic latest-version selection across backend and scoped managers - Expanded runtime APIs and type exports to make the new schema and submission primitives reusable by downstream consumers
Changed
- Export, import, and validation now share one schema-aware source of truth instead of relying on field-to-column assumptions
- Builder and renderer now operate on the same normalized schema shape, keeping defaults, validation, and payload hydration aligned
- External payload alias resolution remains stable for both
nameandfield_key
Tests
- Added coverage for simple fields, composite fields,
addressexpansion, header validation, latest-by-uuid resolution, and Zod/schema normalization
Full Changelog: https://github.com/EvanSchleret/FormForgeClient/compare/v1.2.4...v2.0.0
v2.0.0
We are thrilled to announce FormForge (API) v2.0.0, a major release that strengthens the schema foundation, makes export/import flows reliable, and adds deterministic resolution by form UUID.
Added
- Introduced a stable exportable field model for schema-driven CSV template generation, import mapping, and header validation
- Added explicit flattening for composite fields, with
addressexpanded into exportable leaf fields - Added public form resolution by
form_uuid, with deterministic latest-version selection throughFormManager,ScopedFormManager, andFormDefinitionRepository - Added reusable export/import helper APIs so downstream consumers can rely on the same schema source of truth
Changed
- Export and import flows now share one schema-derived representation instead of assuming one field equals one column
- Composite fields are no longer treated as a single CSV column by default
- Latest-by-UUID resolution now uses stable ordering by
version_number DESCandid DESC - Validation and submission flows continue to use the same normalized schema model
Tests
- Added coverage for simple fields, composite fields,
addressexpansion, header validation, unknown and missing forms, and latest-by-UUID resolution
Full Changelog: https://github.com/EvanSchleret/FormForge/compare/v1.5.2...v2.0.0
v1.2.4
Fixed
FormForgeRendererno longer drops the injectedbeforeRequesthook whenclientConfigis provided- Bearer authentication now remains active when passing renderer-specific overrides such as
scopeParams useFormForgeClientnow preserves the existing injected FormForge client when merging config overrides
Tests
- Added a regression test to verify that
beforeRequestis still executed whenclientConfigoverrides are passed touseFormForgeClient
Full Changelog: https://github.com/EvanSchleret/FormForgeClient/compare/v1.2.3...v1.2.4
v1.2.3
Fixed
FormForgeRenderernow accepts externalmodelValuepayload keys indexed byfield_keyin addition tofield.name- Hydration/sanitation now resolves field aliases (
name+field_key) to one canonical field entry - When both
nameandfield_keyare provided for the same field,nametakes precedence - Unknown payload keys continue to be removed during sanitation
Tests
- Added renderer payload tests for:
name-only hydrationfield_key-only hydration- mixed payload with
nameprecedence - unknown fields rejection
Full Changelog: https://github.com/EvanSchleret/FormForgeClient/compare/v1.2.2...v1.2.3
v1.5.2
Added
- Backend now accepts submission/validation payload keys by canonical
nameandfield_key(default mode:both) - New validation config:
formforge.validation.input_key_modewith:name_onlyfield_key_onlyboth(default)
Changed
- Input key resolution now follows:
- exact
name - fallback exact
field_key
- exact
- When both
nameandfield_keyare provided for the same field,nametakes precedence - Payload sanitization/allowed-fields flow now supports
field_keyinputs through canonical normalization
Error handling
- Explicit conflict error when multiple aliases target the same field in a conflicting way
- Unknown field behavior unchanged (
reject_unknown_fieldsstill applies as before)
Tests
- Added/updated coverage for:
name-only payloadfield_key-only payload- mixed
name + field_keypayload - collision/conflict scenarios
- unknown field rejection compatibility
Full Changelog: https://github.com/EvanSchleret/FormForge/compare/v1.5.1...v1.5.2
v1.2.1
Changed
- Refactored
useFormForgeManagementlist APIs to return contextual list results:listForms(...)now returns{ data, refresh }listFormRoute(...)now returns{ data, refresh }
refresh()on the returned list result now reliably re-runs the same original request context (endpoint, scope, filters, and route key when applicable).
Fixed
- Fixed ambiguity where global
management.refresh()could refresh a different list source than the one previously loaded (for example falling back to/formsafter loading/form-routes/{key}).
Compatibility
- Existing reactive state (
management.forms) remains available for current integrations. - Global
refreshForms()/refresh()is kept as a fallback, while per-resultrefresh()is now the recommended pattern.
Full Changelog: https://github.com/EvanSchleret/FormForgeClient/compare/v1.2.0...v1.2.1
v1.5.1
Fixed
- Added support for filtering form query routes by linked category slug using
field: "category_slug". - Resolved mismatch where
categoryfiltering targeted stored category reference (key) and could not match category slug values.
Added
- New
category_slugfield support inhttp.query_routes.forms.wherepredicates. - Feature test coverage for form query route filtering by category slug.
Full Changelog: https://github.com/EvanSchleret/FormForge/compare/v1.5.0...v1.5.1
v1.2.0
Added
- Added client API methods:
listFormRoute(routeKey, options?)listCategoryRoute(routeKey, query?, options?)
- Added management composable support:
useFormForgeManagement().listFormRoute(...)
- Added category composable support:
useFormForgeCategory().listCategoryRoute(...)categoryRouteKeyoption for initial loading behavior
- Added UI integration props:
FormForgeBuilder:formRouteKeycategoryRouteKey
FormForgeCategoryCreateModal:categoryRouteKey
Changed
- Builder can now preload a form from a configured form route when
loadFormKeyis not provided. - Category loading in builder/modal can be aligned with backend
category-routesdefinitions.
Documentation
- Added dedicated backend documentation page for query routes.
- Updated management/composables/component docs to include query route usage.
Full Changelog: https://github.com/EvanSchleret/FormForgeClient/compare/v1.1.3...v1.2.0
v1.5.0
Added
- Introduced
http.query_routesconfiguration for reusable, named query routes. - Added new management endpoints:
GET /form-routes/{routeKey}GET /category-routes/{routeKey}
- Enabled scoped and non-scoped support for query routes.
- Added nested predicate DSL with logical groups:
all(AND)any(OR)
- Added rich operators:
eq,neq,gt,gte,lt,ltein,not_incontains,starts_with,ends_withis_null,not_nullbetween
- Added aggregate filtering support:
responses_countfor form routesforms_countfor category routes
Changed
- HTTP route listing command now includes query route endpoints.
- Authorization action map and base policy now include:
management.form_routemanagement.category_route
Tests
- Added feature coverage for form route resolution and category route resolution.
Full Changelog: https://github.com/EvanSchleret/FormForge/compare/v1.4.0...v1.5.0
v1.4.0
Added
- Runtime locale resolution for backend validation flows:
- explicit method locale
- query param (
formforge_locale) - header (
X-FormForge-Locale) - config/app locale fallback chain
- EN/FR translation resources for FormForge backend messages.
- Publishable package language files via
formforge-lang.
Changed
- Validation and field-level backend responses now use translatable message keys while preserving canonical technical keys.
- Partial validation flows continue to return canonical field keys; only message text is localized.
- Backend docs reorganized with a dedicated Validation section.
Notes
- Laravel native rule messages are still resolved by host app translation files.
Full Changelog: https://github.com/EvanSchleret/FormForge/compare/v1.3.0...v1.4.0
v1.3.0
Added
- New normalized field descriptor API for FormForge schemas:
describeFields()onFormInstance,FormManager,ScopedFormManager
- New centralized field resolution API:
resolveField(...)matchingname,field_key,key,id
- New partial batch validation API:
validateFields(...)for subset-oriented field validation- Supports alias identifiers in
onlyFields - Returns errors keyed by canonical field
name - Returns explicit errors for unresolved
onlyFieldsidentifiers
Changed
validateField(...)now uses centralized field resolution to avoid divergence in alias matching logic
Behavior notes
- Existing APIs remain intact:
validate(...)unchanged (including unknown-field handling)validateField(...)signature and response shape unchanged
- Partial validation (
validateFields) is field-oriented:- Unknown payload keys are ignored
- No global unknown-fields rejection in this flow
Tests
- Added coverage for:
- alias resolution via
name,field_key,key,id - normalized descriptors (
options,required,lookup_keys, etc.) - partial subset validation (valid/invalid)
onlyFieldsalias support- unresolved identifier errors
- non-regression for existing
validate()/validateField()behavior
- alias resolution via
Full Changelog: https://github.com/EvanSchleret/FormForge/compare/v1.2.1...v1.3.0
v1.2.1
Fixed
SubmissionValidator::validateField()now resolves fields using aliases, not onlyname.- Accepted field identifiers are now:
name,field_key,key, andid(normalized via trim + string cast). - Validation payload/rules still use the field canonical
name, preserving existing validation behavior. - Unknown identifiers still raise
UnknownFieldsExceptionwhen no alias matches.
Tests
- Added/updated feature tests to cover:
validateField('name', value)(existing behavior)validateField('field_key', value)validateField('key', value)validateField('id', value)- unknown key still throws
UnknownFieldsException
Full Changelog: https://github.com/EvanSchleret/FormForge/compare/v1.2.0...v1.2.1
v1.2.0
Added
- Single-field validation capability for FormForge schemas, allowing validation of one input against one question in one form without creating a submission.
- New public API methods:
FormInstance::validateField(string $field, mixed $value): arrayFormManager::validateField(string $formKey, string $field, mixed $value, ?string $version = null): arrayScopedFormManager::validateField(string $formKey, string $field, mixed $value, ?string $version = null): array
- New HTTP endpoints (available in both scoped and non-scoped route trees):
POST /forms/{key}/validate-fieldPOST /forms/{key}/versions/{version}/validate-field
- New validation config option:
formforge.validation.field.stop_on_first_failure(default:false)
Changed
- Resolve endpoint group now also exposes targeted field validation routes, reusing existing endpoint middleware/auth/action routing patterns.
- Authorization action map extended with:
resolve.validate_field_latestresolve.validate_field_version
- Base policy contract extended with:
resolve_validate_field_latest(...)resolve_validate_field_version(...)
Notes
- Field-level validation returns a structured result (
valid,errors,validated) instead of persisting data. - Unknown field names are rejected consistently with existing validation behavior.
Full Changelog: https://github.com/EvanSchleret/FormForge/compare/v1.1.1...v1.2.0
FormForge Client v1.1.2 🚀
The v1.1.2 is focused on a targeted standalone renderer fix to prevent stale external fields from leaking into submission payloads.
Since v1.1.0, package-level runtime changes are intentionally minimal and centered on this bug fix.
✨ Highlights
- Safer standalone
v-modelpayload handling inFormForgeRenderer - Automatic cleanup of unknown keys when form schema fields no longer exist
➕ Added
- Runtime payload sanitization in standalone/external-model mode:
- keeps only keys present in current schema field names
- emits cleaned
update:modelValuewhen stale keys are detected
⚡ Improved
- Better resilience when forms evolve (e.g. fields removed after initial model hydration)
- Cleaner parent state synchronization in standalone usage
🐛 Fixed
- Unknown field submission errors caused by outdated keys in external
v-modelpayloads (e.g.Payload contains unknown fields: short_text)
📘 Full Changelog: v1.1.0...v1.1.2
FormForge Client v1.1.0 🚀
I'm excited to announce v1.1.0, focused on stronger standalone integration, clearer publishing workflows, and better validation control in embedded/custom form setups.
This release improves how FormForge works when integrated into external parent forms while also simplifying management API publication behavior through payload-driven actions.
✨ Highlights
- Payload-driven auto-publication for form create/update workflows
defaultPublishedbuilder behavior aligned with create/patch actions (no extra publish call)- Better standalone validation ergonomics with exposed renderer validation APIs
- Improved blur-based validation behavior in external
v-modelintegrations - Continued stability improvements for scoped route resolution
➕ Added
- Management payload support for:
auto_publish: trueautoPublish: true(normalized toauto_publish)
FormForgeRendererexposed methods for host apps:validate(options?)validateField(name)clearErrors(path?)getErrors(path?)
- New renderer props for validation triggers:
validateOnvalidateOnBlur
⚡ Improved
- Builder save flow now supports auto-publication via payload on create/patch
defaultPublishednow relies on the management mutation path instead of issuing a separate/publishrequest- Standalone/external-model UX with explicit field-level blur validation handling
- Scope param resilience when resolving named scoped routes after navigation
🐛 Fixed
- Cases where named scope params could be missed after route transitions
- TypeScript lint issue (
no-explicit-any) in submission response typing
** 📘 Full Changelog**: https://github.com/EvanSchleret/FormForgeClient/compare/v1.0.0...v1.1.0
v1.1.1
Added
- Added support for
auto_publish(andautoPublish) in form managementcreateandpatchrequests POST /formscan now immediately publish the created form whenauto_publishistruePATCH /forms/{key}can now immediately publish the updated form whenauto_publishistrue- Publication now happens as part of the same management flow, returning the published revision in the response
Full Changelog: https://github.com/EvanSchleret/FormForge/compare/v1.1.0...v1.1.1
v1.1.0
Added
- Category name guard via config:
- New key:
formforge.categories.forbidden_names - Case-insensitive matching
- Leading/trailing spaces ignored
- Enforced on:
POST /api/formforge/v1/categoriesPATCH /api/formforge/v1/categories/{categoryKey}
- Returns
422with validation error oncategorywhen blocked
- New key:
FormSubmission::meta(string|array $key, mixed $value = null): self- Convenience helper to merge and persist submission metadata
Changed
- Category handling no longer creates implicit default categories during form creation/sync paths
- Added dedicated category creation flow (command-driven) to keep category lifecycle explicit
Fixed
- Migration compatibility: shortened FK name for privacy overrides table
- Test fixture compatibility: removed strict dependency on
FormSubmission::meta()in automation fixture path - CI changelog updater now has a guaranteed target file (
CHANGELOG.md) to avoid release job failure
Config Migration
php artisan formforge:install:merge --skip-migrations --no-backup
DB Migration
php artisan migrate
Full Changelog: https://github.com/EvanSchleret/FormForge/compare/v1.0.2...v1.1.0
v1.0.2
Added
- Added a new Artisan command:
formforge:category:create - The command supports both direct arguments/options and interactive prompts when no name is provided
- Interactive mode now asks for key category fields (including system/active flags)
Changed
- Removed implicit automatic creation of the default
generalcategory - Form sync and management creation flows now allow forms without auto-generated categories
- Category backfill migration logic no longer creates a fallback
Generalcategory when category data is missing
Full Changelog: https://github.com/EvanSchleret/FormForge/compare/v1.0.1...v1.0.2
v1.0.1
- Fixed a MySQL migration failure caused by an auto-generated foreign key name exceeding MySQL’s identifier length limit
Full Changelog: https://github.com/EvanSchleret/FormForge/compare/v1.0.0...v1.0.1
FormForge v1.0.0
I’m excited to ship the first stable release of FormForge.
FormForge is now production-ready as a deterministic dynamic forms engine for Laravel, with immutable revisions, strict validation, built-in HTTP APIs, and privacy-focused submission lifecycle tooling.
What I’m shipping in 1.0.0
Core platform
- I finalized the code-first form definition workflow with deterministic schema behavior.
- I introduced immutable form versioning and safer mutation flows.
- I added category-aware form organization (including slug support).
HTTP API
- I shipped a complete API surface under
/api/formforge/v1:- schema
- submission
- upload
- resolve
- draft
- management
- I added scoped routes for tenant/context-style integrations.
- I hardened response resources and serialization for safer API output.
Security and authorization
- I introduced owner-aware authorization and scoped policy controls.
- I strengthened endpoint protection and route-level option handling.
- I added safer install/merge and route-scope behavior to reduce misconfiguration risk.
Submission workflows
- I shipped authenticated draft workflows.
- I added submission export tooling (CSV/JSONL).
- I shipped resolver-driven automation targets and post-submission automation handlers.
Privacy / GDPR
- I introduced built-in retention and anonymization tooling.
- I added GDPR policy and response commands, plus runtime execution support.
- I added privacy policy/override persistence to support real compliance workflows.
Developer experience
- I added CLI coverage for install, list, describe, sync, route/options introspection, export, GDPR, and automation scaffolding.
- I stabilized CI and test workflow around Pest/Testbench for package reliability.
Compatibility
- PHP:
>=8.2 - Laravel:
12.x | 13.x - License:
MIT
Install
composer require evanschleret/formforge
php artisan formforge:install
php artisan migrate
Notes for adopters
- I recommend enabling scoped routes and ownership resolution early for multi-tenant or context-aware backends.
- I recommend reviewing
config/formforge.phpfor GDPR defaults, upload mode, and unknown-field validation before production rollout.
FormForge Client v1.0.0
I'm excited to announce v1.0.0, the first stable release of FormForge Client.
This release marks the transition from iterative development to a production-ready baseline, with a strong focus on reliability, developer ergonomics, and a consistent end-user experience across the client package and the Laravel backend package.
Highlights
- Stable, versioned API and client behavior for core form workflows
- Improved SSR-friendly data loading and rendering consistency
- Stronger validation and error handling across critical flows
- Better type safety and maintainability in frontend and backend code
- Expanded automated test coverage and CI confidence for release quality
Added
- Initial stable feature set for form creation, editing, and submission workflows
- Structured request validation and standardized JSON API responses
- Reusable frontend composables for shared app logic
- Improved SEO metadata handling for public-facing pages
Improved
- Performance across key rendering and data-fetching paths
- DX for local development, linting, and type-checking workflows
- Internal architecture with clearer separation between controllers and business logic
Fixed
- Inconsistent handling of edge-case validation errors
- SSR/CSR mismatch issues in selected views
- Multiple stability issues discovered during pre-1.0 hardening
Full Changelog: v1.0.0 establishes the stable foundation for the 1.x line, with future releases focused on incremental features, performance, and ecosystem integrations.