@ogify/core 0.1.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 RevoLabs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,350 @@
1
+ # OGify - Beautiful Dynamic OG Images in Seconds
2
+
3
+ [![npm version](https://badge.fury.io/js/%40ogify%2Fcore.svg)](https://badge.fury.io/js/%40ogify%2Fcore)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![TypeScript](https://img.shields.io/badge/TypeScript-007ACC?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
6
+
7
+ Generate stunning Open Graph images in seconds, not hours. OGify eliminates the complexity of OG image generation with zero-config font loading, automatic caching, and production-ready templates.
8
+
9
+ ## ⚡ Why OGify?
10
+
11
+ - 🔌 **Zero-config**: Works out of the box with Next.js, Remix, Astro, etc.
12
+ - 🎨 **No font management**: Just specify a Google Font name - no downloads, no font files, no hassle.
13
+ - 📦 **No asset pipeline**: Emojis load dynamically from CDNs.
14
+ - 🖼️ **Rich templates**: OGify provides a set of production-ready templates with zero configuration.
15
+ - ⚡ **Smart caching**: OGify automatically caches fonts, emojis, and generated images - no configuration required.
16
+ - 🛡️ **Type-safe**: Full TypeScript support catches errors before runtime.
17
+
18
+ ## 📦 Installation
19
+
20
+ ```bash
21
+ pnpm add @ogify/core
22
+ ```
23
+
24
+ ## 🚀 Quick Start
25
+
26
+ ### 1. Define a Template
27
+
28
+ Create a template using `defineTemplate` with an HTML renderer function:
29
+
30
+ ```typescript
31
+ import { defineTemplate, OgTemplateOptions } from '@ogify/core';
32
+
33
+ const blogTemplate = defineTemplate({
34
+ id: 'blog-post',
35
+ name: 'Blog Post',
36
+ description: 'Template for blog post OG images',
37
+ fonts: [
38
+ { name: 'Inter', weight: 700 },
39
+ { name: 'Inter', weight: 400 }
40
+ ],
41
+ renderer: ({ params }: OgTemplateOptions) => {
42
+ return `
43
+ <div style="display: flex; flex-direction: column; width: 100%; height: 100%; background: white; padding: 40px;">
44
+ <h1 style="font-size: 60px; font-weight: 700; color: #000;">
45
+ ${params.title}
46
+ </h1>
47
+ <p style="font-size: 30px; color: #666;">
48
+ ${params.description}
49
+ </p>
50
+ </div>
51
+ `;
52
+ },
53
+ });
54
+ ```
55
+
56
+ ### 2. Create a Renderer
57
+
58
+ Create a renderer instance and register your templates:
59
+
60
+ ```typescript
61
+ import { createTemplateRenderer } from '@ogify/core';
62
+
63
+ const renderer = createTemplateRenderer({
64
+ templates: [blogTemplate],
65
+ defaultParams: {
66
+ brand: 'My Company'
67
+ }
68
+ });
69
+ ```
70
+
71
+ ### 3. Generate an Image
72
+
73
+ Render a template to a PNG buffer:
74
+
75
+ ```typescript
76
+ // Basic usage (1200x630)
77
+ const imageBuffer = await renderer.renderToImage('blog-post', {
78
+ title: 'Hello World',
79
+ description: 'My first OG image'
80
+ });
81
+
82
+ // Custom dimensions for Twitter (1200x675)
83
+ const twitterImage = await renderer.renderToImage('blog-post', {
84
+ title: 'Hello World'
85
+ }, {
86
+ width: 1200,
87
+ height: 675
88
+ });
89
+ ```
90
+
91
+ **That's it!** You're ready for production. No font files to download, no build configuration, no asset pipeline.
92
+
93
+ ## 🚀 Time-Saving Features
94
+
95
+ ### **Zero-Config Google Fonts**
96
+
97
+ Traditional approach (manual setup):
98
+
99
+ ```typescript
100
+ // ❌ Manual: Download fonts, manage files, configure paths
101
+ import fs from 'fs';
102
+ const fontData = fs.readFileSync('./fonts/Inter-Bold.ttf');
103
+ const font2Data = fs.readFileSync('./fonts/Inter-Regular.ttf');
104
+
105
+ const fonts = [
106
+ { name: 'Inter', data: fontData, weight: 700 },
107
+ { name: 'Inter', data: font2Data, weight: 400 }
108
+ ];
109
+ ```
110
+
111
+ OGify approach (zero config):
112
+
113
+ ```typescript
114
+ // ✅ OGify: Just specify the font name - we handle the rest
115
+ const template = defineTemplate({
116
+ fonts: [
117
+ { name: 'Inter', weight: 700 }, // Automatically loaded from Google Fonts
118
+ { name: 'Inter', weight: 400 }
119
+ ],
120
+ // ...
121
+ });
122
+ ```
123
+
124
+ **Time saved**: ~15 minutes per font family
125
+
126
+ ### **Automatic Caching**
127
+
128
+ ```typescript
129
+ // First render: Downloads fonts from Google (~500ms)
130
+ await renderer.renderToImage('blog-post', { title: 'Post 1' });
131
+
132
+ // Second render: Uses cached fonts (~50ms) - 10x faster! ⚡
133
+ await renderer.renderToImage('blog-post', { title: 'Post 2' });
134
+
135
+ // All subsequent renders: Lightning fast
136
+ await renderer.renderToImage('blog-post', { title: 'Post 3' });
137
+ ```
138
+
139
+ **Performance**: 10x faster after first render, no configuration needed
140
+
141
+ ### **Dynamic Emoji Loading**
142
+
143
+ ```typescript
144
+ // ✅ Emojis just work - loaded dynamically from CDN
145
+ renderer: ({ params }) => `
146
+ <div>
147
+ <h1>${params.title}</h1>
148
+ <div>👋 😄 🎉 🚀</div> <!-- Automatically rendered -->
149
+ </div>
150
+ `
151
+ ```
152
+
153
+ **Time saved**: No emoji sprite sheets, no asset management, no build step
154
+
155
+ ## 📚 Advanced Usage
156
+
157
+ ### Custom Fonts
158
+
159
+ Load fonts from Google Fonts, custom URLs, or embedded data:
160
+
161
+ ```typescript
162
+ const template = defineTemplate({
163
+ id: 'custom-fonts',
164
+ name: 'Custom Fonts Template',
165
+ description: 'Template with custom fonts',
166
+ fonts: [
167
+ // Google Fonts (automatic)
168
+ { name: 'Roboto', weight: 400 },
169
+
170
+ // Custom URL
171
+ { name: 'MyFont', url: 'https://example.com/font.woff2', weight: 700 },
172
+
173
+ // Embedded data
174
+ { name: 'EmbeddedFont', data: fontBuffer, weight: 400 }
175
+ ],
176
+ renderer: ({ params }) => `<div>${params.title}</div>`
177
+ });
178
+ ```
179
+
180
+ ### Emoji Support
181
+
182
+ Choose from multiple emoji providers:
183
+
184
+ ```typescript
185
+ const template = defineTemplate({
186
+ id: 'emoji-template',
187
+ name: 'Emoji Template',
188
+ description: 'Template with emoji support',
189
+ fonts: [{ name: 'Inter', weight: 400 }],
190
+ emojiProvider: 'twemoji', // or 'fluent', 'noto', 'openmoji', etc.
191
+ renderer: ({ params }) => `
192
+ <div>
193
+ <h1>${params.title}</h1>
194
+ <div>👋 😄 🎉</div>
195
+ </div>
196
+ `
197
+ });
198
+ ```
199
+
200
+ ### Lifecycle Hooks
201
+
202
+ Add custom logic before and after rendering:
203
+
204
+ ```typescript
205
+ const renderer = createTemplateRenderer({
206
+ templates: [blogTemplate],
207
+ beforeRender: async (templateId, params) => {
208
+ console.log(`Rendering ${templateId}`, params);
209
+ // Log analytics, validate params, etc.
210
+ },
211
+ afterRender: async (templateId, params, imageBuffer) => {
212
+ console.log(`Rendered ${templateId} successfully`);
213
+ // Cache image, send notifications, etc.
214
+ }
215
+ });
216
+ ```
217
+
218
+ ### Platform-Specific Dimensions
219
+
220
+ Generate images for different platforms:
221
+
222
+ ```typescript
223
+ // Facebook/LinkedIn (1200x630)
224
+ const facebookImage = await renderer.renderToImage('blog-post', params);
225
+
226
+ // Twitter (1200x675)
227
+ const twitterImage = await renderer.renderToImage('blog-post', params, {
228
+ width: 1200,
229
+ height: 675
230
+ });
231
+ ```
232
+
233
+ ## 🎨 Template Features
234
+
235
+ ### Supported CSS Properties
236
+
237
+ Templates support a subset of CSS properties via Satori:
238
+
239
+ - **Layout**: `display: flex`, `flexDirection`, `alignItems`, `justifyContent`
240
+ - **Spacing**: `padding`, `margin`, `gap`
241
+ - **Typography**: `fontSize`, `fontWeight`, `color`, `lineHeight`, `textAlign`
242
+ - **Background**: `backgroundColor`, `backgroundImage`
243
+ - **Border**: `border`, `borderRadius`
244
+ - **Size**: `width`, `height`, `maxWidth`, `maxHeight`
245
+
246
+ ### Tailwind-like Utilities
247
+
248
+ You can use Tailwind-like class names:
249
+
250
+ ```typescript
251
+ renderer: ({ params }) => `
252
+ <div class="flex flex-col items-center justify-center w-full h-full bg-white p-4">
253
+ <h1 class="text-[60px] font-bold text-black">${params.title}</h1>
254
+ <p class="text-[30px] text-gray-600">${params.description}</p>
255
+ </div>
256
+ `
257
+ ```
258
+
259
+ ## 📖 API Reference
260
+
261
+ ### `defineTemplate(config)`
262
+
263
+ Defines a new OG template.
264
+
265
+ **Parameters:**
266
+
267
+ - `id` (string): Unique identifier
268
+ - `name` (string): Human-readable name
269
+ - `description` (string): Template description
270
+ - `renderer` (function): Function that returns HTML string
271
+ - `fonts` (array): Array of font configurations
272
+ - `emojiProvider` (optional): Emoji provider to use
273
+
274
+ **Returns:** `OgTemplate`
275
+
276
+ ### `createTemplateRenderer(config)`
277
+
278
+ Creates a new template renderer instance.
279
+
280
+ **Parameters:**
281
+
282
+ - `templates` (array): Array of template definitions
283
+ - `defaultParams` (optional): Default parameters for all templates
284
+ - `beforeRender` (optional): Hook called before rendering
285
+ - `afterRender` (optional): Hook called after rendering
286
+
287
+ **Returns:** `TemplateRenderer`
288
+
289
+ ### `renderer.renderToImage(templateId, params, options?)`
290
+
291
+ Renders a template to a PNG buffer.
292
+
293
+ **Parameters:**
294
+
295
+ - `templateId` (string): ID of the template to render
296
+ - `params` (object): Parameters to pass to the template
297
+ - `options` (optional): Rendering options
298
+ - `width` (number): Image width (default: 1200)
299
+ - `height` (number): Image height (default: 630)
300
+
301
+ **Returns:** `Promise<Buffer>`
302
+
303
+ ### `renderer.getTemplate(id)`
304
+
305
+ Retrieves a template by ID.
306
+
307
+ **Returns:** `OgTemplate | undefined`
308
+
309
+ ### `renderer.getTemplateIds()`
310
+
311
+ Gets all registered template IDs.
312
+
313
+ **Returns:** `string[]`
314
+
315
+ ## ⚡ Performance & Production
316
+
317
+ ### **Automatic Caching (Zero Config)**
318
+
319
+ OGify automatically caches fonts and emojis in memory - no configuration required:
320
+
321
+ ```typescript
322
+ // First render: Downloads fonts from Google Fonts (~500ms)
323
+ await renderer.renderToImage('blog-post', { title: 'Post 1' });
324
+
325
+ // Second render: Uses cached fonts (~50ms) - 10x faster! ⚡
326
+ await renderer.renderToImage('blog-post', { title: 'Post 2' });
327
+
328
+ // Third+ renders: Lightning fast from cache
329
+ await renderer.renderToImage('blog-post', { title: 'Post 3' });
330
+ ```
331
+
332
+ ## 📋 Changelog
333
+
334
+ See [CHANGELOG.md](CHANGELOG.md) for a complete history of changes and releases.
335
+
336
+ ## 🤝 Contributing
337
+
338
+ We welcome contributions! Please see our contributing guidelines.
339
+
340
+ ## 📄 License
341
+
342
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
343
+
344
+ ## 🙏 Credits
345
+
346
+ Built on top of:
347
+
348
+ - [satori](https://github.com/vercel/satori) - SVG generation
349
+ - [satori-html](https://github.com/vercel/satori-html) - HTML to VDOM conversion
350
+ - [resvg-js](https://github.com/thx/resvg-js) - PNG conversion