Add OpenGraph images and SEO meta tags to plugin pages#407
Merged
Conversation
Plugin listing pages had no per-plugin <title>/OpenGraph tags, so social shares fell back to the generic site card. This adds: - SEO/OG/Twitter meta (title, description, image) on the plugin show and license pages, mirroring the blog controller pattern. - Generated OG images via TheOg (like blog posts): a queued GeneratePluginOgImage job renders to the public disk and stores the URL on a new plugins.og_image column. Dispatched from PluginSyncService and Filament EditPlugin so images stay fresh. - A PluginOgLayout that renders plugin version, required NativePHP Mobile constraint, and iOS/Android minimums as rounded "pill" badges (composed from rectangles + circles via a PillBox feature, since Intervention has no rounded-rect primitive). - A plugins:generate-og-images command to backfill existing plugins. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The plugin deleting hook resolves SatisService, whose constructor assigns the (string-typed) api key from config. In CI SATIS_API_KEY is unset, so the null config value triggered a TypeError. Mock the service in the deletion test (matching existing Satis test conventions) since the test only exercises OG image cleanup. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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
Plugin listing pages had no per-plugin
<title>or OpenGraph/Twitter tags, so social shares fell back to the generic site card. This adds proper SEO metadata and a generated OG image for every plugin, mirroring how blog posts already work.What changed
PluginDirectoryControllernow sets the title, description, and OpenGraph/Twitter tags on both the plugin show and license pages (following the existingShowBlogControllerpattern).GeneratePluginOgImagejob renders an image to the public disk and stores its URL on a newplugins.og_imagecolumn. It's dispatched fromPluginSyncService::sync()(the single content pipeline — webhooks, the customer create flow, and theSyncPluginjob) and from FilamentEditPlugin::afterSave(), so images stay fresh. TheOgImageServicewas refactored to share its rendering between articles and plugins; the article path is unchanged.PluginOgLayoutrenders the plugin version, requirednativephp/mobileconstraint, and iOS/Android minimum versions (shown with a+, e.g.iOS 18.2+) as rounded pill badges. Intervention has no rounded-rectangle primitive, soPillBoxcomposes a stadium shape from a rectangle + a circle at each end.php artisan plugins:generate-og-images [--missing]generates images synchronously for existing plugins (no queue worker required).Why
Shared plugin links (Slack, X, etc.) now show a branded, per-plugin card with the plugin's name, description, and platform/version support instead of a generic fallback.
Testing
PluginShowSeoMetaTest(title + OG/Twitter meta, generated-image usage, default fallback, license page).PluginOgImageTest(job renders + stores the image, sync dispatches the job, delete cleanup, pill label composition incl. the+minimum behavior, backfill command).PluginSyncServiceTestupdated to fake the queue so it stays a focused unit test.Note
Existing plugins won't have an image until their next sync/edit or a run of
plugins:generate-og-images. Generation is queued, so a worker (Horizon) must be processing the queue.🤖 Generated with Claude Code