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 Code Field Laravel Package

creagia/filament-code-field

A CodeMirror-powered code field for Filament forms with syntax highlighting, autocompletion, light/dark modes, multiple languages (JSON, PHP, HTML, XML, JavaScript), and read-only support.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Pick the right major before touching composer.json. The version matrix is inverted from the usual "latest is best" instinct, and this is the single most common way an afternoon gets lost:

Your stack Install
Filament 3 + Laravel 11 composer require creagia/filament-code-field (^3.0)
Filament 3 + Laravel 10 or 12 composer require "creagia/filament-code-field:^2.0.0"
Filament 2 composer require "creagia/filament-code-field:^1.0.0"

Run composer show filament/filament laravel/framework first, write the constraint explicitly, and commit the lock file. Do not let a composer update float you across a major.

2. There is nothing to install beyond Composer. No service provider to register, no config to publish, no migration, no artisan command. The package ships a PHP Field class plus compiled CodeMirror JS/CSS that Filament loads itself. Verify after install that vendor/creagia/filament-code-field/resources/dist (or equivalent) is present and deployed — if your deploy pipeline runs composer install --no-dev and then only copies public/build, the editor will render as a dead textarea.

3. First use case: a JSON settings blob on a Resource form. Add one field, open the screen, and confirm syntax highlighting, autocompletion, and dark mode all work before building anything around it.

use Creagia\FilamentCodeField\CodeField;

public static function form(Form $form): Form
{
    return $form->schema([
        CodeField::make('settings_json')
            ->label('Settings')
            ->withLineNumbers()
            ->required(),
    ]);
}

4. Where to look first. The public API is small enough to read in one sitting: open src/CodeField.php in vendor/ and skim the constants (JSON, PHP, HTML, XML, JS) and the helper methods (jsField(), htmlField(), …). That file is a more reliable source of truth than the README, which has drifted (see Gotchas). The linked Creagia blog post is the only source for screenshots and editor-level behaviour.

Implementation Patterns

Language per field, chosen by what the user is editing — not by what the column stores. Default is JSON, so the only reason to call setLanguage() is a genuinely different payload. Prefer the fluent helpers for readability; they read like Filament's own ->textarea() / ->markdown() idiom:

CodeField::make('payload')->jsonField()->withLineNumbers(),
CodeField::make('template')->htmlField()->disableAutocompletion(),
CodeField::make('snippet')->jsField(),
CodeField::make('handler')->setLanguage(CodeField::PHP)->withLineNumbers(),

Read-only viewing is a first-class pattern. ->disabled() is the documented way to render stored code in a view modal or a read-only Resource page. Because Filament does not dehydrate disabled fields, this is safe for display and safe against accidental round-trips:

CodeField::make('settings_json')
    ->label('Stored settings')
    ->disabled()
    ->withLineNumbers(),

For an actual infolist (ViewRecord), there is no infolist entry component in this package — the pragmatic route is a disabled CodeField inside an action modal, or a plain TextEntry with ->prose()/->copyable() if you only need to see the value.

Wrap it in a house field class. This is the highest-leverage pattern for day-to-day use, because it gives you defaults, a single place to swap implementations, and insulation from a Filament major upgrade:

namespace App\Filament\Fields;

use Creagia\FilamentCodeField\CodeField;

class JsonEditor extends CodeField
{
    protected function setUp(): void
    {
        parent::setUp();

        $this->jsonField()
            ->withLineNumbers()
            ->default('{}')
            ->rules([
                fn () => function (string $attribute, $value, $fail) {
                    json_decode($value ?? '');
                    if (json_last_error() !== JSON_ERROR_NONE) {
                        $fail('This is not valid JSON: ' . json_last_error_msg());
                    }
                },
            ]);
    }
}

Swapping back to Filament\Forms\Components\Textarea is then a one-line change in one file.

