PHPackages                             3neti/og-meta - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. 3neti/og-meta

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

3neti/og-meta
=============

Service-centric Open Graph meta tag generation with resolver-based architecture

v1.0.0(3mo ago)09↓90%MITPHPPHP ^8.2

Since Mar 26Pushed 3mo agoCompare

[ Source](https://github.com/3neti/og-meta)[ Packagist](https://packagist.org/packages/3neti/og-meta)[ RSS](/packages/3neti-og-meta/feed)WikiDiscussions main Synced 3w ago

READMEChangelog (1)Dependencies (4)Versions (2)Used By (0)

OG Meta
=======

[](#og-meta)

Auto-generate Open Graph images for link previews (WhatsApp, iMessage, Facebook, Viber, etc.). Renders status-aware card images with optional splash HTML content.

Two rendering modes:

- **screenshot** — Cloudflare Browser Rendering via `spatie/laravel-screenshot`. Full HTML/CSS support including Tailwind, images, and custom fonts.
- **gd** — PHP GD library. No external service needed but limited to plain text and base64 image overlays.

Controlled by `og-meta.renderer` config key.

Architecture
------------

[](#architecture)

```
Request → InjectOgMeta middleware → OgMetaService → Resolver → OgMetaData
                                         ↓
                                   OgImageRenderer
                                    ├── screenshot → Blade template → Cloudflare API → PNG
                                    └── gd → PHP GD functions → PNG
                                         ↓
                                   Storage (public disk) → cache hit on next request

```

**Middleware flow**: The `og-meta` middleware calls a resolver for the current route, gets `OgMetaData`, and shares `$og` view data (title, description, image URL) for the `` tags in ``.

**Image flow**: When a crawler fetches the `og:image` URL (`GET /og/{resolverKey}/{identifier}`), `OgImageController` calls the same resolver, renders the card via `OgImageRenderer`, caches the PNG to disk, and serves it with `Cache-Control` headers.

### Key Files

[](#key-files)

FilePurpose`src/Data/OgMetaData.php`DTO — all card fields and OG tag values`src/Contracts/OgMetaResolver.php`Interface — resolvers implement this`src/Resolvers/ModelOgResolver.php`Abstract base — handles model lookup boilerplate`src/Services/OgImageRenderer.php`Renders images (screenshot or GD mode)`src/Services/OgMetaService.php`Orchestrates resolvers and rendering`src/Http/Controllers/OgImageController.php`Serves images at `GET /og/{resolverKey}/{identifier}``src/Http/Middleware/InjectOgMeta.php`Shares `$og` view data for meta tags`resources/views/card.blade.php`HTML template for screenshot mode`resources/views/tags.blade.php``` tag partial for ``Card Blade Template — Design Reference
--------------------------------------

[](#card-blade-template--design-reference)

**Location**: `resources/views/card.blade.php`

This is the HTML template rendered to a PNG via Cloudflare Browser Rendering in screenshot mode. Designers and AI agents should understand this layout when customizing the card appearance.

### Canvas

[](#canvas)

- **Dimensions**: 1200×630px (OG standard — required by Facebook, WhatsApp, iMessage)
- **Format**: Full HTML document with ``, ``, ``
- **Styling**: Tailwind CSS via CDN, Inter font (400/600/700/900) via Google Fonts

### Layout Structure

[](#layout-structure)

Centered, full-width layout — the voucher code is the dominant element:

```
┌──────────────────────────────────────────────────────┐
│  48px padding — status-colored background             │
│  ┌────────────────────────────────────────────────┐  │
│  │                                                │  │
│  │  REDEEM-X (small, gray, top-left)              │  │
│  │                                                │  │
│  │            ║   R2PQ   ║                        │  │
│  │               ₱50.00                           │  │
│  │       [REDEEMABLE]  [CASH]                     │  │
│  │                                                │  │
│  │                                                │  │
│  └────────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────────┘

```

- **Code**: 7xl font-black, centered, flanked by `║` parallel line decorators (gray-200, font-thin)
- **Amount**: 4xl font-semibold, gray-700, centered below code
- **Badges**: Pill-shaped (`rounded-full`), side by side. Type badge (gray-100 bg, gray-500 text) + Payee badge (gray-700 bg, white text)
- **App name**: Absolute positioned top-left, sm uppercase tracking-wider, gray-300

### Template Variables

[](#template-variables)

VariableTypeDescription`$bgColor`stringCSS `rgb()` for outer background (from status config)`$badgeColor`stringCSS `rgb()` for status badge (from status config)`$appName`stringApp name shown top-left`$headline`stringLarge centered text (e.g. voucher code)`$subtitle`?stringSecondary centered text (e.g. amount)`$status`stringDrives background color (not rendered as badge)`$payeeBadge`?string`$typeBadge`?stringType badge label (e.g. "redeemable", "payable")### Status Colors

[](#status-colors)

Colors are defined as RGB arrays in `config/og-meta.php` and converted to CSS `rgb()` strings by `OgImageRenderer::statusCssColor()`:

StatusBackgroundBadge`active``rgb(220, 252, 231)` (green-100)`rgb(22, 163, 74)` (green-600)`redeemed``rgb(229, 231, 235)` (gray-200)`rgb(107, 114, 128)` (gray-500)`expired``rgb(254, 226, 226)` (red-100)`rgb(220, 38, 38)` (red-600)`pending``rgb(254, 243, 199)` (yellow-100)`rgb(202, 138, 4)` (yellow-600)Unknown statuses fall back to neutral gray.

### Customization Rules

[](#customization-rules)

1. **Keep 1200×630**: Social platforms expect this aspect ratio. Deviating causes cropping.
2. **Delete cached PNGs** after template changes — images are cached on disk.
3. **Fonts**: Change the `@import` URL in `` for different Google Fonts.
4. **Test locally**: Generate via `curl -o test.png http://app.test/og/{key}/{id}` and view the PNG.

OgMetaData DTO
--------------

[](#ogmetadata-dto)

`LBHurtado\OgMeta\Data\OgMetaData` — all fields that resolvers populate:

FieldTypeUsed For`title``string``og:title` meta tag`description``string``og:description` meta tag`status``string`Badge color, background color, cache filename`headline``string`Large text on card`subtitle``?string`Secondary text on card`tagline``?string`Bottom text on card`url``?string``og:url` meta tag`imageUrl``?string``og:image` — auto-set by `OgMetaService` if null`cacheKey``?string`Image cache filename segment (e.g. voucher code)`httpMaxAge``?int``Cache-Control` max-age in seconds (null = infinite)`message``?string`Text below the status badge (GD mode)`overlayImage``?string`Base64-encoded image for GD mode (right side)`splashHtml``?string`Raw HTML for screenshot mode (reserved for future use)`typeBadge``?string`Secondary badge label (e.g. "redeemable", "payable")`payeeBadge``?string`**Renderer-specific fields**:

- `overlayImage` is only used in GD mode — the renderer composites it onto the canvas
- `typeBadge` renders as a gray pill badge in screenshot mode
- `payeeBadge` renders as a dark pill badge next to the type badge in screenshot mode
- A resolver can populate fields for both rendering modes

Creating a Resolver
-------------------

[](#creating-a-resolver)

### 1. Create the class

[](#1-create-the-class)

Extend `ModelOgResolver` for model-backed resolvers:

```
