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

Filament Cnpj Field Laravel Package

jeffersongoncalves/filament-cnpj-field

A Filament form field for Brazilian CNPJ input, adding masking and validation to Laravel admin panels. Simplifies collecting and verifying company registration numbers in Filament forms.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Filament v5-only package — there is no v4 path, so the first step is confirming your panel is already on v5 before you composer require. If you're mid-upgrade, park this until the panel boots cleanly.

  1. composer require jeffersongoncalves/filament-cnpj — it pulls jeffersongoncalves/laravel-cnpj, which is where the actual check-digit algorithm and Minha Receita HTTP client live. Skim that dependency's README too; the field is a thin form-component wrapper around it.
  2. Check whether anything needs publishing (php artisan vendor:publish --tag=...). If a config file exists, it will hold the lookup endpoint/timeout — set those before writing any forms, because the defaults will point at a public API you may not want to hammer from production.
  3. Look first at vendor/jeffersongoncalves/filament-cnpj/src/ — specifically the CnpjInput class. Read the public methods before reading the docs; for a package this small the class is the documentation, and you'll want to know exactly which fluent methods exist for mask mode and lookup rather than guessing from the release note.

First use case: a CnpjInput::make('cnpj') field dropped into an existing CompanyResource form schema. That alone gets you the mask and server-side check-digit validation — no lookup, no autofill, no network. Ship that first, confirm it saves digits cleanly, and only then turn on the Minha Receita integration.

Implementation Patterns

Start masked-only, add lookup second. The validation and mask are self-contained and safe. The company lookup is an outbound HTTP call with someone else's uptime — treat it as an enhancement, not part of the core field contract. Wire it behind a separate fluent call so you can disable it per-field.

Normalise on the way in, format on the way out. Keep the database column holding the unmasked 14-character string and let the field handle display. In practice that means the field's dehydrated state should be digits-only (or alphanumerics-only for the new format) and any ->formatStateUsing() you add should re-apply the mask for edit forms. Do the stripping in one place — a mutateFormDataBeforeSave() or an Eloquent mutator — not scattered through the form.

Use it for table filters too. Filament lets you reuse the same component inside ->filters([...]) and inside action modal forms. A masked CNPJ filter is a big usability win on a company list and costs nothing extra once the field works in the resource form.

Extract shared schemas. If CNPJ appears on more than one resource or panel, put the field in a small static CompanyForm::schema() / CnpjFields::make() helper. You'll want one place to flip mask mode when you support both CNPJ formats.

Handle the lookup as a UX affordance. Trigger it on blur (->live(onBlur: true) plus afterStateUpdated) and fill sibling fields (razao_social, nome_fantasia, address) only when they're empty — never silently overwrite what the user typed. Guard the handler so a failed lookup leaves the form fully usable.

Test with Http::fake(). Anything touching Minha Receita must be faked in your suite or your CI becomes dependent on a third-party Brazilian API. Assert on the unmasked state value; that's the contract that actually reaches your database.

Gotchas and Tips

  • The mask is presentation; validation is server-side. Any value posted programmatically (imports, API endpoints, seeders, Livewire tests) bypasses the JS mask entirely. Make sure your validation rule normalises before checking digits, and never assume the state is formatted.
  • Alphanumeric CNPJ changes your schema. Brazil's CNPJ format moves to alphanumeric, and this package supports both. That means the column must be a string, not an integer/bigint — if you have legacy rows in a numeric column, plan a migration before enabling the alphanumeric mask. The check-digit algorithm also differs between the two formats, so don't hand-roll a regex validator alongside this package; use its rule so both formats stay correct.
  • Lookup calls happen on the request thread. A slow Minha Receita response blocks the Livewire round-trip and the user just sees a spinner. Set an aggressive timeout, catch failures, and cache successful lookups (CNPJ → company data is near-static). If it's a high-traffic admin panel, consider a queued job that populates fields on the next poll rather than an inline call.
  • Data freshness is not your problem to solve, but it is your problem to disclose. Minha Receita is a community mirror of Receita Federal data and can lag. Don't present lookup results as authoritative — leave the fields editable.
  • Rehydration is the classic bug. On edit, a masked value loaded into a field that validates the unmasked form will fail. If you see "invalid CNPJ" on records that definitely have valid CNPJs, this is why — check your formatStateUsing / dehydrate pair first.
  • Fresh v5-only, single-maintainer package. No deprecation path, no v4 fallback, small dependency tree but it does pull an HTTP client. Pin the version, and read the source of the laravel-cnpj dependency before trusting it with anything you send to a public endpoint — you're effectively auditing two packages.
  • Extension points: prefer wrapping the field in your own class that calls ->rules() / ->mask() explicitly over forking the vendor view. If you need a bespoke mask or a different lookup provider, override the field's view or swap out the lookup call rather than patching vendor code — you'll be upgrading this alongside Filament itself.
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.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource