Skip to main content
← Back to Table of Contents

Summary

Permalink field for Filament: title + slug in one block, live URL preview, inline editing, Copy/Visit/Regenerate buttons, and uniqueness validation.
Spatie laravel-sluggable is optional. By default, the slug is generated from the title using the shared client slugifier, with PHP Str::slug() for locale-sensitive or unsupported transliteration and saved to the database like a regular form field. You only need to add the Spatie package if you want the same rules as on model saving (such as -2, -3 suffixes, preventOverwrite, etc.).

Start here — integration without Spatie (default)

No extra packages required besides filament-flex-fields. The model does not need any traits or slug options—just a database column and $fillable configuration.

Who is responsible for what

Checklist — 4 steps

Step 1 — Migration

Step 2 — Model (minimal, without Spatie)

The model does not need:
  • use HasSlug ani getSlugOptions()
  • an observer generating the slug
  • mutatora setSlugAttribute
  • composer require spatie/laravel-sluggable
The slug is saved to the record just like title—from the form data.

Step 3 — Filament Resource (minimum)

This creates: a title field + a hidden auto-sync flag + a slug field in one FusedGroup. If you want to see https://your-domain.com/blog/my-post under the slug:
Or only in the Resource, without changing the config:

Parameters of TitleSlugField::make() — what is available?

What happens automatically (without Spatie)

Slug generation without Spatie (technical)

No server requests. No model configuration required.

Four ways to add title + slug

When to switch to Spatie?

Only add Spatie when you need model-level hooks that the form alone cannot handle:
  • automatic -2, -3 suffixes on database collisions
  • preventOverwrite — never overwrite the slug after publish
  • skipGenerateWhen, extraScope, multiple source fields
  • using the same SlugOptions in form preview and on save()
Do tego: Spatie laravel-sluggable integration.

Common issues (without Spatie)

Next sections: Default form layout → Installation → Config → Full Example → Spatie Integration

Default form layout (FusedGroup)

TitleSlugField::make() always returns Filament\Schemas\Components\FusedGroup — the same layout with or without parameters:
Important: spatieModel changes only the slug preview generation logic (server + SlugOptions). It does not change the form layout.

What is inside FusedGroup

The group has CSS class fff-title-slug-fused-group (without the standard Filament border between fields).

Default appearance (ASCII)

When config('filament-flex-fields.slug.url_host') is set (e.g. APP_URL):
When url_host is null (no URL preview in config):

Table of default visual values

The same layout — three ways to call

Livewire test helper — hidden auto-sync field name:

Installation and assets

The package ships inside janczakb/filament-flex-fields. The path without Spatie only needs the package assets — no extra composer require.

Optional: Spatie (only when you need it)

Install only if the model uses HasSlug / getSlugOptions() and you want matching form preview:
Without that package TitleSlugField::make() still works fully — generation uses the shared client slugifier, with PHP generation when required.

Package configuration (config/filament-flex-fields.php)

Publish the config:
Slug-related keys:
Example — blog with custom Polish field names:

Full Example from scratch (migration -> model -> Resource)

Continuation of the Start here — integration without Spatie section. Steps 1–3 are the minimum; step 4 (Spatie) is optional.

1. Migration

2. Model (without Spatie — enough for production)

Do not add HasSlug or getSlugOptions() — unless you move to step 4 below.

3. Filament Resource (without Spatie)

4. (Optional) The same Resource with Spatie

Add this step only when you need suffixes, preventOverwrite, or other SlugOptions rules during save.
Two layers: the form shows a live slug preview; on save Spatie HasSlug may add a suffix (-2) or apply preventOverwrite — that is expected.

Cookbook — typical scenarios

Scenario 1: Blog — create + edit (default behaviour)

  • Create: title → slug live.
  • Edit: changing the title does not change the slug.

Scenario 2: Always sync slug with title

Scenario 3: Slug read-only on edit

Scenario 4: Custom title (RichEditor) + slug

Scenario 5: Slug uniqueness within tenant

Scenario 7: CMS Homepage (/)

Standalone SlugField (matches playground Homepage slug):
Inside TitleSlugField:

Scenario 8: Repeater — row with title and slug

Nested paths (sections.0.title → sections.0.slug) are resolved automatically.

Scenario 9: Manual slug only (no title, no auto-generate)

