statikbe/laravel-filament-flexible-content-blocks/filament-flexible-content-blocks-custom-block
Claude Code and agent skill by statikbe/laravel-filament-flexible-content-blocks
- community
Checking that the SKILL.md file is still in the repository.
Create or modify a custom content block for the statikbe/laravel-filament-flexible-content-blocks package - the block class, its Filament form schema, its Blade view, media collections, translations and registration on a model. Use when adding a new block type to the Filament content blocks builder, or when a custom block does not show up in the builder, shows raw translation keys, or fails to render on the front-end.
Install
npx vskill@latest install statikbe/laravel-filament-flexible-content-blocks/filament-flexible-content-blocks-custom-blockSKILL.md
Creating a custom flexible content block
When to use this skill
Use this skill when the project uses statikbe/laravel-filament-flexible-content-blocks and you need a block type that the package does not ship (an FAQ accordion, a statistics band, a form embed, ...), or when you are debugging a custom block.
If instead you are wiring the package onto a model for the first time (migration, model traits, Filament resource, front-end view), use the filament-flexible-content-blocks-setup skill.
This works identically when the project uses statikbe/laravel-filament-flexible-content-block-pages, the ready-made CMS built on top of this package: custom blocks are written the same way and registered on that package's page model.
The rule that breaks everything if you get it wrong
Custom blocks extend `Statikbe\FilamentFlexibleContentBlocks\ContentBlocks\AbstractContentBlock`.
Do NOT extend `AbstractFilamentFlexibleContentBlock`. That subclass exists only for blocks that live inside the package. It hard-codes the package's own namespaces:
| It implements for you | ...which for your block means | |
|---|---|---|
getName() = 'filament-flexible-content-blocks::' . getNameSuffix() | Your block is named as if it were a package block, and its media collection and stored type key sit in the package namespace. | |
getLabel() / getFieldLabel() | Labels are looked up in filament-flexible-content-blocks::filament-flexible-content-blocks.form_component.content_blocks.*, so your block shows the raw translation key in the builder. | |
render() | Renders filament-flexible-content-blocks::content-blocks.{theme}{suffix}, a view inside the package that does not exist for your block - View not found. |
The class doc-block says so too: "Blocks implemented outside of the filament-flexible-content-blocks package should extend AbstractContentBlock!"
AbstractContentBlock extends Illuminate\View\Component, so your block is a Blade component; it wires itself into the Filament builder through make(), which you inherit.
Workflow
- Create the class in
app/ContentBlocks/{Name}Block.php. Copytemplates/CustomBlock.php.stub
as a starting point.
- Implement the seven required members (see
reference/block-api.mdfor the full signatures):
public static function getName(): string- a stable, unique, lowercase identifier, e.g.'faq'.public static function getIcon(): \BackedEnum|string- e.g.Heroicon::QuestionMarkCircle.public static function getLabel(): string- the label in the block picker.public static function getFieldLabel(string $field): string- label per form field.protected static function makeFilamentSchema(): array|Closure- the Filament form components.public function render()- return the Blade view for the front-end.public function getSearchableContent(): array- the block's plain text, for searching.
Also write a __construct(Model&HasContentBlocks&HasMedia $record, ?array $blockData) that calls parent::__construct() and maps $blockData onto public properties.
- Create the Blade view at
resources/views/content-blocks/{name}.blade.php. Start from
templates/custom-block.blade.php.stub. Public properties and public methods of the block class are available in the view (methods as closures: $replaceParameters($content)).
- Add translations for the label and the field labels in your own lang files - never in the
package's namespace.
- Register the block on the model so it appears in the builder and so its media collections are
registered. See "Registering" below.
- Add media handling only if the block has images: override
addMediaCollectionAndConversion()and
use BlockSpatieMediaLibraryFileUpload. See reference/block-api.md.
- Reuse the package's block features where they fit - block styles, background colours, image
position/width/conversion. See reference/concerns.md.
- Make Tailwind see the view: the front-end CSS must
@sourceyour
resources/views/content-blocks directory (usually already covered by the app's own view glob).
- Verify: open the Filament resource, add the block, save, and load the front-end page. Run
vendor/bin/pint and the project's static analysis.
Registering the block
The builder gets its blocks from the model's registerContentBlocks().
- Model uses
HasContentBlocksTrait: add the class to that model'sregisterContentBlocks().
``php public static function registerContentBlocks(): array { return [ ...FilamentFlexibleBlocksConfig::getDefaultFlexibleBlocks(), FaqBlock::class, ]; } ``
- Model uses
HasDefaultContentBlocksTrait: either add the class to
config('filament-flexible-content-blocks.default_flexible_blocks') (it then applies to every model using that trait), or override registerContentBlocks() on the model - a method on the class wins over the trait's.
Registration order is the order shown in the block picker.
Checklist
- [ ] Extends
AbstractContentBlock, notAbstractFilamentFlexibleContentBlock. - [ ]
getName()returns a unique, stable string - it is persisted as thetypekey inside the
content_blocks JSON and used as the media collection name. Renaming it orphans all existing content and images of that block.
- [ ] Constructor calls
parent::__construct($record, $blockData)first (it generates the block id
that media lookups depend on).
- [ ] Every value read in the Blade view is a public property or public method on the block class.
- [ ]
getSearchableContent()returns the block's text, sogetSearchableBlockContent()stays complete. - [ ] The block is registered on every model that should offer it.
- [ ] If the block uploads images,
addMediaCollectionAndConversion()is implemented; otherwise images
are never converted.
Common mistakes
- Raw translation keys in the builder, or `View not found` on render - the block extends
AbstractFilamentFlexibleContentBlock. Switch to AbstractContentBlock and implement getLabel(), getFieldLabel() and render() yourself.
- Block missing from the picker - not in the model's
registerContentBlocks(), orvisible()
returns false.
- Images upload but never appear -
addMediaCollectionAndConversion()was not implemented, the
upload field's ->collection() does not match static::getName(), or a plain SpatieMediaLibraryFileUpload was used instead of BlockSpatieMediaLibraryFileUpload (which tags the media with the block id so multiple instances of the same block keep their own images).
- All instances of the block show the same image - same cause: the upload field must be
BlockSpatieMediaLibraryFileUpload.
- Block styles have no effect -
render()must appendgetBlockStyleTemplateSuffix()to the view
name, and a matching view per style must exist.
Reference
reference/block-api.md- every method ofAbstractContentBlock: required, overridable, and helpers.reference/concerns.md- the reusable traits and block form fields (block style, background colour,
image position/width/conversion, call-to-action) and their config keys.
templates/CustomBlock.php.stub- a complete block class with an image, block style and background
colour.
templates/custom-block.blade.php.stub- the matching front-end view.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingresources/boost/skills/filament-flexible-content-blocks-custom-block/SKILL.md
Popularity
- Repository stars
- 181
- Repository forks
- 28
- 7-day trend score
- 26
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/statikbe/laravel-filament-flexible-content-blocks/filament-flexible-content-blocks-custom-block)