vhbelvadi/bluesky-feed
A Laravel package for integrating Bluesky (AT Protocol) feeds into your application. Fetch posts from public feeds, configure handles and limits, and render results in Blade views through a simple, lightweight API.
Version 1.5.0 is a purely additive release: the reply/quote renderer now resolves four new namespaced placeholders — {{ original:poster }}, {{ original:name }}, {{ original:avatar }} and {{ original:text }} — so a rendered reply can pull author and body data from the post being replied to, not just from the reply itself.
Start here:
composer require <vendor>/<package> (or composer update <vendor>/<package> if already present). Laravel auto-discovery should register the service provider; if not, add it to config/app.php.php artisan vendor:publish --provider="...\ServiceProvider". The reply template (usually a Blade view under resources/views/vendor/<package>/) is where the placeholder strings actually live. This is the first file to open.{{ poster }}, {{ name }}, {{ avatar }} or {{ text }}. The new original: tokens are the same fields, resolved against the parent post.First real use case: a threaded forum or comment feed. When rendering reply R to post P, your template can now show P's author and a snippet of P's body inline:
<div class="reply">
<img src="{{ original:avatar }}" alt="{{ original:name }}">
<span class="replying-to">Replying to {{ original:poster }}</span>
<blockquote>{{ original:text }}</blockquote>
{{ text }}
</div>
Render with the original attached. The placeholders can only resolve if the renderer receives the parent post. Pass the reply and its original together (or ensure the reply model's original / parent relation is loaded) — an unloaded relation is the most common reason the tokens come out blank.
$html = ReplyRenderer::render($reply, original: $reply->parent);
Keep the two namespaces straight. Unprefixed tokens ({{ name }}, {{ text }}) describe the current post; original: tokens describe the parent. A quote block typically uses only original:* plus the reply body, which keeps templates readable.
Customize per-context. Because these are template-level tokens, you can ship different reply templates (compact feed view vs. full thread view) and swap them by config or by publishing a variant view. Use original:poster for a linked username and original:name for the plain display name — they diverge when a user has renamed or deleted their account.
Compose with existing Blade. The tokens interpolate into ordinary Blade, so wrap them in components, apply Str::limit()-style truncation to original:text, and link with your route helper around original:poster.
Test the output, not the token. Feature-test the rendered string so upgrades like 1.5.0 can't silently change layout:
$response->assertSee($parent->author->username);
original:* renders empty, check that the parent is loaded — Reply::with('original.author')->paginate() avoids both the blank output and an N+1 per reply.@if/?-> and fall back to a "post unavailable" notice rather than emitting an empty <blockquote>.original:text is the risky one. It is user content inside a blockquote. Confirm whether it is escaped or raw before trusting it; if raw, sanitize on write or run it through your HTML purifier. Nested quotes can also recurse — cap quote depth or strip nested reply blocks before rendering.{{ original:avatar }} will happily output an empty src. Pair it with a default image or ?->avatar_url ?? asset('img/default.png').poster vs name. poster is generally the identity used for the link/mention; name is the display string. Using name as the link text produces dead-looking links after a rename.config:cache, view:cache), placeholder changes won't appear until you rebuild — a classic "my new tokens don't render" false alarm.original:* resolvers (e.g. original:url) instead of forking the template.How can I help you explore Laravel packages today?