Use when there is no title field — user types the slug by hand. This is not the same as playground slug__standalone (that name means “slug field alone in the layout”, but it still uses ->source('title')).

Scenario 10: Form read-only (whole field)

Matches playground Form readonly:

Scenario 11: Spatie + multiple source fields (optional package)


Quick Start — Filament Resource (create + edit)

Summary of the Start here section — without Spatie:
Application-side requirements: slug column in migration + slug in model’s $fillable. Nothing more. What happens automatically:

How slug generation works

Form preview vs model save: When Spatie is configured, the field uses the same SlugOptions as your model so previews match production rules (separator, language, max length, multi-field sources, extraScope, suffix start, Closure sources).

Create vs edit

Default (preserve slug on edit)

On edit, changing the title does not change the slug. Good for published URLs.

Always sync slug from title

Read-only slug on edit only

Read-only title


Universal locale tabs: For any translatable attribute (title, body, metadata, …), use the dedicated TranslatableFields component. The section below covers TitleSlugField only — translatable titles with a single shared slug.

Translatable titles (single slug)

For generic translatable fields (body, excerpt, metadata, …) without slug coupling, use TranslatableFields instead.
Optional multi-language title with one shared slug. Locale switching uses package TranslatableFields (built on SegmentTabs).

What is implemented today

spatieModel ≠ Spatie Translatable. spatieModel on TitleSlugField is for Spatie Sluggable (HasSlug). For translations use translatableLocales (+ optional spatieTranslatable).

Basic usage

Changing EN/FR titles does not change the slug. Only the slugSourceLocale tab drives permalink generation.
On save, Filament merges title.pl / title.en into a title array. No extra glue code required.

Storage with Spatie laravel-translatable (optional)

On edit: if the record uses HasTranslations and the package is installed, each tab is hydrated via getTranslation(). Otherwise tabs read the raw JSON attribute. On save: the nested title array from the form is assigned to the model; Spatie JSON-encodes translatable attributes automatically.

Global defaults (config/filament-flex-fields.php)

When translatableLocales is omitted in TitleSlugField::make(), locales are read from config('filament-flex-fields.slug.translatable_locales').

Required title locales

By default only the slug source locale title is required. Optional locales can stay empty on create/edit.
FlexField config key: required_title_locales (null, 'all', or list of locale codes).

Per-locale title customization

Full TranslatableFields passthrough

When translatableLocales is set, title tabs are built with TranslatableFields internally. By default the factory enables directionByLocale() (RTL/LTR on the title input, not the label — see TranslatableFields / directionByLocale) and emptyBadgeWhenAllFieldsAreEmpty() (warning empty badge on tabs where the title is blank). The active tab stays on slugSourceLocale, not activeTabWithValue(). Use translatableFieldsConfigurator for further tweaks (activeTabWithValue(), bordered panels, custom tab icons, localeFieldUsing(), storageAttributeUsing(), etc.):
getSourceStatePath() resolves to title.{slugSourceLocale} automatically (e.g. title.pl).

SlugField translatable API

FlexField schema config

Slug generation locale

Translatable titles always use server-side slug preview (generateSlugPreview / Str::slug with slugSourceLocale). Alpine receives serverGenerate: true and slugSourceLocale so live preview matches PHP — including Polish diacritics (Łódź → lodz), which generic browser ASCII folding cannot handle reliably.

Spatie laravel-sluggable integration (v4.x)

Not required. If the default path without Spatie is sufficient, you can skip this section entirely.
Tested with spatie/laravel-sluggable ^4.0 (currently 4.0.2). The integration uses official Spatie v4 classes:
  • Spatie\Sluggable\Actions\GenerateSlugAction (via config/sluggable.php → actions.generate_slug)
  • Spatie\Sluggable\Support\SluggableAttributeResolver dla modeli z #[Sluggable] bez getSlugOptions()
  • Spatie\Sluggable\Support\Config::getAction() — ten sam resolver akcji co trait HasSlug
Spatie adds a second layer: saving the slug with model options (suffixes, scope, preventOverwrite). The form can display the same preview as the model — just pass spatieModel.

Optional dependency isolation (technical)

spatie/laravel-sluggable is in composer.json → suggest, not require. The package does not force installing Spatie. Optional. Install when you want model-driven slug rules:

Minimal model (trait — klasycznie)

