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 Editor Laravel Package

sebastiaankloos/filament-code-editor

Filament Code Editor adds a ready-to-use code editor form field to Filament panels, with syntax highlighting, line numbers, and configurable options for editing code and JSON directly in your admin forms.

Deep Wiki
Context7

Getting Started

The package ships a single Filament form component that wraps an embedded code editor (CodeMirror-based). You drop it into a form schema like any other field.

1. Install and register assets

composer require sebastiaankloos/filament-code-editor
php artisan vendor:publish --tag="filament-code-editor-assets"   # if the tag exists in your version

2. Confirm the compatibility matrix before you write code. This package's last release was April 2023, which predates Filament v3. Open vendor/sebastiaankloos/filament-code-editor/composer.json and check the filament/filament constraint. If it caps at ^2.0, either pin your panel to Filament v2, or budget time to fork and port the field (the component is small — one PHP field class, a Blade view, and a JS asset). Do this check first; almost everything else in this assessment assumes the field loads.

3. Find the entry point. Read these three files in order:

  • src/Components/CodeEditor.php (or whatever the class namespace is — grep for extends Field) — this is the public API surface: language(), height(), theme(), readOnly().
  • resources/views/*.blade.php — shows how the editor is mounted and which JS/Alpine hooks are used.
  • resources/js/* — shows the editor library version and how state is synced back to Livewire.

4. First use case: a settings/config editor. The highest-value, lowest-risk integration is editing a stored text value that is not PHP:

use SebastiaanKloos\FilamentCodeEditor\Components\CodeEditor;

CodeEditor::make('value')
    ->label('JSON configuration')
    ->language('json')
    ->height('420px')
    ->required(),

Put it on a Settings custom page or a SiteConfig resource, back it with a longText column, and you have a working admin-side config editor in ~10 minutes. Start here rather than on a PHP/Blade template field — you get the full editing experience without exposing arbitrary code execution paths on day one.

Implementation Patterns

Form schema field, resource or custom page. The field is schema-scoped, so it works identically in Resource::form(), ->form() on a page, and inside Filament\Forms\Components\Section/Grid:

public static function form(Form $form): Form
{
    return $form->schema([
        Section::make('Template')
            ->schema([
                CodeEditor::make('body')
                    ->language('blade')
                    ->height('60vh')
                    ->columnSpanFull(),
            ]),
    ]);
}

Language selection driven by another field. The most common real-world pattern is a Select for the file/format type plus a code field whose language follows it. Use ->reactive() on the select and ->language(fn (Closure $get) => $get('format')). If the language prop is applied only at mount time in your version, use ->key(fn ($get) => 'editor-'.$get('format')) to force a remount — cheap and reliable.

Validation is your job, not the editor's. Syntax highlighting is cosmetic; the field will happily save broken JSON. Attach a rule:

CodeEditor::make('config')
    ->language('json')
    ->rules([
        fn () => function (string $attribute, $value, Closure $fail) {
            json_decode($value);
            if (json_last_error() !== JSON_ERROR_NONE) {
                $fail('Invalid JSON: '.json_last_error_msg());
            }
        },
    ]),

For CSS/JS/Blade, at minimum run a server-side sanity check (balanced braces, no <?php in a non-PHP field) rather than trusting the editor.

Read-only viewer pattern. Use the same field with ->readOnly() and ->height('70vh') inside a ViewRecord page or a modal action to show config snapshots or diffs. Cheaper than building a separate syntax-highlighted renderer, and visually consistent with the editor.

Template editing with a safety net. If you let admins edit Blade/PHP, store the content in the DB and compile it to a cache file or Blade::string() at render time — never write it into resources/views from a web request. Pair the field with a "preview" action and an audit column (updated_by, updated_at) so a bad save is recoverable. Git-backed storage (write to a repo, commit on save) is the pattern that survives contact with production.

Repeater / modal caveat handling. When the field lives inside a Repeater or modal, mount it in an Alpine x-init on the container rather than at page load, and destroy on removal — otherwise you get overlapping editor DOM for each row. If you only need N=1 editors per page, keep it that way; this package is not optimized for heavy repeater use.

Gotchas and Tips

It is archived. No security patches, no Filament v3/v4 support, no fixes for editor-library CVEs. Treat it as a vendored component: fork it into packages/, or copy the field class into your app. Add a note in your repo so future-you knows why the dependency is pinned.

Filament version mismatch is the #1 failure. Symptoms: field renders as a plain textarea, or JS throws Alpine is not defined / editor never initializes. Verify the constraint in composer.json and check that the asset registration (FilamentAsset::register / Alpine::register) runs on the Filament version you have.

Assets may load from a CDN. Many small editor packages pull the CodeMirror/Monaco bundle from a CDN. On air-gapped or CSP-strict environments the editor silently degrades. Check the Blade view for https:// references and publish/vendor the JS locally if so, then update your CSP script-src.

Livewire sync and debounce. The editor updates state via wire:model/$wire.set. Large files (hundreds of KB) will produce laggy typing if it syncs on every keystroke. Wrap with ->defer() / ->debounce(750) on the underlying state, and keep a maxlength or explicit size check — Livewire payload limits will bite before you expect.

Dark mode. Editor themes are separate from Filament's dark mode. Pass a theme explicitly (e.g. a light theme for light panels) and, if your version supports it, bind it reactively to the panel's appearance. Otherwise you get a white editor in a dark panel, which is the most common cosmetic complaint.

Height units. height() may accept px only in some versions; vh/rem may be ignored or break the layout inside Section/Grid. Test with ->columnSpanFull() and set a fixed pixel height if percentages collapse.

Validation messages are not surfaced by the editor. Because the editor replaces the <input>, the standard Filament error state may not visually appear on the field. Confirm @error handling in the Blade view; if missing, add a visible error block or wrap the field so users see why saving failed.

Extension points, ranked by cost. 1) Field props (language, height, theme, readOnly) — free. 2) Publish and edit the Blade view to add a "format/pretty-print" button — cheap and high value for JSON. 3) Publish the JS to add keybindings or a custom theme — moderate. 4) Add a new language mode — requires registering it in the editor instance; check whether the package exposes a config array for modes before hacking the JS.

Debugging checklist when the field misbehaves: is the asset rendered (<script>/<link> in the page source)? is the Alpine component present in the DOM (x-data="..." on the wrapper)? does the console show an editor initialization error? is the Livewire property name correct? Answer those four before touching the package source.

Prefer a maintained alternative if you're starting fresh. If your only need is JSON/config editing, a plain Textarea with ->rows() plus a JSON validation rule covers 80% of the value at zero maintenance cost. Reach for this package when the syntax highlighting and line numbers genuinely improve the workflow — and accept that you're adopting it as a fork, not a dependency.

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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect