orlyapps/nova-multiline-text
A Laravel Nova field for multiline text input, letting you edit longer content with configurable rows and display line breaks cleanly in index and detail views. A simple drop-in alternative to Nova's standard Text field.
Confirm the prerequisite before anything else: a licensed Nova install where laravel/nova resolves from Composer. If your Nova credentials aren't configured locally and in CI, composer require fails with a repository-resolution error that looks like a problem with this package but isn't.
composer require orlyapps/nova-multiline-text
Auto-discovery registers the service provider. There is no config file to publish, no migration, no new column type. The stored value is an ordinary string, so if the column already holds text, you change nothing at the database layer.
First use case: pick one resource with a notes/description/address field currently using the stock Textarea::make(), and swap it:
use Orlyapps\NovaMultilineText\MultilineText;
public function fields(Request $request)
{
return [
ID::make()->sortable(),
MultilineText::make('Notes', 'notes')
->rules('nullable', 'string', 'max:2000')
->placeholder('Internal notes…')
->rows(6)
->hideFromIndex(),
];
}
Then verify what you actually came for — that line breaks survive on create, update, detail, and index — before touching a second resource.
Before wiring it in anywhere else, spend fifteen minutes reading src/ and resources/js/components/. What the PHP class extends determines which fluent methods (rules, nullable, default, fillUsing, dependsOn, placeholder, rows) you get for free, and whether the Vue component binds text or uses v-html decides your XSS posture. That read is the whole assessment; everything below follows from it.
Swap one field, not all of them. Adopt as a spike on a single resource. Rollback is a one-line resource edit plus composer remove, with no data-format commitment. Run it side-by-side with native Textarea::make() — keep the built-in where it works, and use MultilineText only where line-break rendering or row control is the verified gap. This caps the blast radius and documents the delta by example for the next person reading the resource.
Treat it as a rendering concern, not a validation one. Chain rules, nullable, and an explicit max: exactly as you would with Textarea::make(). The widget accepts a 5,000-character paste into a VARCHAR(255) column without complaint; the database truncates silently and the operator never sees an error.
Use it for dense plain text, not rich content. Notes, addresses, internal comments, short config snippets that land in VARCHAR/TEXT. If the requirement is Markdown, WYSIWYG, previews, or a character counter, this is the wrong field — reach for a dedicated editor.
Verify all four surfaces explicitly. Create, update, detail, index. If line-break preservation is your reason for adopting, a field that preserves newlines in the form but collapses them on index is worse than the built-in, because now two renderers disagree about the same value.
Exercise dependsOn if you use it. A field that renders but silently stops reacting to its dependency looks fine on the happy path and fails in production. Test the reactive interaction before relying on it.
Fork into your namespace past two or three resources. Once adoption spreads, vendor the field as App\Nova\Fields\MultilineText so a Nova major upgrade forces an explicit touchpoint rather than a silent boot failure during composer update. The source is small enough that copying it is realistic — and if you need a variant (autosize, counter, preview), a ~30-line in-house field is often the better long-term trade than carrying the dependency.
Record the decision next to the usage. A one-line comment — "used instead of Textarea::make() because it preserves newlines on index" — prevents the same conversation from being relitigated and gives the next maintainer the rollback criterion.
"It's a textarea" is not a justification. Before adopting, name the delta from Textarea::make(): preserved line breaks on detail/index, row control, autosize, counter. If none apply, reject it and use the built-in.
Read composer.json, not the README, for version constraints. Nova majors have renamed and relocated field base classes. A package targeting a major you aren't on is a no-go no matter how clean the component looks. Check the declared Nova major and PHP/Laravel matrix against your installed versions.
The asset pipeline is a build-time liability. If dist/ is committed, upgrades are frozen but deploys are safe. If it isn't, you cannot rebuild without Nova's private npm registry. A missing compiled asset surfaces as a blank field or a 404, and it's easy to miss in staging where asset publishing differs from production.
Check the Vue component for v-html. Echoing stored operator input through v-html in an admin panel is a stored XSS vector. If you find it, escalate to a security review — don't treat it as a field swap.
Watch for silent truncation. Size your max: rule to the actual column width. The operator gets no validation error when the value disappears at the database layer, and the first symptom is missing text weeks later.
Debug blank fields in this order: provider auto-discovery (php artisan about / package:discover), published assets present and versioned, declared Nova major vs. installed major, then the component source. That list is faster than the README, which is thin.
Assume abandonment as the base case. Seven stars, zero dependents, a single maintainer, and no downstream corpus proving it survives a Nova bump. Pin the version in composer.lock, write the "why this and not Textarea::make()?" answer next to the field usage, and name an owner. An unowned fork rots quietly until an upgrade exposes it.
The extension point is the source, not the API. There is no documented customization surface. If you need different behavior, copy the class and component into your namespace and own them — never patch vendor/.
How can I help you explore Laravel packages today?