v2.1.0: listing SEO bug fixes, schema completion, search, pagination#12
Merged
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
This PR prepares a v1.5.0 release focused on public blog SEO correctness, structured data, search, and accessible pagination.
Changes:
- Adds listing SEO helpers, sitemap tag URLs, post/listing schema emission, and controller SEO wiring.
- Adds portable post search plus a Livewire search component.
- Adds numbered pagination views, docs, tests, and changelog updates.
Reviewed changes
Copilot reviewed 30 out of 30 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Support/SchemaExtractor.php | Adds FAQ/HowTo schema extraction helpers. |
| src/Support/BlogListingSeo.php | Adds listing SEOData factory methods. |
| src/Models/Post.php | Adds search scope and FAQ schema wiring. |
| src/Livewire/BlogSearch.php | Adds Livewire search component. |
| src/Http/Controllers/BlogController.php | Wires search, pagination query strings, and SEO calls. |
| src/FilamentBlogServiceProvider.php | Registers SEO transformers, Livewire component, and TagManager singleton. |
| src/BlogSitemapGenerator.php | Adds tag archive URLs to sitemap generation. |
| resources/views/** | Adds pagination/search views and updates listing links/cards. |
| config/filament-blog.php | Adds schema and search configuration. |
| docs/**, README.md, CHANGELOG.md | Documents new SEO, schema, search, pagination, and release changes. |
| tests/** | Adds coverage for sitemap tags, listing SEO/schema, FAQ/HowTo schema, search, pagination, and Livewire search. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+83
to
+84
| if (! $post instanceof Post && ($slug = $route?->parameter('slug')) !== null) { | ||
| $post = Post::query()->published()->where('slug', $slug)->first(); |
Comment on lines
+67
to
+68
| preg_match_all( | ||
| '/<h3[^>]*>(.+?)<\/h3>\s*<p[^>]*>(.+?)<\/p>/is', |
Comment on lines
+19
to
+22
| // The shipped package controller does not call seo()->for() in show(). | ||
| // Consumers override the controller to do so (see Post::getDynamicSEOData | ||
| // for the article + FAQ schema wiring). We simulate that here by binding | ||
| // a fresh TagManager and pointing it at the post we want to render. |
Comment on lines
+42
to
+44
| | Set `callback` to a closure `(Builder $query, string $term): void` to | ||
| | use Postgres FTS, MySQL FULLTEXT, Scout, Meilisearch, or any other | ||
| | backend. |
Comment on lines
+29
to
+34
| 'search' => [ | ||
| 'callback' => function (\Illuminate\Database\Eloquent\Builder $query, string $term): void { | ||
| $query->whereRaw( | ||
| "to_tsvector('english', title || ' ' || excerpt || ' ' || content) @@ plainto_tsquery('english', ?)", | ||
| [$term] | ||
| ); |
Ports the v1.5.0 work to the Relaticle\Ink namespace after the v2.0.0 rename landed in main. No behavior changes vs the original v1.5.0 PR — pure namespace adaptation. Adds: - BlogListingSeo helper for per-page canonicals on listing routes - Post::search scope with config-driven callback hook - FAQPage + HowTo + Blog + CollectionPage JSON-LD auto-emission - Numbered, aria-labeled pagination view - BlogSearch Livewire component - wire:navigate on post-card Fixes: - Tag URLs in BlogSitemapGenerator - Per-page canonicals on /blog?page=N - seo()->for(\$post) called on show/preview See CHANGELOG.md and PR description for full details.
b3b3106 to
e77715f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A coherent v1.5.0 release covering listing-page SEO correctness, schema completion (FAQPage + HowTo + Blog + CollectionPage), portable search, and an accessible numbered pagination view.
Driven by gaps surfaced during a 3-month blog launch on a consumer project. The work was prototyped there first and is now generalized for the package.
Fixed (bugs)
BlogSitemapGeneratornow iterates/blog/tag/{slug}URLs whenfeatures.tagsis on. The package docs document tag routes as first-class but the sitemap was silently skipping them./blog,/blog/category/{slug},/blog/tag/{slug}) now emit per-page canonical URLs and page-aware titles via a newBlogListingSeohelper. Previously every paginated page canonicalized to page 1.showandpreviewroutes now callseo()->for($post)so post-attached SEO (BlogPosting + BreadcrumbList + FAQPage) actually renders in public-routes mode. Previously the schema only fired for consumers who overrode the controller.Added (features)
FAQPageJSON-LD auto-emit from## FAQsections (default on; toggle viaschema.faq_auto).HowToJSON-LD auto-emit from## Stepssections (opt-in viaschema.howto_auto).Blog+CollectionPageJSON-LD on listing routes.blog::pagination.blog.wire:navigateon<x-blog::post-card>post-link and pagination links.Post::search($term)scope (portable LIKE default, override viasearch.callback).?q=honored on shipped/blogroute withnoindex,followon result URLs.BlogSearchLivewire component (<livewire:blog::search />).search.md,schema.md,listing-seo.md.ManukMinasyan\FilamentBlog\Support\BlogListingSeohelper (also usable from headless consumers).ManukMinasyan\FilamentBlog\Support\SchemaExtractorhelper for FAQ + HowTo HTML parsing.Internal changes worth flagging
FilamentBlogServiceProvidernow bindsRalphJSmit\Laravel\SEO\TagManageras a singleton inpackageRegistered(). Without this,seo()->for(...)in controllers does not persist to{!! seo() !!}in layouts — the singleton binding is required for the documented usage pattern butralphjsmit/laravel-seodoesn't ship it. If you'd prefer to require consumers to bind it themselves, that's a one-line revert; flagged so you can choose.<livewire:blog::search />(with::in the name) doesn't resolve through Livewire's standard::component()registration. Worked around with aLivewire::resolveMissingComponentcallback. If you'd prefer to renameBlogSearch→Search(canonical Livewire convention) and drop the workaround, easy follow-up.Backward compatibility
## FAQH2 they didn't intend as FAQ schema (setschema.faq_auto = falseto opt out).schema.faq_autodefaults totrue.schema.howto_autodefaults tofalse(opt-in).<title>tag on paginated pages (now suffixed with— Page N) and the<link rel="canonical">URL on pages 2+. This is SEO-correct behavior; consumers relying on the broken previous behavior will see indexing changes.Test plan
vendor/bin/pest --compact— 58 passed, 118 assertions (was 23 onmain)vendor/bin/pint --test --format agent— clean## FAQsection, validate at https://search.google.com/test/rich-results## Stepsandschema.howto_auto=true, validate HowTo/blog/tag/{slug}URL appears/blog?page=2on a consumer with 15+ posts, verify canonical and— Page 2titleProvenance
Implementation plan traceable at
docs/superpowers/plans/2026-05-13-filament-blog-v1.5.mdin the consumer project that drove this work.The commits are individually testable — each task ships its own tests and committed together with the implementation: