waad/filament-import-wizard
Queue-powered 4-step CSV and Excel import wizard for Filament with smart column mapping, relationship linking, Spatie Translatable and locale merge support, dynamic schema validation, upsert, and live progress tracking for 100K+ row imports.
Architecture fit
Action (ImportWizardAction) plus a Livewire wizard component, queued chunk jobs, a published config, and published migrations. It fits a Filament-4 admin panel cleanly and requires no changes to our domain models beyond optional getImportRules() / getImportFieldLabel() methods.save() (Eloquent events, observers, timestamps fire) and bulk upsert() (events do not fire). This asymmetry is the single most important architectural detail for us.Schema::getColumnListing), with an override hook. Elegant, but it makes import behavior a function of current migrations rather than an explicit contract.BelongsTo-only, with find-or-create semantics and auto-increment ID heuristics. No BelongsToMany, MorphTo, or pivot support documented.Integration feasibility
composer require, optional config publish, required migration publish, filament:assets rebuild. A developer can produce a working import on one model in under a day.@livewire('filament-import-wizard', ...)) gives optionality to expose imports outside the admin panel later, which is a genuine plus for customer-facing bulk upload.Technical risk
1.0.0 → 1.1.1 churn, and an aggregate score of ~18/100. The code may be good; the ecosystem signal says "assume you may own this fork."boot() hooks. Any audit log, webhook, search-index sync, or notification observer we rely on will silently not run for updated records. The documented "fallback to chunked inserts on upsert failure" compounds this: the same batch can take two different code paths.title_en, titleAr) into a JSON column is a silent-corruption class of bug if a column is named ambiguously; unwinding written JSON is manual.unique rule generated from schema may also be scoped to the whole table, which is wrong under multi-tenancy.whereJsonContains() lookups, Schema::getColumnListing(), case sensitivity, and Excel parsing all behave differently across MySQL/Postgres/SQLite. The Excel reader dependency isn't named, so the 100K-row memory ceiling is unverified; XLSX at that scale is memory-bound, CSV is not.Key questions to resolve before committing
save() at scale?Stack fit
sync queue mode as a staging-only convenience, never production: it converts a 100K-row import into a synchronous web request.~1.1) and commit the lockfile. Vendor the source into review scope — we should be reading ProcessImportChunk and the relation resolver before go-live, not after.Migration path
Compatibility validation
BelongsTo find-or-create, upsert keys, and tenant-scoped unique validation.Sequencing
App\Support\Imports\WizardActionFactory (or equivalent) so the vendor namespace appears in fewer than five files. This caps the cost of a future fork or replacement at days, not weeks.enableUpsert() for the pilot so all writes go through save() and events are consistent.Maintenance
Support
Scaling
save() means 100K+ queries plus event overhead. Accept the slower path where audit fidelity matters; use upsert only on tables without observer dependencies, and document that decision per resource.Failure modes to instrument and alert on
filament:assets) breaking admin styles if skipped → add to the deploy checklist.Ramp-up
Verdict for planning purposes: technically attractive and unusually well-scoped for its size, but the adoption signal (12 stars, 0 dependents, single maintainer) plus the upsert/event asymmetry and unverified tenant isolation make this a "spike with explicit exit criteria and a fork contingency," not an unconditional adopt. Proceed only behind an internal adapter, on a dedicated queue, with upsert disabled until the event gap is proven safe for each target table.
How can I help you explore Laravel packages today?