@ogify/core 0.5.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  Zero-config dynamic Open Graph images for Next.js, Nuxt, Remix, and more. Just copy & paste the production-ready templates.
8
8
 
9
- ![OGify](../../apps/examples/outputs/aligned-aligned-ltr.png)
9
+ ![OGify](/docs/assets/preview.png)
10
10
 
11
11
  ## ⚡ Why OGify?
12
12
 
@@ -17,399 +17,11 @@ Zero-config dynamic Open Graph images for Next.js, Nuxt, Remix, and more. Just c
17
17
  - ⚡ **Smart caching**: Automatically caches fonts, emojis, and generated images - no configuration required.
18
18
  - 🌍 **RTL Support**: Built-in support for Right-to-Left languages like Arabic, Hebrew, and Persian.
19
19
 
20
- ## 📦 Installation
20
+ ## 📚 Documentation
21
21
 
22
- ```bash
23
- pnpm add @ogify/core @ogify/templates
24
- ```
25
-
26
- or
27
-
28
- ```bash
29
- npm install @ogify/core @ogify/templates
30
- ```
31
-
32
- or
33
-
34
- ```bash
35
- yarn add @ogify/core @ogify/templates
36
- ```
37
-
38
- ## 🚀 Quick Start
39
-
40
- ### 1. Choose a Template
41
-
42
- OGify comes with a collection of beautiful, production-ready templates. Check out [our gallery](https://ogify.dev/templates) for more.
43
-
44
- ```typescript
45
- import template from '@ogify/templates/basic';
46
- import type { TemplateParams } from '@ogify/templates/basic';
47
- ```
48
-
49
- ### 2. Create a Renderer
50
-
51
- Create a renderer instance and register your template:
52
-
53
- ```typescript
54
- import { createRenderer } from '@ogify/core';
55
- import template from '@ogify/templates/basic';
56
- import type { TemplateParams } from '@ogify/templates/basic';
57
-
58
- const renderer = createRenderer<{ basic: TemplateParams }>({
59
- templates: { basic: template },
60
- sharedParams: {
61
- brandLogo: 'https://ogify.dev/logo.svg',
62
- brandName: 'OGify',
63
- }
64
- });
65
- ```
66
-
67
- ### 3. Generate an Image
68
-
69
- Render the template to a PNG buffer:
70
-
71
- ```typescript
72
- // Basic usage (1200x630)
73
- const imageBuffer = await renderer.renderToImage('basic', {
74
- title: 'Hello World',
75
- subtitle: 'My first OG image',
76
- layout: 'centered', // aligned | centered | split
77
- cta: 'Read More',
78
- primaryColor: '#000000',
79
- });
80
-
81
- // Custom dimensions for Twitter (1200x675)
82
- const twitterImage = await renderer.renderToImage('basic', {
83
- title: 'Hello World',
84
- subtitle: 'My first OG image',
85
- layout: 'split',
86
- }, {
87
- width: 1200,
88
- height: 675
89
- });
90
-
91
- // RTL Support (Arabic/Hebrew/Persian)
92
- const rtlImage = await renderer.renderToImage('basic', {
93
- title: 'مرحبا بالعالم',
94
- subtitle: 'هذه أول صورة OG لي',
95
- layout: 'aligned',
96
- }, {
97
- isRTL: true
98
- });
99
- ```
100
-
101
- **That's it!** You're ready for production. No font files to download, no build configuration, no asset pipeline.
102
-
103
- ## 🚀 Time-Saving Features
104
-
105
- ### **Rich Templates**
106
-
107
- Access a growing library of beautiful, production-ready templates. [Browse Templates](https://ogify.dev/templates)
108
-
109
- **Time saved**: Hours of design and implementation time
110
-
111
- ### **Zero-Config Google Fonts**
112
-
113
- Traditional approach (manual setup):
114
-
115
- ```typescript
116
- // ❌ Manual: Download fonts, manage files, configure paths
117
- import fs from 'fs';
118
-
119
- const fontData = fs.readFileSync('./fonts/Inter-Regular.ttf');
120
- const font2Data = fs.readFileSync('./fonts/Inter-Bold.ttf');
121
-
122
- const fonts = [
123
- { name: 'Inter', data: fontData, weight: 400 },
124
- { name: 'Inter', data: font2Data, weight: 700 }
125
- ];
126
- ```
127
-
128
- OGify approach (zero-config):
129
-
130
- ```typescript
131
- // ✅ OGify: Just specify the font name - we handle the rest
132
- const template = defineTemplate({
133
- fonts: [
134
- { name: 'Inter', weight: 400 }, // Automatically loaded from Google Fonts
135
- { name: 'Inter', weight: 700 }
136
- ],
137
- // ...
138
- });
139
- ```
140
-
141
- **Time saved**: ~15 minutes per font family
142
-
143
- ### **Automatic Caching**
144
-
145
- ```typescript
146
- // First render: Downloads fonts from Google (~500ms)
147
- await renderer.renderToImage('basic', { title: 'Post 1', subtitle: '...' });
148
-
149
- // Second render: Uses cached fonts (~50ms) - 10x faster! ⚡
150
- await renderer.renderToImage('basic', { title: 'Post 2', subtitle: '...' });
151
-
152
- // All subsequent renders: Lightning fast
153
- await renderer.renderToImage('basic', { title: 'Post 3', subtitle: '...' });
154
- ```
155
-
156
- **Performance**: 10x faster after first render, no configuration needed
157
-
158
- ### **Dynamic Emoji Loading**
159
-
160
- ```typescript
161
- // ✅ Emojis just work - loaded dynamically from CDN
162
- renderer: ({ params }) => `
163
- <div>
164
- <h1>${params.title}</h1>
165
- <div>👋 😄 🎉 🚀</div> <!-- Automatically rendered -->
166
- </div>
167
- `
168
- ```
169
-
170
- **Time saved**: No emoji sprite sheets, no asset management, no build step
171
-
172
- ## 🛠️ Creating Custom Templates
173
-
174
- If you want to build your own templates from scratch, you can use `defineTemplate`.
175
-
176
- ```typescript
177
- import { defineTemplate, OgTemplateOptions } from '@ogify/core';
178
-
179
- const blogTemplate = defineTemplate({
180
- fonts: [
181
- { name: 'Inter', weight: 400 },
182
- { name: 'Inter', weight: 700 }
183
- ],
184
- renderer: ({ params }: OgTemplateOptions) => {
185
- return `
186
- <div style="display: flex; flex-direction: column; width: 100%; height: 100%; background: white; padding: 40px;">
187
- <h1 style="font-size: 60px; font-weight: 700; color: #000;">
188
- ${params.title}
189
- </h1>
190
- <p style="font-size: 30px; color: #666;">
191
- ${params.description}
192
- </p>
193
- </div>
194
- `;
195
- },
196
- });
197
- ```
198
-
199
- ## 📚 Advanced Usage
200
-
201
- ### Custom Fonts
202
-
203
- Load fonts from Google Fonts, custom URLs, or embedded data:
204
-
205
- ```typescript
206
- const template = defineTemplate({
207
- fonts: [
208
- // Google Fonts (automatic)
209
- { name: 'Roboto', weight: 400 },
210
-
211
- // Custom URL
212
- { name: 'MyFont', url: 'https://example.com/font.woff2', weight: 700 },
213
-
214
- // Embedded data
215
- { name: 'EmbeddedFont', data: fontBuffer, weight: 400 }
216
- ],
217
- renderer: ({ params }) => `<div>${params.title}</div>`
218
- });
219
- ```
220
-
221
- ### Emoji Support
222
-
223
- Choose from multiple emoji providers:
224
-
225
- ```typescript
226
- const template = defineTemplate({
227
- fonts: [{ name: 'Inter', weight: 400 }],
228
- emojiProvider: 'twemoji', // 'fluent' | 'fluentFlat' | 'noto' | 'blobmoji' | 'openmoji'
229
- renderer: ({ params }) => `
230
- <div>
231
- <h1>${params.title}</h1>
232
- <div>👋 😄 🎉</div>
233
- </div>
234
- `
235
- });
236
- ```
237
-
238
- ### Lifecycle Hooks
239
-
240
- Add custom logic before and after rendering:
241
-
242
- ```typescript
243
- const renderer = createRenderer({
244
- templates: { 'blog-post': blogTemplate },
245
- beforeRender: async (templateId, params) => {
246
- console.log(`Rendering ${templateId}`, params);
247
- // Log analytics, validate params, etc.
248
- },
249
- afterRender: async (templateId, params, imageBuffer) => {
250
- console.log(`Rendered ${templateId} successfully`);
251
- // Cache image, send notifications, etc.
252
- }
253
- });
254
- ```
255
-
256
- ### Caching Configuration
257
-
258
- Configure caching strategy for fonts and emojis/icons:
259
-
260
- ```typescript
261
- // Memory Cache (default)
262
- const memoryRenderer = createRenderer({
263
- templates: { 'blog-post': blogTemplate },
264
- cache: {
265
- type: 'memory',
266
- ttl: 3600000, // 1 hour
267
- max: 100 // max items
268
- }
269
- });
270
-
271
- // Filesystem Cache
272
- const fsRenderer = createRenderer({
273
- templates: { 'blog-post': blogTemplate },
274
- cache: {
275
- type: 'filesystem',
276
- dir: './.ogify-cache', // cache directory
277
- ttl: 3600000, // 1 hour
278
- max: 100 // max items
279
- }
280
- });
281
- ```
282
-
283
- ### Platform-Specific Dimensions
284
-
285
- Generate images for different platforms:
286
-
287
- ```typescript
288
- // Facebook/LinkedIn (1200x630)
289
- const facebookImage = await renderer.renderToImage('basic', {
290
- title: 'Hello World',
291
- subtitle: 'My first OG image',
292
- });
293
-
294
- // Twitter (1200x675)
295
- const twitterImage = await renderer.renderToImage('basic', {
296
- title: 'Hello World',
297
- subtitle: 'My first OG image',
298
- }, {
299
- width: 1200,
300
- height: 675
301
- });
302
- ```
303
-
304
- ## 🎨 Template Features
305
-
306
- ### Supported CSS Properties
307
-
308
- Templates support a subset of CSS properties via Satori. See [Satori CSS](https://github.com/vercel/satori?tab=readme-ov-file#css) for more details.
309
-
310
- - **Layout**: `display: flex`, `flexDirection`, `alignItems`, `justifyContent`
311
- - **Spacing**: `padding`, `margin`, `gap`
312
- - **Typography**: `fontSize`, `fontWeight`, `color`, `lineHeight`, `textAlign`
313
- - **Background**: `backgroundColor`, `backgroundImage`
314
- - **Border**: `border`, `borderRadius`
315
- - **Size**: `width`, `height`, `maxWidth`, `maxHeight`
316
- - ...
317
-
318
- ### Tailwind-like Utilities
319
-
320
- You can use Tailwind-like class names:
321
-
322
- ```typescript
323
- renderer: ({ params }) => `
324
- <div class="flex flex-col items-center justify-center w-full h-full bg-white p-4">
325
- <h1 class="text-[60px] font-bold text-black">${params.title}</h1>
326
- <p class="text-[30px] text-gray-600">${params.description}</p>
327
- </div>
328
- `
329
- ```
330
-
331
- ## 📖 API Reference
332
-
333
- ### `defineTemplate(config)`
334
-
335
- Defines a new OG template.
336
-
337
- **Parameters:**
338
-
339
- - `renderer` (function): Function that returns HTML string
340
- - `fonts` (array): Array of font configurations
341
- - `emojiProvider` (optional): Emoji provider to use
342
-
343
- **Returns:** `OgTemplate`
344
-
345
- ### `createRenderer(config)`
346
-
347
- Creates a new template renderer instance.
348
-
349
- **Parameters:**
350
-
351
- - `templates` (object): Map of template definitions keyed by ID
352
- - `sharedParams` (optional): Default parameters for all templates
353
- - `cache` (optional): Cache configuration object
354
- - `beforeRender` (optional): Hook called before rendering
355
- - `afterRender` (optional): Hook called after rendering
356
-
357
- **Returns:** `TemplateRenderer`
358
-
359
- ### `renderer.renderToImage(templateId, params, options?)`
360
-
361
- Renders a template to a PNG buffer.
362
-
363
- **Parameters:**
364
-
365
- - `templateId` (string): ID of the template to render
366
- - `params` (object | function): Parameters (or function returning params) to pass to the template
367
- - `options` (optional): Rendering options
368
- - `width` (number): Image width (default: 1200)
369
- - `height` (number): Image height (default: 630)
370
- - `isRTL` (boolean): Enable Right-to-Left text direction (default: false)
371
-
372
- **Returns:** `Promise<Buffer>`
373
-
374
- ### RTL Support
375
-
376
- OGify supports Right-to-Left (RTL) languages via the `isRTL` option.
377
-
378
- ```typescript
379
- const image = await renderer.renderToImage('basic', {
380
- title: 'مرحبا بالعالم', // Arabic: Hello World
381
- subtitle: 'هذه أول صورة OG لي',
382
- }, {
383
- isRTL: true
384
- });
385
- ```
386
-
387
- ### `renderer.getTemplate(id)`
388
-
389
- Retrieves a template by ID.
390
-
391
- **Returns:** `OgTemplate | undefined`
392
-
393
- ## ⚡ Performance & Production
394
-
395
- ### **Automatic Caching (Zero Config)**
396
-
397
- OGify automatically caches fonts, emojis, and generated images in memory - no configuration required
398
-
399
- ```typescript
400
- // First render: Downloads fonts from Google Fonts (~500ms)
401
- await renderer.renderToImage('basic', { title: 'Post 1', subtitle: '...' });
402
-
403
- // Second render: Uses cached fonts (~50ms) - 10x faster! ⚡
404
- await renderer.renderToImage('basic', { title: 'Post 2', subtitle: '...' });
405
-
406
- // Third+ renders: Lightning fast from cache
407
- await renderer.renderToImage('basic', { title: 'Post 3', subtitle: '...' });
408
- ```
409
-
410
- ## 📋 Changelog
411
-
412
- See [CHANGELOG.md](CHANGELOG.md) for a complete history of changes and releases.
22
+ - 🌐 **[Website](https://ogify.dev)** - Official website
23
+ - 🎨 **[Template Gallery](https://ogify.dev/templates)** - Browse all available templates
24
+ - 📖 **[Documentation](/docs/README.md)** - Complete guides and API reference
413
25
 
414
26
  ## 🤝 Contributing
415
27
 
package/dist/index.js CHANGED
@@ -595,7 +595,7 @@ async function renderTemplate(template, params, options) {
595
595
  value: width
596
596
  }
597
597
  });
598
- return Buffer.from(pngData.asPng());
598
+ return pngData.asPng();
599
599
  }
600
600
 
601
601
  // src/renderer.ts
package/dist/index.mjs CHANGED
@@ -567,7 +567,7 @@ async function renderTemplate(template, params, options) {
567
567
  value: width
568
568
  }
569
569
  });
570
- return Buffer.from(pngData.asPng());
570
+ return pngData.asPng();
571
571
  }
572
572
 
573
573
  // src/renderer.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ogify/core",
3
- "version": "0.5.0",
3
+ "version": "1.0.0",
4
4
  "description": "Core types and utilities for OGify Open Graph image generator",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",