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

Url Link Type Extension Laravel Package

anomaly/url_link_type-extension

A PyroCMS/Laravel addon that adds a URL link field type to the Streams platform, letting editors add and validate external links as a reusable field type in your modules and addons. Lightweight and simple to register.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a small PyroCMS/Streams Platform addon that contributes one thing: a URL link type to the Navigation module's link picker. Without it, navigation links can only point at pages, and you have to hard-code external or arbitrary URLs elsewhere. With it, a nav item can point at https://…, /relative/path, tel:, mailto:, or an anchor.

Requirements first. It is a satellite of anomaly/navigation-module — it does nothing on its own. Confirm you are on PyroCMS 3.x / Streams Platform and that the Navigation module is installed and migrated before touching this.

composer require anomaly/url_link_type-extension
php artisan addon:install anomaly.extension.url_link_type

If your project doesn't auto-discover addons, register the service provider in config/app.php (or your addons config) as Anomaly\UrlLinkTypeExtension\UrlLinkTypeExtensionServiceProvider.

Where to look first. Open the addon's service provider and its link type class — the whole package is roughly one class plus a composer.json and lang/ directory. The class will extend the Navigation module's base link type and declare a slug (typically url), a name, and a form section. Every behaviour you care about is in that one class: the form fields it exposes (url, target, maybe rel), how it validates them, and how it renders the href.

First use case. Go to Navigation → Links → Create, and confirm URL now appears in the link type dropdown alongside Page. Create a link with label Docs, URL https://example.com/docs, target _blank, attach it to your main navigation, then render with:

{{ nav('main') }}

If Docs renders with the right href, the addon is wired correctly and the rest is configuration.

Implementation Patterns

Treat it as a link type, not a page replacement. The intended workflow is: content editors add external/legacy URLs to menus in the control panel; developers keep page links as page links. Mixing both in one menu is the normal case and works fine — each link stores its own type and entry payload.

Seeding links in code. For deployments and tests, create URL links through the Navigation repository rather than inserting rows by hand, because the link type owns validation of the entry payload:

use Anomaly\NavigationModule\Link\Contract\LinkRepositoryInterface;

app(LinkRepositoryInterface::class)->create([
    'navigation' => 'main',
    'title'      => 'Docs',
    'link_type'  => 'anomaly.extension.url_link_type',
    'entry'      => [
        'url'    => 'https://example.com/docs',
        'target' => '_blank',
    ],
    'sort_order' => 10,
]);

Verify the exact link_type slug against the addon's link type class — it is the one string every seeder, fixture, and migration depends on, and it is not stable across forks.

Building a link resolver in your theme. If you need the raw target (for analytics attributes, JSON-LD, or a custom menu component), iterate the navigation's links and branch on the type instead of relying on nav():

@foreach($navigation->links as $link)
    @if($link->link_type === 'anomaly.extension.url_link_type')
        <a href="{{ $link->entry->url }}"
           target="{{ $link->entry->target ?: '_self' }}"
           rel="{{ $link->entry->target === '_blank' ? 'noopener noreferrer' : '' }}">
            {{ $link->title }}
        </a>
    @endif
@endforeach

Multi-locale menus. The Navigation module stores link titles per locale; the URL itself usually does not get translated. If you need locale-specific destinations (e.g. /en/pricing vs /fr/tarifs), either create a link per locale or store the path relative (/pricing) and prefix at render time. The addon gives you a single URL string — plan for this before editors start building menus.

Integration tips. Use relative URLs for anything internal that may move between domains or environments; use the addon only for the truly external stuff. Cache-bust menus after deploys (php artisan cache:clear) because nav() caches the compiled tree — a stale href after a content edit is almost always cache, not the addon.

Gotchas and Tips

Zero stars, zero dependents, no maintenance signal. This is effectively an internal Anomaly Labs artifact. Pin it to a commit in composer.json, vendor it into your repo, or fork it. Do not assume a Laravel 10/11 or Streams 1.4+ upgrade path exists — if the Navigation module's link type contract changed, this addon will fatal on boot with a signature or abstract-method error. Test installs on a fresh environment, not just your already-warm dev box.

No URL sanitisation out of the box. The field is typically a plain url or text input. That means javascript:alert(1) can end up in an href if you let untrusted users into the control panel. Either restrict who can manage navigation, or add a validation rule / mutator on the link type that enforces a scheme allowlist (http, https, mailto, tel, and leading /).

target="_blank" without rel. The addon stores the target; it does not necessarily emit rel="noopener noreferrer". Browsers have largely fixed window.opener abuse, but for audit compliance add the rel in your template override rather than trusting the stored markup.

Empty URL is a silent failure. If url is not required in the link type's form, an editor can save a URL link with a blank URL and you get <a href=""> — which reloads the current page. Add required to the field, or guard in the template: @if($link->entry->url).

Trait/interface mismatch is the most common breakage. The link type extends something like Anomaly\NavigationModule\LinkType\LinkType and implements LinkTypeInterface. If you are debugging an addon:install failure, diff this class against a known-working link type shipping with the Navigation module (usually the Page link type) — that diff tells you exactly what the contract expects for your version.

Extension points are thin, by design. There are no events to hook here. If you need conditional URL resolution (AB tests, geo redirects, signed URLs), do it in the template or in a small custom link type of your own — copying this package's ~4 files is genuinely the recommended path. It is a reference implementation as much as a dependency.

Blade overrides need a publish step. If the addon ships a view for link rendering and you need to change the markup, publish assets (php artisan addon:publish anomaly.extension.url_link_type) or override the view path in your theme — editing inside vendor/ will be wiped by the next composer install.

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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource