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

wiebenieuwenhuis/filament-code-editor

A Filament form field that adds a full-featured code editor powered by CodeMirror, with syntax highlighting, themes, and configurable modes for editing code, JSON, and other languages directly inside your Filament forms and panels.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and publish assets. The package ships JS/CSS for its editor (a CodeMirror-based Alpine component). After Composer install you must make those assets available to Filament:

composer require wiebenieuwenhuis/filament-code-editor
php artisan filament:assets          # Filament v3 asset pipeline
# if the tag exists in your version:
php artisan vendor:publish --tag="filament-code-editor-assets"

Where to look first. Open vendor/wiebenieuwenhuis/filament-code-editor/src/Components/CodeEditor.php. That single class is the public API — the fluent methods you see there (language(), height(), and whatever else your pinned version exposes) are the whole surface area. Read the README's example form, then read the class, and you're done; there is no service provider config worth studying beyond asset registration.

Minimal first use case. Drop it into any Resource form in place of a Textarea, bound to a TEXT/LONGTEXT column:

use Wiebenieuwenhuis\FilamentCodeEditor\Components\CodeEditor;

CodeEditor::make('snippet')
    ->language('php')
    ->height('400px')
    ->columnSpanFull();

The field's state is a plain string, so persistence, ->required(), ->maxLength(), and Filament's normal validation all work unchanged. A good first target is a "custom CSS" or "webhook payload template" field on a Settings page — small blast radius, obvious win over a textarea, and it lets you confirm the assets actually load before you refactor a dozen forms.

Implementation Patterns

Language per record, not per form. Hard-coding ->language('php') is fine for a one-off, but if users store multiple snippet types, drive it from the model:

CodeEditor::make('body')
    ->language(fn (?Snippet $record) => $record?->language ?? 'plaintext')

Wrap this behind a custom field class (extend CodeEditor, add a snippet() helper) so the ten forms in your app don't each re-derive the language. This is also your escape hatch if the package dies — you swap one parent class.

Pair the editor with a preview + hard validation. The editor is a UI affordance, not a validator. For JSON, validate in ->rules() with json_decode + json_last_error(); for PHP, shell out to php -l in a custom rule or accept that you're storing unvalidated code. Rendering the stored value back to users requires {{ }}/e() escaping — never {!! !!} a field a user typed into this editor.

Read-only for non-editors. Filament's ->disabled()/->readOnly() generally propagate to the underlying Alpine component, but verify visually — a disabled CodeMirror instance that still accepts keystrokes is a common gap in small packages. If it misbehaves, fall back to ->hidden(fn () => ! auth()->user()->can('edit')) plus a TextEntry-style display.

Settings pages and modals. Because it is a standard Filament field, it composes into filament/spatie-laravel-settings-plugin pages and action modals without ceremony — but modal usage is where asset/height issues show up first (the editor can render at 0px if the modal measures before mount). Set an explicit ->height() rather than relying on CSS defaults.

Testing. Treat it as a text field in tests: fillForm(['snippet' => '<?php echo 1;']) on a Livewire::test() of the Resource page works because state flows through Livewire's normal set/dehydrateStateUsing path. Don't try to simulate the CodeMirror DOM in Dusk unless you genuinely need to test the JS — assert on the persisted column instead.

Pair with a diff/versioning story. The moment users edit code through a browser form, "who broke prod" becomes your problem. Store a revision (or use owen-it/laravel-auditing) on save. This costs an hour now and is the difference between the field being a convenience and a liability.

Gotchas and Tips

  • Assets are the #1 failure mode. If the field renders as a bare textarea, the CodeMirror JS never loaded. Check the browser network tab for the package's assets, then re-run php artisan filament:assets and php artisan optimize:clear. Deploying with a stale public/ directory (or a deploy script that skips asset publishing) silently degrades to a plain textarea — which looks "fine" until someone notices there's no syntax highlighting.
  • Strict CSP breaks it. CodeMirror injects inline styles and uses eval-free but dynamic style elements. A nonce-based CSP will blank the editor with no console-obvious cause unless you allow style-src 'unsafe-inline' or nonce the generated <style> tags. Test the editor on a production CSP, not just locally.
  • Dark mode is theme-dependent. The editor reads Filament's theme to pick a palette; if you've written a custom panel theme, you may get white-on-white. Override via the field's methods or a small CSS shim in your panel theme — don't patch the vendor file.
  • DB column sizing. TEXT caps at 64KB. CSS/JS bundles and large JSON fixtures blow past that quietly (MySQL truncates or errors depending on STRICT_TRANS_TABLES). Use LONGTEXT and consider a ->maxLength() that matches reality.
  • Unknown languages fail silently. Passing an unsupported language string typically falls back to plain text rather than throwing. If highlighting "doesn't work," your ->language() argument is the first suspect — check the package's supported-language list against your value.
  • Debounce and wire:model.live. Large files plus live binding equals input lag; the editor syncs state on debounce. Keep it as the default (deferred) binding and only switch to .live for small snippets where you need reactive previews.
  • Pin the version and expect to fork. 18 stars, 0 dependents, single maintainer, no ecosystem pressure testing it. Lock an exact tag in composer.json, and write a 20-line test that mounts a form containing the field so a Filament major bump fails loudly in CI rather than in a user's browser. The field class is thin enough that forking is a realistic — and probably eventual — outcome; keep package-specific calls isolated in one custom field class to make that swap cheap.
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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource