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

Laravel Nova Chordpro Field Laravel Package

henryavila/laravel-nova-chordpro-field

A Laravel Nova field for editing and displaying ChordPro song lyrics with chords, giving Nova resources a clean, dedicated input experience.

View on GitHub
Deep Wiki
Context7

Getting Started

The package adds a Nova field that stores and displays ChordPro song text — lyrics with inline chords ([C]Amazing [F]grace) plus directives such as {title:}, {key:} and, as of 1.2.0, {capo:}.

  1. Install into an existing Nova app:
    composer require henryavila/laravel-nova-chordpro-field
    
  2. Add a TEXT (not VARCHAR) column to hold the raw ChordPro source, e.g. songs.content.
  3. First use case — a Song resource:
    use HenryAvila\ChordproField\Chordpro;
    
    public function fields(NovaRequest $request)
    {
        return [
            Text::make('Title'),
            Chordpro::make('Content')
                ->rules('required', 'string', 'max:65535')
                ->help('Paste ChordPro text. Use {capo: n} for a capo warning.'),
        ];
    }
    
  4. Where to look first in the source: the field service provider (to confirm the registered Vue component name), resources/js/components/FormField.vue / DetailField.vue, and the README's directive examples. The 1.2.0 diff is small enough to read in full — it lives in the detail/display component where {capo:} is parsed and surfaced.

Implementation Patterns

Store source, render on read. Keep the DB column as the raw ChordPro string and let the field handle parsing on the Detail/Index side. Never store HTML — you lose the ability to re-render after a chord library upgrade or a capo/transpose change.

Capo as metadata, not as transposition. {capo: 2} tells the performer to clamp fret 2; it does not mean "transpose the chords by 2". The 1.2.0 feature is a display concern — a badge/hint in the field output. If you also want transposed chords, do the math yourself in an accessor and feed the field a derived string (or a separate read-only field):

Chordpro::make('Content')->onlyOnDetail(),

Text::make('Capo', fn () => $this->capo_fret)->onlyOnDetail(),

Parse the directive once, reuse it. If you need the capo value in the UI outside the field (badges on the index, setlist printouts), regex the stored source rather than duplicating parsing logic:

protected function capoFret(): int
{
    preg_match('/^\s*\{capo:\s*(\d+)\s*\}/mi', $this->content ?? '', $m);
    return (int) ($m[1] ?? 0);
}

Compose with a renderer only if needed. The Nova field gives you editing and a metadata-aware preview; it is not a full lead-sheet renderer. For public-facing song pages, render server-side from the same stored string (e.g. a ChordPro-to-HTML library or a Blade partial) so the Nova preview and the front end agree on directives.

Validation and normalisation. Use ->rules() plus a ->fillUsing() or model mutator to normalise line endings and trim stray whitespace around directives — ChordPro parsers are line-oriented and brittle about indentation.

Index columns. For lists, prefer a truncated plain text column over the ChordPro field:

Text::make('Title')->sortable(),
Text::make('Capo', fn () => $this->capo_fret ?: '—')->onlyOnIndex(),

Gotchas and Tips

  • Directives must start the line. {capo: 2} indented by a space, or inline after lyrics, will be ignored by most ChordPro parsers — including whatever the field uses. Normalise on save.
  • 1.2.0 is additive. No migrations, no config or field-API changes, no deprecations. A composer update is safe; pin ^1.1 if you need to freeze.
  • Missing capo is the default case. The field should render nothing (or a neutral state) when no directive is present. Guard against {capo: 0} and {capo:} before casting to int.
  • XSS surface. If the field renders chords/lyrics as HTML rather than escaped text, user-submitted songs become an injection vector. Confirm escaping in DetailField.vue before opening the field to non-admin users.
  • Column size. Songs with many verses comfortably exceed 255 chars. Use TEXT/MEDIUMTEXT; a VARCHAR(255) truncation looks like a parsing bug and is a bad afternoon.
  • Escaping in the editor. Vue/Nova will happily pass through braces, but watch for Blade or JS templating in your own preview components — {title: …} inside a Blade {{ }} context is a common self-inflicted breakage.
  • Customising the component. Publish and rebuild assets (vendor:publish then npm run build) — editing files under vendor/ is lost on the next composer update, and forgetting the rebuild makes the capo display silently fail to appear.
  • Nova version coupling. Confirm the field's peer requirement against your Nova major version (v4 vs v5 asset pipeline differences). A mismatch typically shows up as a blank field rather than an exception — check the browser console and nova.log first.
  • Debugging display issues. Dump the raw stored string ($song->getRawOriginal('content')) to separate "editor mangled the input" from "renderer didn't parse it". Almost every reported capo bug is the former.
  • Extension points. The Vue components are the practical extension surface; there is no config file. Wrap the field in your own Nova field class if you need org-wide defaults (rules, help text, default directives injected on create).
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.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel