phil / social-cards
Share metadata as values: Open Graph, X and fediverse tags, 1200×630 share cards drawn from a declarative template, and the tags of linked pages read and checked
Requires
- php: >=8.5
- ext-ctype: *
- ext-dom: *
- ext-gd: *
- ext-intl: *
- ext-libxml: *
- ext-mbstring: *
- ext-uri: *
- phil/fonts: ^0.1@dev
- phil/url: ^0.1@dev
Requires (Dev)
- phpunit/phpunit: ^13.4
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-11-12 23:53:19 UTC
README
What a page says of itself when it is shared: Open Graph, X and fediverse tags, a 1200×630 card drawn from a template, and the tags of linked pages read and checked.
phil/social-cards models the share metadata of a page as a value: its title and description, its canonical address,
its image and the text that replaces it, its Open Graph type, its locale and the locales it is also written in, its
site, its author and dates, and the accounts of the site and of the author on X and on the fediverse. MetaTags
writes them as the canonical link, the description, the Open Graph tags, the article: tags of an article, the card
of X and fediverse:creator, escaped for HTML.
A page without an image of its own gets a card: GdCardRenderer draws a 1200×630 PNG from a declarative
CardTemplate — a background colour or image, an accent band, a logo, the fonts and colours of the title and subtitle
—, fitting the title by shrinking it between two sizes and breaking its lines by the rules of its language, then
cutting it with an ellipsis when it still does not hold. The fonts are read by phil/fonts. The same template and
content always draw the same bytes, and CardGenerator keeps each card under a fingerprint of everything it shows.
The other way, TagReader reads the tags of a page of another site — bounded in bytes, tags and lengths, parsed by
the HTML5 parser of PHP —, LinkPreview makes the card of a link from them, LinkFinder finds the links a member
pasted in a text, and TagCheck says what is missing or wrong in the tags of a page.
The cards are drawn by GD, without text shaping: Latin, Greek, Cyrillic and the scripts of China, Japan and Korea draw well; Arabic, Hebrew and the scripts of India do not, as the cards explain.
It is a plain PHP library: PHP 8.5 with the ctype, DOM, GD, intl, libxml, mbstring and URI extensions, and phil/fonts. In a Symfony application, phil/social-cards-bundle sets the tags of each page from a Twig function, serves the cards, draws them in a worker, fetches linked pages safely and checks a page from the command line.
Status
| Part | State |
|---|---|
ShareMetadata, ShareImage, ShareType, TwitterCard, MetaTags |
Implemented and tested |
CardTemplate, CardFont, CardImage, Color, CardContent |
Implemented and tested |
LineBreaker, TextFitter, GdCardRenderer, CardGenerator, the stores |
Implemented and tested |
TagReader, PageTags, LinkPreview, TagCheck |
Implemented, tested and fuzzed |
LinkFinder |
Implemented, tested and fuzzed |
Documentation
| Document | What it covers |
|---|---|
| Installation | Requirements and the extensions used. |
| Share tags | The share metadata, its rules, and the tags written. |
| Cards | Templates, fonts, the fitting of the title, the drawing, fingerprints and stores. |
| Previews and checks | Reading the tags of a page, link previews, the links of a text, the check of a page's tags. |
| Exceptions | What is thrown, and when. |
| Extension points | The ports an application implements or replaces. |
| Reference | Every type of the library. |
| Testing | How the library is tested, benchmarked and fuzzed. |
Quick start
use Phil\SocialCards\Card\{CardContent, CardGenerator, CardTemplate, DirectoryCardStore, GdCardRenderer}; use Phil\SocialCards\{MetaTags, ShareMetadata}; $template = CardTemplate::fromArray(['title_font' => '/fonts/Inter-Bold.ttf', 'accent' => '#e11d48']); $cards = new CardGenerator(new GdCardRenderer(), new DirectoryCardStore('/var/cards')); $card = $cards->generate($template, new CardContent('Release notes', 'What changed this month', 'en')); echo MetaTags::html(MetaTags::of(ShareMetadata::fromArray([ 'title' => 'Release notes', 'url' => 'https://example.com/releases', 'description' => 'What changed this month', 'image' => ['url' => "https://example.com/cards/{$card->fingerprint}.png", 'alt' => 'Release notes', 'width' => 1200, 'height' => 630], 'site_name' => 'Example', 'fediverse_creator' => '@team@example.social', ])));
Requirements
PHP 8.5 or later, with the ctype, DOM, GD (with FreeType), intl, libxml, mbstring and URI extensions, and
phil/fonts.
Contributing
Contributions are welcome on the PHIL monorepo: read the contribution guide and the code of conduct. Report a vulnerability privately, as the security policy explains, never in a public issue.
License
MIT, © Philippe Gamache, doing business as Le Gnome Archiviste; a Parler Haut Interagir Librement project. See LICENSE.