Validation is your job, not the package's. The field does syntax highlighting only. Any "is this actually valid?" guarantee comes from a rules() closure (as above), a custom Rule class, or a ->rule('json') on plain JSON columns. Decide this in the same ticket as the field; otherwise you will ship an admin panel that cheerfully persists {"foo": } into a column your application later json_decodes at runtime.

Guard against model casting surprises. A $casts = ['settings_json' => 'array'] attribute hands the field an array, not a string. Keep the editor bound to a string-backed attribute (or add a getXForEditorAttribute() accessor) and let a mutator handle encoding. Test the edit → save → reload loop once per model before trusting it.

Use setDisplayMode() when state changes from outside the editor. Added in 1.0.8 for exactly this: a Select that switches language, or a toggle that flips read-only. Without it, the CodeMirror instance keeps the mode it was mounted with.

Testing: assert form state, not the editor. Livewire/livewire()->fillForm() tests never execute the JS bundle, so they will always pass regardless of whether the editor renders. Use them to assert the value round-trips and your validation rules fire; use a browser test (or a human) to confirm the CodeMirror mount, dark mode, and RTL once per Filament upgrade.

Respect a field budget per screen. Each field mounts an independent CodeMirror instance; multi-editor height behaviour was only stabilised in 1.0.11. Two or three on a screen is fine; a repeater with N code fields is not — use a separate relation manager page instead.

Gotchas and Tips

The README lags the changelog. 1.0.2 added SQL support, but the README's language list still stops at JSON/PHP/HTML/XML/JS. Before you use a language, grep the constants in src/CodeField.php in your pinned version — don't trust the docs, and don't trust a blog post written against 1.x.

disabled() is not readOnly(). In Filament, disabled() also removes the field from dehydration. For a view screen that's what you want; for a form where a locked field must still submit its value, that's a silent data-loss bug. Check which semantics you need before shipping.

Height and length controls exist but are undocumented. 1.0.6 added min/max input height; 3.0.2 added max/min length. Look for these methods in the source rather than the README — they're the correct answer to "the editor is 40px tall on the create page" and "someone pasted a 4MB minified bundle."

Dark mode, RTL, and filament.php config. 1.0.11 fixed a crash when dark mode is disabled in config/filament.php, and 1.0.9 fixed RTL direction and a dark-mode detection break. All of these are historical bugs, not current ones — but they tell you exactly which panel configurations to smoke-test after any upgrade: dark mode off, RTL locale, and more than one editor on a page.

No config file means no global defaults. You cannot publish a config to set the default language, height, or line numbers panel-wide. Subclassing (above) or a Field::macro() in a service provider are the only sanctioned ways to centralise opinionated defaults. Don't patch vendor/.

CSP and asset delivery are the classic silent failures. The component injects styles and loads compiled JS from the package's vendor path. If your panel sits behind a strict Content-Security-Policy, verify that inline styles are permitted (style-src 'unsafe-inline' or a nonce) and that vendor/ is served, not blocked by an nginx location rule. Symptom: a plain grey textarea with no highlight and no error in the console beyond a CSP violation.

Watch the abandonment signal. 57 stars, zero dependents, one principal maintainer, and a changelog dominated by Dependabot PRs. That's acceptable for internal admin tooling; it is not acceptable on a customer-facing path. Keep the wrapper class, keep the Textarea fallback documented in the ticket, and treat "Filament v4 upgrade" as a scheduled risk with a lag you don't control.

Blast radius is contained if you let it be. Failure here degrades a form input — it is not data corruption or an outage, provided server-side validation exists and the field sits behind your own subclass. That combination is what turns a third-party dependency decision into a reversible one.

Extension points, ranked by durability: subclass → rules() closure → inherited Filament methods (label(), hint(), helper(), default(), columnSpan()) → setDisplayMode() for reactive state. Overriding the field's Blade view works but is the first thing to break on a Filament upgrade, so treat it as a temporary patch, not a pattern.

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.
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo
stevenay/myanfont
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin