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

Brevity Laravel Package

kylewm/brevity

Brevity is a URL shortener for Laravel: create short links, redirect visitors, and track hits. It offers a simple, self-hosted alternative to third-party services, with configurable length and custom slugs.

View on GitHub
Deep Wiki
Context7

Getting Started

kylewm/brevity is not the link shortener the package description claims — it is a small, dependency-free text truncation utility (a port of the Known/Clearbit "brevity" algorithm). It trims a block of plain text to a target length while trying to avoid chopping words, URLs, @mentions, or #hashtags mid-token. There is no service provider, facade, config file, or Artisan command. Treat it as a leaf library you call from your own code, not a framework component.

Minimal steps:

  1. Install it:
    composer require kylewm/brevity
    
  2. Read src/ before writing code against it. The repo is unmaintained and thinly documented; confirm the exact namespace and the shorten() signature (typically shorten(string $text, int $limit): string) rather than trusting the README.
  3. Sanity-check behaviour in a REPL:
    php artisan tinker
    >>> \Kylewm\Brevity\Brevity::shorten('A long post with a link https://example.com/a/very/long/path and trailing words', 100);
    
    Try it with a URL, an emoji, and CJK text before you commit to the dependency.
  4. First real use case: OG/Twitter card descriptions for a blog post or product page. It is read-only, no database writes, no queue — one computed string in a Blade layout or a Post accessor. That gets you value with near-zero blast radius.

If the spike above shows bad behaviour on your real content, stop and vendor the file (see Gotchas) — the algorithm is ~40 lines and CC0-1.0 means you can copy it into app/Support/ with no attribution obligation.

Implementation Patterns

Wrap it, don't sprinkle it. Because there is no Laravel integration, bind a thin application-owned service in a provider so you can swap the implementation without touching product code:

// app/Support/Text/PostTruncator.php
namespace App\Support\Text;

class PostTruncator
{
    public function shorten(string $text, int $limit = 280): string
    {
        // Brevity assumes plain text — normalise first
        $text = trim(strip_tags($text));

        return \Kylewm\Brevity\Brevity::shorten($text, $limit);
    }
}

Inject this into controllers, jobs, and Blade components. Never call the vendor class from models, jobs, or templates directly — that is the one integration decision that determines how cheap replacement will be later.

Model accessor for previews. Expose a tweet-length preview without mutating stored content:

protected function tweetPreview(): Attribute
{
    return Attribute::get(fn () => app(PostTruncator::class)
        ->shorten($this->body, 280));
}

Shorten once, at the point of dispatch. In a cross-post job, compute the truncated string immediately before you hand it to the outbound payload and persist it there. If the Blade preview and the job each recompute independently, the user can see one string and the platform can receive another.

Chained limits are fine. Rendering both a 160-char card description and a 280-char tweet? Shorten at the longer limit once and again at the shorter one. The algorithm is cheap, and double-truncation of already-truncated text generally behaves — just watch for the double-ellipsis case noted below.

Notifications and SMS. The URL-preservation behaviour matters most here: a Notification body capped at ~140 chars with a chopped https://… link is worse than no link. Shorten the body, then append the link separately if you can.

Blade layout component. The OG tag is the canonical home:

<meta property="og:description"
      content="{{ app(\App\Support\Text\PostTruncator::class)->shorten($post->excerpt ?? $post->body, 160) }}">

Sequencing when migrating existing truncation. If you currently use substr or Str::limit, introduce the wrapper behind a feature flag and diff outputs on production-shaped content (URLs, emoji, CJK, HTML) before rolling it into any persistence or publishing path.

Gotchas and Tips

  • The description is wrong. composer require for a "short, shareable links" library will get you a truncation helper. Read the source on day one; don't build a redirect table around it.
  • URL weighting is not t.co. X counts every URL as 23 characters; brevity counts the real string (or treats it as atomic). If you are enforcing a hard 280 for the X API, treat the output as an upper bound and validate against the platform's own counter before posting.
  • CJK and emoji are counted as characters, not weighted codepoints. For international audiences the result is approximate. Ensure mbstring is installed — the package relies on mb_* functions and will misbehave on byte-oriented fallbacks.
  • Feed it plain text. strip_tags() or a renderer's text output first. Passing HTML counts tag characters and can chop inside a tag, producing mangled output downstream.
  • No extension points. No hook, formatter, or config for ellipsis style or URL weight. Post-process in your wrapper (strip trailing punctuation, swap the ellipsis, re-append a shortlink) rather than patching the vendor file.
  • Don't trust it as the only guard. Add a final Str::limit($result, $limit, '') after it as a belt-and-braces check — there is no guarantee it never exceeds the limit by a character on edge cases.
  • Debugging truncation surprises: log mb_strlen($text) before and after, plus mb_strlen($output). The recurring bugs are whitespace-only or very short inputs round-tripping oddly, and a double ellipsis when you shorten already-shortened text.
  • Pin the version. 12 stars, 0 dependents, no release cadence — composer update will not bring fixes. Run your suite on your target PHP version and accept ownership.
  • Vendoring is the durable option. CC0-1.0, ~40 lines, one file. Copying it into app/Support/ with a credit comment is often safer than a Packagist dependency you must keep patching around, and it removes the "unmaintained transitive dep" conversation from future security reviews.
  • Scope discipline. Decide explicitly whether the product needs approximate truncation (previews, admin lists, meta descriptions — this package) or exact Twitter-aware counting (weighted URLs, CJK, emoji — a separate build). Mixing the two expectations produces the "your post is too long" bug that only appears with links and emoji.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console