Minimal model (v4 attribute — without getSlugOptions())

Multi-field attribute (v4):

Wire the form (zero extra config)

Spatie in the form is enabled only when:
  • podasz spatieModel, i
  • model ma getSlugOptions() lub atrybut #[Sluggable] z rozpoznawalnymi opcjami.
Simply having Post as the Resource model does not enable Spatie automatically — the slug configuration must exist on the model.
What changes after adding spatieModel: Or on standalone SlugField:

Explicit Spatie field mapping

When form field names differ from model attributes:

Supported Spatie SlugOptions features in preview

Multi-field source example

The form must have the fields used in extraScope / skipGenerateWhen (e.g., tenant_id, status) filled out — SlugField reads them from the live form state (data.*), not just the source fields.

Scoped unique slugs (Spatie extraScope)

Attribute-based model (Spatie v4+)

No getSlugOptions() required — SlugField reads the attribute when the method is absent.

Override Spatie for preview only

slugifyUsing() always wins over Spatie.

Force server-side preview

Spatie mode and translatable titles already use server-side generateSlugPreview. For custom slugifiers or other cases:

Custom Spatie action class

If you override config/sluggable.php → actions.generate_slug, the field uses your bound GenerateSlugAction implementation automatically.

skipGenerateWhen — preview without overwriting

In the form preview, when skipGenerateWhen returns true, the field will keep the existing slug instead of generating a new one.

startSlugSuffixFrom and collisions in preview

If my-post already exists in the database, the preview may show my-post-5 (according to Spatie rules).

Closure as slug source

The form must have the title and edition fields filled out — SlugField reads them from the live state of siblings in the schema.

usingSuffixGenerator — custom suffix


The permalink bar shows host (without https://), optional path prefix, slug segment, and optional postfix. HTTPS hosts display a green lock icon.

Subdomain style (host only)

Sandwich URL (prefix + slug + postfix)

Closure visitUrl / visitRoute receives injected: slug (string), routeKey (string — for self-healing models: hello-world-5, otherwise same as slug) and record (?Model).

Action button layout

Buttons sit below the input: Edit / OK / Cancel on the left; Regenerate / Copy / Visit on the right.
Global default: config('filament-flex-fields.slug.action_button_labels').

Uniqueness validation

Separate from Spatie’s DB suffix generation — this is form validation before save.

Default (unique in table)

Disable uniqueness check

Scoped uniqueness (tenant, locale, type, …)

Filament-style unique parameters


Homepage slug (/)

For CMS pages that should live at the site root:
Only the exact value / is allowed as a special case.

TitleSlugField factory parameters

TitleSlugField::make() is a static factory returning a FusedGroup (title + hidden auto-sync flag + slug). Example of titleUniqueParameters — unique title within tenant:
| $urlHost | ?string | config('filament-flex-fields.slug.url_host') | Permalink host | | $urlPath | ?string | null | Permalink path prefix | | $urlHostVisible | bool | true | Show host segment | | $visitLinkLabel | ?string | translated default | Visit button label | | $visitUrl | string\|Closure\|null | null | Custom visit URL; closure: slug, routeKey, record | | $showVisitLink | bool | true | Show visit action | | $slugLabelPostfix | ?string | null | Trailing URL segment after slug | | $preserveSlugOnEdit | bool\|Closure | true | Don’t auto-update slug on edit | | $translatableLocales | array\|Closure\|null | config('…slug.translatable_locales') | Enables TranslatableFields title UI; null = single-language title | | $slugSourceLocale | string\|Closure\|null | config('…slug.slug_source_locale') or app.locale | Locale whose title drives slug generation | | $requiredTitleLocales | 'all'\|list<string>\|Closure\|null | config('…slug.required_title_locales') or slug source locale only | Which title tabs are required (null = source locale only) | | $spatieTranslatable | bool\|Closure | false | Marks Spatie Translatable intent; hydrate auto-detects HasTranslations when package is present | | $titleLocaleConfigurator | ?Closure | null | fn (FlexTextInput $field, string $locale) => $field | | $translatableFieldsConfigurator | ?Closure | null | fn (TranslatableFields $fields) => $fields->… — full title tabs config | | $spatieModel | string\|Closure\|null | null | Spatie Sluggable only (HasSlug) — not Translatable | | $slugConfigurator | ?Closure | null | fn (SlugField $field) => $field->... | Example — custom title field + slug configurator:
Example — custom field names via config:

Example for each parameter of TitleSlugField::make()


SlugField — configuration API

Each method below is chainable on SlugField::make('slug').

source(string|Closure|null $statePath)

State path of the field that drives auto-generation (usually title).

sourceLive(bool|Closure $condition = true)

When false, slug does not react to source changes (manual slug only).

translatableTitle(bool|Closure $condition = true)

Enables translatable title source paths (title.pl, …). Usually set via titleLocales().

titleLocales(array|Closure $locales)

Locale map (['pl' => 'PL', 'en' => 'EN']) or list (['pl', 'en']). Implies translatableTitle(true).

slugSourceLocale(string|Closure $locale)

Which locale title drives slug auto-generation. Default: config slug_source_locale, then app.locale, then first locale.

translatableTitleField(string|Closure $fieldName)

Base title attribute when resolving source path (default: title).

spatieTranslatable(bool|Closure $condition = true)

Configuration flag for Spatie Translatable models. Hydration auto-detects HasTranslations on the record when spatie/laravel-translatable is installed — the flag does not need to be true for detection to work.

titleField(Field $field)

Attach a title field for SlugField::withTitle() / manual fused layouts.

titleFieldWrapper(?Closure $wrapper)

titleAfterStateUpdated(?Closure $callback)

slugAfterStateUpdated(?Closure $callback)

titleReadOnly(bool|Closure $condition = true) / slugReadOnly(bool|Closure $condition = true)

Blocks editing of the respective field. Works with TitleSlugField and manual SlugField::withTitle().

slugifyUsing(?Closure $callback)

Custom slugifier; receives ['source' => string].

spatieModel(string|Closure|null $modelClass)

Enable Spatie integration for preview generation.

spatieSlugField(string|Closure $attribute = 'slug')

Model attribute Spatie writes to / reads from.

spatieSourceField(string|Closure|null $field)

Primary model attribute for the live source string.

serverSideGeneration(bool|Closure $condition = true)

Use Livewire generateSlugPreview instead of client Str.slug. Automatically enabled when Spatie integration is active or when translatable titles are used.

slugSeparator(string|Closure $separator = '-')

Normalization separator (also used by fallback SlugGenerator). Default validation slugPattern is derived from this separator automatically.

maxSlugLength(int|Closure|null $length)

Max length for fallback generator; Spatie uses slugsShouldBeNoLongerThan from model.

urlHost(string|Closure|null $host) / urlPath(string|Closure|null $path)

Permalink segments. Host may include https://; display strips the scheme.

urlHostVisible(bool|Closure) / urlPathVisible(bool|Closure)

Controls which URL segments are visible in the permalink preview.

permalinkPreview(bool|Closure $condition = true)

Show or hide the entire permalink chrome.

permalinkLabel(string|Closure|null $label)

visitUrl(string|Closure|null $url) / visitRoute(string|Closure|null $route)

Target of the Visit button. The Closure receives injected parameters: slug, routeKey (self-healing: {slug}-{id}), and optionally the record.

visitLinkLabel(string|Closure|null $label)

Action toggles below the slug. By default all are true (except Regenerate — visible only after manual slug edit).
Example — Copy only, no Visit:

actionButtonLabels(bool|Closure) / actionButtonsIconOnly(bool|Closure)

Control text on action buttons (Hero UI button-group + Gravity icons).

autoUpdateDisabledField(string|Closure|null $field)

Hidden boolean field path tracking manual slug edits. TitleSlugField sets {slug}_auto_update_disabled automatically.

autoGenerate(bool|Closure $condition = true)

Main toggle for auto-generating slug from the source field.

preserveSlugOnEdit(bool|Closure $condition = true)

On the edit operation, it stops auto-sync from the title (protects published URL). On create, it always syncs.

inlineEditing(bool|Closure $condition = true)

When true (default): permalink preview + Edit/OK/Cancel/Reset buttons. When false: standard TextInput.

allowHomepageSlug(bool|Closure $condition = true)

Allows homepage slug / (CMS homepage). Requires custom validation pattern.

generationDebounce(int|Closure $milliseconds = 400)

Debounce before regenerating slug from title.

slugPattern(string|Closure $pattern) / regex(string|Closure|null $pattern)

Optional override. When omitted, pattern is auto-derived from slugSeparator() (and allowHomepageSlug() when enabled). regex() is an alias.

slugLabelPostfix(string|Closure|null $postfix)

Trailing path after slug in permalink preview.

recordSlug(string|Closure|null $slug)

Initial/stored slug for edit preview and visit link before state hydrates.

slugRules(array|Closure $rules)

Additional validation rules (besides built-in pattern and slugUnique).

slugUnique(bool|Closure $condition = true) / slugUniqueParameters(array $parameters) / slugUniqueScope(?Closure $scope) / slugUniqueModel(string|Closure|null $model)

Uniqueness validation in the form (independent of Spatie suffixes on save).

size(string|Closure $size) / variant(string|Closure $variant)

Size and visual variant of the field wrapper (Hero UI). Defaults from config('filament-flex-fields.ui').
Defaults: config('filament-flex-fields.ui.slug_size'), slug_variant.

Inherited Filament Field API

SlugField inherits standard Filament methods — they work exactly the same as in other fields:
TitleSlugField configures title and slug separately — supply slug helper text via the slugConfigurator:

Public helper methods (views, tests, extensions)

Public methods used in Blade templates, tests, and custom field extensions: Example in test:

FlexField schema keys (FieldType::Slug)

When using FlexFieldFormBuilder:

Advanced recipes

Repeater with per-row title + slug

Nested paths are resolved automatically (sections.0.title → sections.0.slug).

Standalone slug (no title field)

Regenerate button behaviour

Regenerate only appears when auto-sync has been disabled by a manual slug edit (setting the hidden field {slug}_auto_update_disabled = true). During normal syncing, the button is hidden.
Note: SlugField uses wire:ignore on the Alpine fragment — changing data.slug directly in tests might not reflect UI behavior. Test by updating the title or modifying slug_auto_update_disabled.

Playground (Live Preview)

Enable the playground in .env:
Panel navigation: Settings & Tools → Flex Fields Playground — cluster with left sub-navigation (Filament SubNavigationPosition::Start).
  • Root URL: /admin/flex-fields (redirects to first component)
  • Slug field page: /admin/flex-fields/slug-field
  • The catalog is enabled by default behind panel authentication. Set FLEX_FIELDS_PLAYGROUND=false to omit its routes, or use playground(false) for a panel. See catalog access configuration.
Spatie is optional for every recipe below. Playground demos do not require Spatie. Translatable titles use PHP generation; ordinary Latin titles use the client slugifier. To align preview and save with laravel-sluggable, see Optional Spatie upgrade (playground recipes) at the end of this section.
Source of truth: SlugFieldPlayground in the package (src/Support/Playground/SlugFieldPlayground.php). Default form state keys (slug__title, slug__standalone, …) live in SlugFieldPlayground::defaultState().

Playground recipes — 1:1 with SlugFieldPlayground

Full section schema (copy-paste ready):

Recipe 1 — Shared title source + slug field (slug__standalone)
A separate title field drives one or more slug fields on the same form. Playground reuses slug__title for recipes 1, 5, and 6.

Recipe 2 — Title + slug one-liner (TitleSlugField)

Recipe 3 — Translatable title + single slug (slug__i18n_*)
Default state shape: 'slug__i18n_title' => ['pl' => '…', 'en' => '…'], 'slug__i18n_slug' => 'przewodnik-po-morzu-srodziemnym'.
Recipe 4 — Title + slug pair (titleField() + recordSlug())

Recipe 5 — Permalink preview + Visit link (slug__permalink)
Uses the shared title field from recipe 1 (slug__title).

Recipe 6 — URL slug sandwich (slug__sandwich)
Uses the shared title field from recipe 1 (slug__title).
Preview: wyachts.test/books/my-slug/detail/
Recipe 7 — Read-only variants (grid)
Spatie: optional for all three.

Optional Spatie upgrade (playground recipes)

None of the playground recipes require composer require spatie/laravel-sluggable. Add it only when you need model-level suffixes (-2), preventOverwrite, extraScope, or identical rules on save and in the form preview. TitleSlugField recipes (2, 3):
SlugField recipes (1, 4–7):
Full integration: Spatie laravel-sluggable integration (install, HasSlug, getSlugOptions(), #[Sluggable], translatable models).

Playground quick reference

Translations

Publish translation files:
Override in lang/vendor/filament-flex-fields/{locale}/default.php. UI Keys (slug.*): Validation (validation.slug.*): Custom labels without publishing — override directly on the field:
Set your application locale (app.locale = pl) to load built-in translations if desired.

Troubleshooting

Diagnostics in tinker / test:

Comparison with blendbyte/filament-title-with-slug


Playground

Slug: slug-field /admin/flex-fields/slug-field — see Playground.

Editor transaction and shared rendering (2026-10 reconstruction)

SlugField now renders one native input through the shared FLEX text-input primitive. Its Edit/OK/Cancel/Reset and permalink commands use the shared SegmentControl renderer in command mode. These buttons do not submit a form or change a selected radio/tab value. Edit and Cancel update local state and deferred Livewire metadata; they do not request a page render. Edit creates a draft while retaining the committed slug. OK validates configured slug rules and live uniqueness through a renderless schema method when required; a failed request leaves the draft open. Cancel restores the latest committed value. Reset regenerates from the current source and restores auto-sync only after generation succeeds. Late responses cannot overwrite a newer edit, source value or disposed field. Direct editing keeps the raw native input value while typing, then displays the normalized slug on blur. Source and metadata paths follow the mounted schema, including custom form roots and nested containers. Title templates are cloned instead of accumulating callbacks. Optional Spatie preview generation uses a cloned record so opening the form does not mutate its original model. Custom slugifyUsing() callbacks run in PHP automatically. Custom permalink callbacks are evaluated for the current committed value, including Copy after regeneration. Uniqueness settings are evaluated at validation time. Query scopes and modifyRuleUsing constraints apply to the same candidate records. For a table with a nonstandard primary key, set identityColumn in slugUniqueParameters when combining a scope with modifyRuleUsing; an Eloquent model supplies its key automatically. Keep a database unique constraint for concurrent writes. The homepage value / is explicitly accepted by allowHomepageSlug() even with a custom ordinary-slug pattern; other configured validation rules still apply. The editor displays the fixed URL slash once and an empty editable segment. PHP examples live in resources/examples/slug-field/usage.php and are loaded by the catalog page, not by application forms.

Rebuilt optional Spatie integration (Sluggable v4)

SlugField supports Sluggable v4 without requiring it on pages that do not use a sluggable model. The shared adapter delegates native generation to Spatie; PHP option resolution, disposable model hydration, generation policies and uniqueness queries live in separate Support/Slug/Spatie/ modules.
Configure Article::getSlugOptions() as usual: multiple source fields/source closures, language, source length, separator, scopes, suffixes, create/update flags, skip conditions and prevent-overwrite are preserved. A field with no explicit separator inherits the actual model separator. Native allowDuplicateSlugs() also controls the default validation policy; explicit slugUnique() can enforce uniqueness instead. Native source length is not the same as a final output-length limit (suffixes may extend the result). Automatic previews respect model policies. Explicit Reset/Regenerate invokes manual generation semantics and bypasses automatic create/update/skip/overwrite restrictions. It still preserves a slug that native Spatie considers customized. Generation uses a clone: previews do not persist data, alter model originals or change the caller’s locale. Cached native options are cloned as well. For HasTranslatableSlug + optional HasTranslations, choose the source locale with slugSourceLocale('pl'); exact regional keys such as pt_BR are supported. Only the selected locale is generated/checked in the editor, without copying fallback values into a missing translation. Other model locales remain intact. Native translated customization rules and per-locale JSON collision checks are retained. Final validation uses the same model scope and selected locale. A field represents one scalar slug; it does not turn a single editor into an entire JSON translation map. Compose locale editors/storage with TranslatableFields when editing/persisting multiple slug translations. Configured/model-overridden generation actions and configured self-healing route key actions are used. Self-healing visit/copy URLs resolve server-side against the current committed slug. If a custom action changes the collision domain, configure matching slugUniqueScope/slugUniqueParameters for manual validation. The adapter targets v4; its confined translated bridge needs compatibility verification on dependency upgrades. A source/output contradiction (for example native source slug while the editor source is title) is rejected with a configuration error rather than producing an unrelated suffix. For domain-level integrations, SpatieSlugIntegration::preview(...) returns an immutable result (value, generated, skipReason); generate(...) retains the string API. Both accept optional force and current-form slug parameters.
Last modified on October 29, 2026