Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Tomato Forms Laravel Package

tomatophp/tomato-forms

Tomato Forms is a form builder for TomatoPHP and Filament that lets you create dynamic, database-backed forms and manage submissions from your admin panel, with reusable field components so you can add custom forms to any Laravel app without boilerplate.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. The package is a Filament v3 plugin that ships migrations, config, two admin resources, and a form → fields → answers-in-user-meta data model. That model is the actual product value: admins author field definitions in a panel, and answers land as key/value rows against the user record instead of new schema columns. It fits an existing Laravel + Filament admin surface that needs config-driven, admin-authored data capture. It does not fit as a system of record — key/value meta is a rendering and capture layer, not a reporting or billing substrate.

Integration feasibility. The install path is short and standard (composer require, publish config and migrations, migrate, register the plugin in the panel provider). The surface is small enough to read end-to-end in an afternoon. The single unknown that gates the whole plan: is there a non-panel render/submit path, or is this admin-only? If admin-only, we own the Blade renderer and the submit endpoint, which is where most of the integration effort actually lives.

Technical risk. Ordered by severity:

  • Filament major compatibility (highest). Last release May 2024, predates Filament v4. Assume incompatibility with our current major until a spike proves otherwise. Check the filament/filament constraint in the package's composer.json before installing.
  • Silent data loss via meta-key collision. Field keys written unprefixed into a shared user-meta namespace can overwrite unrelated attributes with no error. Highest-severity item in the package; must be audited on day one.
  • No cascade cleanup. Deleting a form or field almost certainly strands meta rows with no cleanup path.
  • Stored XSS. Labels, help text, and option text are admin-authored and rendered back to users; any {!! !!} in package views is a persistent vector.
  • No schema versioning. Renaming or retyping a field makes historical submissions unmappable to the current definition; reports quietly lie after edits.
  • Validation is stored JSON config, not a DB constraint. Assume per-field validation is not enforced at the submit endpoint until proven otherwise.
  • File uploads are undefined. Disk, path, retention, and MIME validation are all open questions — likely we implement this ourselves.
  • Ownership risk. Zero stars, zero dependents, single maintainer, dormant upstream. Maintenance is ours regardless of the install path.

Key questions to answer before committing.

  1. What is the filament/filament version constraint, and does the plugin boot on our current major?
  2. Does the package expose a non-panel render/submit route, or do we build it?
  3. Where does "user meta" live, and is it a shared namespace with other packages?
  4. Is per-field validation enforced server-side at submit, and is the payload whitelisted?
  5. What is the authorization model over form definition (who authors) and form submission (who may answer)?
  6. Is there cascade or cleanup on form/field deletion?
  7. What does the file-upload path do on disk, MIME validation, and deletion?

Integration Approach

Stack fit. Strong if we are already on Laravel + Filament v3 inside the TomatoPHP ecosystem. Weak if we are on Filament v4, on a non-Filament front end, or if the forms are customer-facing — in each of those cases the fork effort approaches a small in-house build.

Migration path. Treat this as fork-and-own under MIT, not as a dependency. Concretely:

  • Pin the exact version ("tomatophp/tomato-forms": "1.1.19"), commit the lock file, and plan to vendor into an org namespace. A floating constraint is a future broken build given the dormant upstream.
  • Decide and write down whether user meta is a staging area or the system of record. If it is ever the system of record, plan the typed submissions table now so the seam exists before responses accumulate.
  • Keep the fork diff small and documented; upstream is a starting point, not a merge target.

Compatibility. Verify the Filament constraint against our major before any install work. Pin PHP and Laravel versions in the fork's composer.json. Budget for one Filament-major bump as recurring, not one-time, maintenance.

Sequencing (days, not weeks).

  1. Read the migrations first — they are the real API; confirm the model namespaces against them.
  2. Half-day spike: one form, five fields, two users, one submission, read meta back in tinker, render in an authenticated Blade view. This answers every key question in one pass.
  3. Decide gate: continue with the fork, or stop and build in-house.
  4. Build thin FormRepository / SubmissionRepository interfaces between app code and package tables. This is the highest-leverage decision — it survives a storage swap.
  5. Namespace every meta key (forms.{slug}.{field}); never key on field ID.
  6. Re-validate server-side from field definitions; whitelist keys and reject anything else.
  7. Build the Blade renderer as an explicit field-type match/@switch with an @includeIf fallback so custom types are partials, not package edits.
  8. Seed stable internal forms as code so they survive migrate:fresh and diff in PRs.
  9. Feature-test the repository and submit endpoint at the seam — not the Filament resources, which are brittle across majors.
  10. Ship the orphan-sweep artisan command before anyone is allowed to delete a form in the panel.

Operational Impact

Maintenance. Upstream is effectively dormant; we own patching, security review, and Filament compatibility permanently. The codebase is small enough that this is realistic, but it is a standing line item, not a one-off. Keep the fork diff auditable so a future maintainer can reason about it.

Support. Internal, admin-authored users only at first. No external SLA, no customer-facing exposure. Publish authoring conventions as part of rollout: never rename a field key (add new, hide old), never delete a field without archiving, never put PII or file uploads in a form until those paths are audited.

Scaling. Low-traffic internal capture is fine. The scaling bottleneck is read-back: aggregating answers across users from a key/value meta store is slow and awkward, and every reporting, billing, compliance, or deletion-rights requirement pushes toward a typed submissions table. Plan the storage decision before volume makes it expensive.

Failure modes and named mitigations.

  • Meta-key collision overwrites an unrelated user attribute, silently → enforce prefixed keys at submit; audit the write path on day one.
  • Deleting a form or field strands rows → soft-delete or archival step plus a scheduled orphan sweep.
  • Validation bypass at submit → server-side validator rebuilt from field definitions, whitelisted keys, never $request->all().
  • Stored XSS via admin-authored labels/options → {{ }} everywhere, audit package views for {!! !!}.
  • Panel 500s after a Filament upgrade → pin the major, test the fork against the target version before any framework bump.
  • File uploads with no retention or MIME policy → treat as unshipped until implemented and reviewed by us.

Ramp-up. One Laravel developer, half a day to spike, one to two days to a production-safe internal deployment with the repository seam, namespaced keys, and server-side revalidation. Add roughly a day for the orphan sweep and seam tests. No dedicated SME required — the surface is small enough to read fully, which is also why fork-and-own is the credible endgame rather than a straight dependency. Keep this off the critical path: nothing revenue-critical, customer-facing, or PII-bearing should sequence behind a package with zero dependents and a single maintainer.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator