{"_id":"@bearstudio/astro-assets-generation","_rev":"5-8afabd641ef3d9ae40fcc7a98feb4828","name":"@bearstudio/astro-assets-generation","dist-tags":{"latest":"0.2.1"},"versions":{"0.1.0":{"name":"@bearstudio/astro-assets-generation","version":"0.1.0","_id":"@bearstudio/astro-assets-generation@0.1.0","maintainers":[{"name":"ntorion","email":"nicolas.torion@bearstudio.fr"},{"name":"ivandalmet","email":"ivan@dalmet.fr"},{"name":"yoannfleurydev","email":"yoann.fleury@yahoo.com"},{"name":"stylishedcoyote","email":"renan.decamps@icloud.com"}],"dist":{"shasum":"a2d03ae4a0e4fba8d0988670535ae216102b2161","tarball":"https://registry.npmjs.org/@bearstudio/astro-assets-generation/-/astro-assets-generation-0.1.0.tgz","fileCount":10,"integrity":"sha512-ryTwizwrVDMz+5zBqgRQdonWyzoSSKryBbzFOWLT6TYoy6MOxObK5xuc12CSRfsH+Dd0+bfi6tOe5WmcM9fzAQ==","signatures":[{"sig":"MEUCIQC5nVQYGDlWe0bt+JlZxN/XTWQev2S53o9m9SozGTP1NgIgIAcRnRK4pKU8+ZkeQMntPb08cxOfmRQLSLzjF+qNTLg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":23681679},"type":"module","_from":"file:bearstudio-astro-assets-generation-0.1.0.tgz","exports":{".":{"types":"./src/index.ts","import":"./dist/index.js"}},"scripts":{"dev":"tsup src/index.ts --format esm --dts --watch","test":"echo \"Error: no test specified\" && exit 1","build":"tsup src/index.ts --format esm --dts --minify","prebuild":"tsx src/scripts/bundle-emojis.ts","npm:publish":"pnpm publish --access public","verdaccio:publish":"pnpm publish --registry http://localhost:4873 --no-git-checks","verdaccio:unpublish":"npm unpublish @bearstudio/astro-assets-generation@$(node -p \"require('./package.json').version\") --registry http://localhost:4873 --force"},"_npmUser":{"name":"yoannfleurydev","email":"yoann.fleury@yahoo.com"},"_resolved":"/private/var/folders/fp/y3c7_l6953dcxh6hfhcyp4qr0000gn/T/f019bb3def684356c99e90c2c4781098/bearstudio-astro-assets-generation-0.1.0.tgz","_integrity":"sha512-ryTwizwrVDMz+5zBqgRQdonWyzoSSKryBbzFOWLT6TYoy6MOxObK5xuc12CSRfsH+Dd0+bfi6tOe5WmcM9fzAQ==","_npmVersion":"11.12.1","description":"Astro integration to generate assets with Takumi","directories":{},"_nodeVersion":"24.15.0","dependencies":{"ts-pattern":"5.9.0","@twemoji/svg":"15.0.0","@takumi-rs/image-response":"0.65.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"4.21.0","tsup":"8.5.1","react":"19.2.3","react-dom":"19.2.3","typescript":"latest","@types/node":"20.0.0","@types/react":"19.2.8","@types/react-dom":"19.2.3","@repo/typescript-config":"0.0.0"},"peerDependencies":{"astro":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/astro-assets-generation_0.1.0_1777305855429_0.509118185823187","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"@bearstudio/astro-assets-generation","version":"0.1.2","_id":"@bearstudio/astro-assets-generation@0.1.2","maintainers":[{"name":"ntorion","email":"nicolas.torion@bearstudio.fr"},{"name":"ivandalmet","email":"ivan@dalmet.fr"},{"name":"yoannfleurydev","email":"yoann.fleury@yahoo.com"},{"name":"stylishedcoyote","email":"renan.decamps@icloud.com"}],"dist":{"shasum":"1f87ca06b47fb8cc31d91ed3ba1c912241ec0212","tarball":"https://registry.npmjs.org/@bearstudio/astro-assets-generation/-/astro-assets-generation-0.1.2.tgz","fileCount":7,"integrity":"sha512-pEnguCggrGteoa75aHyl0WhG4WRuPKmtd/E0QeCz958MBweJpjjrGVwX5qoqPhmZlu9XNxm3UzU/EkxNdcuX+w==","signatures":[{"sig":"MEUCIQD8ISNamakCvdZz9NbyH4XUTFNuHKrs4mlI4n/oUaK8/wIgJIrFlHzP95cp7JdusVpGkT1IYZVeN7jIsx/hnEM+Ym0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":27793},"type":"module","_from":"file:bearstudio-astro-assets-generation-0.1.2.tgz","exports":{".":{"types":"./src/index.ts","import":"./dist/index.js"},"./disk-loader":{"types":"./src/disk-loader.ts","import":"./dist/disk-loader.js"}},"scripts":{"dev":"tsup --watch","test":"echo \"Error: no test specified\" && exit 1","build":"tsup","npm:publish":"pnpm publish --access public","verdaccio:publish":"pnpm publish --registry http://localhost:4873 --no-git-checks","verdaccio:unpublish":"npm unpublish @bearstudio/astro-assets-generation@$(node -p \"require('./package.json').version\") --registry http://localhost:4873 --force"},"_npmUser":{"name":"yoannfleurydev","email":"yoann.fleury@yahoo.com"},"_resolved":"/private/var/folders/fp/y3c7_l6953dcxh6hfhcyp4qr0000gn/T/0ae296d8d4c9cb452ce187bcade3dc9f/bearstudio-astro-assets-generation-0.1.2.tgz","_integrity":"sha512-pEnguCggrGteoa75aHyl0WhG4WRuPKmtd/E0QeCz958MBweJpjjrGVwX5qoqPhmZlu9XNxm3UzU/EkxNdcuX+w==","_npmVersion":"11.12.1","description":"Astro integration to generate assets with Takumi","directories":{},"_nodeVersion":"24.15.0","dependencies":{"ts-pattern":"5.9.0","@takumi-rs/image-response":"1.1.2"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"8.5.1","react":"19.2.3","react-dom":"19.2.3","typescript":"latest","@types/node":"20.0.0","@types/react":"19.2.8","@types/react-dom":"19.2.3","@repo/typescript-config":"0.0.0"},"peerDependencies":{"astro":"^5.0.0"},"optionalDependencies":{"@takumi-rs/core-linux-x64-gnu":"1.1.2"},"_npmOperationalInternal":{"tmp":"tmp/astro-assets-generation_0.1.2_1778675559786_0.11017989031216224","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@bearstudio/astro-assets-generation","version":"0.2.0","_id":"@bearstudio/astro-assets-generation@0.2.0","maintainers":[{"name":"ntorion","email":"nicolas.torion@bearstudio.fr"},{"name":"ivandalmet","email":"ivan@dalmet.fr"},{"name":"yoannfleurydev","email":"yoann.fleury@yahoo.com"},{"name":"stylishedcoyote","email":"renan.decamps@icloud.com"}],"dist":{"shasum":"e1e0c4b88d6c55b68abf86058e0a335e3a906c07","tarball":"https://registry.npmjs.org/@bearstudio/astro-assets-generation/-/astro-assets-generation-0.2.0.tgz","fileCount":7,"integrity":"sha512-EQ5OJ4qefWKAFcTJbhDkWa3pgS7qf1f8WJNTGk/OUgqSZ33ChMW77T1EYzy6MHyzNrPcFzPn2UmWI1TIjOzn7A==","signatures":[{"sig":"MEUCIQDsQUPqWCia7CXQ8zpFz1h+lyGk0f5QLifWKgLQozzrkAIgbfXp6cf62aSlNJgWTtmIdVL+dDdML6Y8CWWihSxd2wE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":30512},"type":"module","_from":"file:bearstudio-astro-assets-generation-0.2.0.tgz","exports":{".":{"types":"./src/index.ts","import":"./dist/index.js"},"./disk-loader":{"types":"./src/disk-loader.ts","import":"./dist/disk-loader.js"}},"scripts":{"dev":"tsup --watch","test":"echo \"Error: no test specified\" && exit 1","build":"tsup","check-types":"tsc --noEmit","npm:publish":"pnpm publish --access public","verdaccio:publish":"pnpm publish --registry http://localhost:4873 --no-git-checks","verdaccio:unpublish":"npm unpublish @bearstudio/astro-assets-generation@$(node -p \"require('./package.json').version\") --registry http://localhost:4873 --force"},"_npmUser":{"name":"yoannfleurydev","email":"yoann.fleury@yahoo.com"},"_resolved":"/private/var/folders/fp/y3c7_l6953dcxh6hfhcyp4qr0000gn/T/5713ead1d9712e3678df705c87ddd21a/bearstudio-astro-assets-generation-0.2.0.tgz","_integrity":"sha512-EQ5OJ4qefWKAFcTJbhDkWa3pgS7qf1f8WJNTGk/OUgqSZ33ChMW77T1EYzy6MHyzNrPcFzPn2UmWI1TIjOzn7A==","_npmVersion":"11.17.0","description":"Astro integration to generate assets with Takumi","directories":{},"_nodeVersion":"24.19.0","dependencies":{"takumi-js":"2.9.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"8.5.1","react":"19.2.3","react-dom":"19.2.3","typescript":"latest","@types/node":"20.0.0","@types/react":"19.2.8","@types/react-dom":"19.2.3","@repo/typescript-config":"0.0.0"},"peerDependencies":{"astro":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/astro-assets-generation_0.2.0_1786970417402_0.6300455895396762","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@bearstudio/astro-assets-generation","version":"0.2.1","_id":"@bearstudio/astro-assets-generation@0.2.1","maintainers":[{"name":"ntorion","email":"nicolas.torion@bearstudio.fr"},{"name":"ivandalmet","email":"ivan@dalmet.fr"},{"name":"yoannfleurydev","email":"yoann.fleury@yahoo.com"},{"name":"stylishedcoyote","email":"renan.decamps@icloud.com"}],"dist":{"shasum":"605818ced10f24221375519df70e7308de6c46ce","tarball":"https://registry.npmjs.org/@bearstudio/astro-assets-generation/-/astro-assets-generation-0.2.1.tgz","fileCount":7,"integrity":"sha512-VRPrObBsS5qWBhs/SbSNV1cBNG1lDl2wRS9T3FODeYkHX6axeeOCwVVN7dtCOdN3x39MH9KwXo66eAC1aR4jTA==","signatures":[{"sig":"MEUCIQCNKoMH/c6inKqnSOlo1+suNY9QjKw8CupZEyxFJ9q+hwIgcBkN3Mc6icjy6zvF/wmk1lJMPPRRUDGQ7nDmePPIFTs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":32557},"type":"module","_from":"file:bearstudio-astro-assets-generation-0.2.1.tgz","exports":{".":{"types":"./src/index.ts","import":"./dist/index.js"},"./disk-loader":{"types":"./src/disk-loader.ts","import":"./dist/disk-loader.js"}},"scripts":{"dev":"tsup --watch","test":"echo \"Error: no test specified\" && exit 1","build":"tsup","check-types":"tsc --noEmit","npm:publish":"pnpm publish --access public","verdaccio:publish":"pnpm publish --registry http://localhost:4873 --no-git-checks","verdaccio:unpublish":"npm unpublish @bearstudio/astro-assets-generation@$(node -p \"require('./package.json').version\") --registry http://localhost:4873 --force"},"_npmUser":{"name":"yoannfleurydev","email":"yoann.fleury@yahoo.com"},"_resolved":"/private/var/folders/fp/y3c7_l6953dcxh6hfhcyp4qr0000gn/T/90b123e8f039c301c15e23f86a1b8221/bearstudio-astro-assets-generation-0.2.1.tgz","_integrity":"sha512-VRPrObBsS5qWBhs/SbSNV1cBNG1lDl2wRS9T3FODeYkHX6axeeOCwVVN7dtCOdN3x39MH9KwXo66eAC1aR4jTA==","_npmVersion":"11.17.0","description":"Astro integration to generate assets with Takumi","directories":{},"_nodeVersion":"24.19.0","dependencies":{"takumi-js":"2.9.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"8.5.1","react":"19.2.3","react-dom":"19.2.3","typescript":"latest","@types/node":"20.0.0","@types/react":"19.2.8","@types/react-dom":"19.2.3","@repo/typescript-config":"0.0.0"},"peerDependencies":{"astro":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/astro-assets-generation_0.2.1_1786977999860_0.750984897831716","host":"s3://npm-registry-packages-npm-production"}}},"time":{"created":"2026-04-27T16:04:15.330Z","modified":"2026-08-28T14:13:14.434Z","0.1.0":"2026-04-27T16:04:15.886Z","0.1.2":"2026-05-13T12:32:39.965Z","0.2.0":"2026-08-17T12:40:17.551Z","0.2.1":"2026-08-17T14:46:40.105Z"},"description":"Astro integration to generate assets with Takumi","maintainers":[{"email":"nicolas.torion@bearstudio.fr","name":"ntorion"},{"email":"ivan@dalmet.fr","name":"ivandalmet"},{"email":"yoann.fleury@yahoo.com","name":"yoannfleurydev"},{"email":"renan.decamps@icloud.com","name":"stylishedcoyote"},{"email":"hugo@bearstudio.fr","name":"hugoprd"}],"readme":"# @bearstudio/astro-assets-generation\n\nGenerate dynamic images (OG images, social media cards, etc.) using React components in your Astro projects. Powered by [Takumi](https://github.com/takumi-rs/takumi).\n\n## Features\n\n- Design images with React components and JSX\n- Generate PNG, JPEG, or JPG images\n- Debug mode to preview templates in browser\n- Built-in emoji support with configurable provider (Twemoji by default)\n- Automatic multilingual support (Thai, Japanese, Korean, Arabic)\n- Custom fonts with lazy loading and automatic subsetting\n- Fast Rust-based rendering via takumi-js v2\n\n## Installation\n\n```bash\npnpm add @bearstudio/astro-assets-generation\n```\n\n## Quick Start\n\n### 1. Configure Astro\n\nUpdate your `astro.config.mjs`:\n\n```javascript\nimport { defineConfig } from \"astro/config\";\nimport react from \"@astrojs/react\";\nimport { astroAssetsGeneration } from \"@bearstudio/astro-assets-generation\";\n\nexport default defineConfig({\n  integrations: [react(), astroAssetsGeneration()],\n});\n```\n\nThe integration configures the Takumi Vite/SSR settings for you. On Vercel, it\nalso includes Takumi's native Linux binding in the serverless function output,\nso consumers do not need custom `includeFiles` config.\n\n### 2. Configure the Library\n\nCreate a configuration file (e.g., `src/lib/assets.ts`):\n\n```typescript\nimport { configure } from \"@bearstudio/astro-assets-generation\";\nimport { diskLoader } from \"@bearstudio/astro-assets-generation/disk-loader\";\n\nconfigure({\n  debugBackground: \"#0a0a0a\",\n  siteUrl: import.meta.env.SITE ?? \"http://localhost:4321\",\n  isDev: import.meta.env.DEV,\n  customFonts: [\n    // Optional\n    {\n      name: \"Geist\",\n      url: \"/fonts/Geist.ttf\",\n      weight: 400,\n      style: \"normal\",\n    },\n  ],\n  // emoji: \"twemoji\", // Optional. Default: \"twemoji\"\n  // Required for `output: 'static'` (prerender has no server). Omit for SSR\n  // adapters — the library will fetch from `siteUrl` instead.\n  loadAsset: diskLoader(),\n});\n```\n\n### 3. Create a Template\n\nCreate a React component prefixed with `_`:\n\n```tsx\n// src/pages/blog/[slug]/assets/_og-image.tsx\nimport { FontWrapper } from \"@bearstudio/astro-assets-generation\";\nimport type { AssetImageConfig } from \"@bearstudio/astro-assets-generation\";\n\nexport const config: AssetImageConfig = {\n  width: 1200,\n  height: 630,\n  debugScale: 0.5, // Optional: for debug view\n};\n\nexport default function OgImage({ params }: { params: { slug: string } }) {\n  return (\n    <FontWrapper fontFamily=\"Geist\">\n      <div\n        style={{\n          display: \"flex\",\n          flexDirection: \"column\",\n          width: \"100%\",\n          height: \"100%\",\n          padding: 64,\n          background: \"linear-gradient(135deg, #667eea 0%, #764ba2 100%)\",\n        }}\n      >\n        <h1 style={{ color: \"white\", fontSize: 72, fontWeight: \"bold\" }}>\n          My Blog Post\n        </h1>\n        <p style={{ color: \"white\", fontSize: 24 }}>Post: {params.slug}</p>\n      </div>\n    </FontWrapper>\n  );\n}\n```\n\n### 4. Create API Route\n\n```typescript\n// src/pages/blog/[slug]/assets/[__image].[__type].ts\nimport {\n  apiImageEndpoint,\n  getStaticPathsForAssets,\n} from \"@bearstudio/astro-assets-generation\";\nimport type { APIRoute } from \"astro\";\nimport { getCollection } from \"astro:content\";\nimport \"@/lib/assets\"; // Import your config\n\nconst modules = import.meta.glob(\"./_*.tsx\", { eager: true });\n\nexport const getStaticPaths = async () => {\n  const posts = await getCollection(\"blog\");\n  return getStaticPathsForAssets(\n    modules,\n    posts.map((post) => ({ slug: post.id }))\n  );\n};\n\nexport const GET: APIRoute = apiImageEndpoint(modules);\n```\n\n### 5. Access Your Images\n\n- **PNG**: `/blog/my-post/assets/og-image.png`\n- **JPEG**: `/blog/my-post/assets/og-image.jpg`\n- **Debug**: `/blog/my-post/assets/og-image.debug`\n\n## Using Dynamic Routes (with an Adapter)\n\nBy default, the examples above use `getStaticPaths` to pre-generate images at build time — no server adapter required.\n\nIf you need to generate images on-demand (e.g., for a very large number of routes or frequently changing content), you can use `prerender = false` instead. This requires an [Astro server adapter](https://docs.astro.build/en/guides/server-side-rendering/).\n\n### Install an adapter\n\n```bash\npnpm astro add vercel\n# or\npnpm astro add node\n```\n\n### Update `astro.config.mjs`\n\n```javascript\nimport { defineConfig } from \"astro/config\";\nimport react from \"@astrojs/react\";\nimport vercel from \"@astrojs/vercel\";\nimport { astroAssetsGeneration } from \"@bearstudio/astro-assets-generation\";\n\nexport default defineConfig({\n  integrations: [react(), astroAssetsGeneration()],\n  adapter: vercel(),\n});\n```\n\n### Update API Route\n\nReplace `getStaticPaths` with `prerender = false`:\n\n```typescript\n// src/pages/blog/[slug]/assets/[__image].[__type].ts\nimport { apiImageEndpoint } from \"@bearstudio/astro-assets-generation\";\nimport type { APIRoute } from \"astro\";\nimport \"@/lib/assets\";\n\nexport const prerender = false;\n\nexport const GET: APIRoute = apiImageEndpoint(\n  import.meta.glob(\"./_*.tsx\", { eager: true })\n);\n```\n\n### Drop `loadAsset` for serverless deployments\n\nWhen you ship to a serverless adapter (Vercel, Netlify, Cloudflare…), remove\n`loadAsset: diskLoader()` from your `configure()` call. The library will fetch\nimages and fonts from `siteUrl` at runtime, and the `disk-loader` import is no\nlonger needed. Keeping it in serverless builds causes file tracers like\n`@vercel/nft` to bundle your entire `dist/` into the function output.\n\n### Vercel\n\nNo Vercel-specific app config is required beyond adding the Vercel adapter and\n`astroAssetsGeneration()`. The integration handles Takumi's native Node binding\nfor the Vercel Linux runtime.\n\n## Font Management\n\n### Built-in Fallback Fonts\n\nThe library provides default fallback font definitions for Thai, Japanese,\nKorean, and Arabic. These fonts are loaded from a CDN on first render and\ncached automatically — no manual cache management required. Font subsetting\nis active by default: Takumi only processes the glyphs present in the rendered\ncontent, so loading a full CJK font only costs what the content actually uses.\n\nIf your deployment cannot rely on CDN access, register your own fonts via\n`customFonts`.\n\n### Custom Fonts\n\nAdd fonts in your configuration:\n\n```typescript\nconfigure({\n  customFonts: [\n    {\n      name: \"Tomorrow\", // Name used in CSS font-family declarations\n      url: \"/fonts/Tomorrow-Regular.ttf\", // /public path, absolute URL, or file path\n      weight: 400,\n      style: \"normal\",\n    },\n    {\n      name: \"Tomorrow\",\n      url: \"/fonts/Tomorrow-Bold.ttf\",\n      weight: 700,\n      style: \"normal\",\n    },\n  ],\n});\n```\n\nCustom fonts are lazy-loaded: fetched on first render and cached automatically\nby Takumi's internal key-based cache. Subsequent renders reuse the cached data.\n\n### FontWrapper Component\n\nWraps content with an automatic font-family stack that includes both your\ncustom fonts and the built-in non-Latin fallbacks:\n\n```tsx\nimport { FontWrapper } from \"@bearstudio/astro-assets-generation\";\n\n<FontWrapper fontFamily=\"Tomorrow\">\n  <div style={{ padding: 64 }}>\n    <p>English, 日本語, 한국어, العربية, ไทย - all supported!</p>\n  </div>\n</FontWrapper>;\n```\n\n## Emoji Support\n\nEmojis are detected and rendered automatically inside any text node. Just write them inline:\n\n```tsx\nreturn <h1>Hello 👋 World 🌍</h1>;\n```\n\nThe default provider is Twemoji. You can change it globally in `configure()` or\nper template via `AssetImageConfig`. The per-template value takes precedence.\n\n```typescript\n// Global default\nconfigure({ emoji: \"noto\" });\n```\n\n```tsx\n// Per-template override\nexport const config: AssetImageConfig = {\n  width: 1200,\n  height: 630,\n  emoji: \"fluent\",\n};\n```\n\nAvailable providers: `\"twemoji\"` (default), `\"blobmoji\"`, `\"noto\"`,\n`\"openmoji\"`, `\"fluent\"`, `\"fluentFlat\"`, `\"from-font\"`.\n\n`\"from-font\"` uses emoji glyphs embedded in your loaded fonts instead of\nfetching external images.\n\n## Styling\n\nUse inline styles via the `style` prop:\n\n```tsx\n<div\n  style={{\n    display: \"flex\",\n    alignItems: \"center\",\n    justifyContent: \"center\",\n    width: \"100%\",\n    height: \"100%\",\n    backgroundColor: \"#3b82f6\",\n  }}\n>\n  <h1 style={{ color: \"white\", fontSize: 96, fontWeight: \"bold\" }}>Hello</h1>\n</div>\n```\n\n## Working with Images\n\n### Astro Images\n\n```tsx\nimport { getAstroImageBase64 } from \"@bearstudio/astro-assets-generation\";\n\nconst avatarBase64 = await getAstroImageBase64(author.data.avatar);\n\n<img\n  src={avatarBase64}\n  style={{ width: 128, height: 128, borderRadius: 9999 }}\n/>;\n```\n\n### External Images\n\n```tsx\n<img src=\"https://example.com/image.jpg\" style={{ width: 256, height: 256 }} />\n```\n\n### JSX to Base64\n\nUse `jsxToBase64` to render any JSX component as a PNG and get a base64 data URI. This is useful for embedding generated images inside other templates.\n\n```tsx\nimport { jsxToBase64 } from \"@bearstudio/astro-assets-generation\";\n\nconst base64 = await jsxToBase64(\n  <div tw=\"flex items-center justify-center w-full h-full bg-blue-500\">\n    <h1 tw=\"text-white text-4xl\">Hello</h1>\n  </div>,\n  { width: 600, height: 300 }\n);\n\n<img src={base64} tw=\"w-64 h-32\" />;\n```\n\n## API Reference\n\n### Functions\n\n#### `configure(config)`\n\n```typescript\nconfigure({\n  debugBackground: \"#0a0a0a\",\n  siteUrl: \"https://example.com\",\n  isDev: import.meta.env.DEV,\n  customFonts: [\n    /* ... */\n  ], // Optional\n  emoji: \"twemoji\", // Optional. Default: \"twemoji\"\n  // Optional. Resolves `getAstroImageBase64` images and `/`-prefixed font\n  // URLs before falling back to fetch. Required for `output: 'static'`.\n  loadAsset: diskLoader(),\n});\n```\n\n#### `diskLoader(options?)`\n\nImported from `@bearstudio/astro-assets-generation/disk-loader`. Returns an\n`AssetLoader` that reads a request URL from disk, looking under\n`process.cwd()/dist/` then `process.cwd()/public/` by default.\n\n```typescript\nimport { diskLoader } from \"@bearstudio/astro-assets-generation/disk-loader\";\n\nloadAsset: diskLoader();\nloadAsset: diskLoader({ directories: [\"dist\", \"public\", \"custom\"] });\n```\n\nLives in a sub-export so its `process.cwd()` references stay out of the main\nentry — without that split, `@vercel/nft` would trace `dist/**` into\nserverless function bundles.\n\n#### `apiImageEndpoint(modules)`\n\nCreates an Astro API route handler:\n\n```typescript\nexport const GET = apiImageEndpoint(\n  import.meta.glob(\"./_*.tsx\", { eager: true })\n);\n```\n\n#### `getStaticPathsForAssets(modules, parentParams, imageTypes?)`\n\nGenerates static paths for all combinations of templates and image types. Automatically derives template names from the glob modules.\n\n```typescript\nconst modules = import.meta.glob(\"./_*.tsx\", { eager: true });\n\nexport const getStaticPaths = async () => {\n  const posts = await getCollection(\"blog\");\n  return getStaticPathsForAssets(\n    modules,\n    posts.map((post) => ({ slug: post.id }))\n    // optional 3rd arg: [\"png\", \"jpg\"] by default\n  );\n};\n```\n\n#### `getAstroImageBase64(image)`\n\nConverts Astro image to base64 data URI.\n\n#### `jsxToBase64(component, config)`\n\nRenders a JSX element as a PNG and returns a base64 data URI. Useful for embedding a generated image inside another template.\n\n```typescript\nconst base64 = await jsxToBase64(<MyComponent />, { width: 600, height: 300 });\n```\n\n### Components\n\n#### `<FontWrapper fontFamily=\"Geist\">`\n\nWraps content with automatic font fallback support.\n\n### Types\n\n#### `AssetImageConfig`\n\n```typescript\ninterface AssetImageConfig {\n  width: number;\n  height: number;\n  debugScale?: number; // Scale factor for debug view. Default: 0.5\n  emoji?: EmojiType; // Overrides the global default set in configure()\n}\n```\n\n#### `EmojiType`\n\n```typescript\ntype EmojiType =\n  | \"twemoji\" // Default\n  | \"blobmoji\"\n  | \"noto\"\n  | \"openmoji\"\n  | \"fluent\"\n  | \"fluentFlat\"\n  | \"from-font\"; // Use emoji glyphs from loaded fonts, no external fetch\n```\n\n#### `FontConfig`\n\n```typescript\ninterface FontConfig {\n  name: string; // Used in CSS font-family declarations\n  url: string; // HTTP/HTTPS URL, /public path, or absolute file path\n  weight: number; // 100–900\n  style: \"normal\" | \"italic\";\n}\n```\n\n#### `AssetLoader`\n\n```typescript\ntype AssetLoader = (url: string) => Promise<Buffer | null | undefined>;\n```\n\nReturn `null` or `undefined` to fall back to fetch.\n\n## Troubleshooting\n\n**Images not generating?**\n\n- Verify template starts with `_` (e.g., `_og-image.tsx`)\n- Check API route uses `[__image].[__type].ts` (double underscores)\n- Import config file in API route\n\n**Fonts not loading?**\n\n- Verify font name matches internal font name\n- Check `siteUrl` is correct in production\n- Ensure custom font URLs are accessible from production URL\n- Ensure the deployment environment can reach the CDN for built-in fallback fonts\n\n**Emojis not rendering?**\n\n- Ensure the deployment environment can reach the CDN for the configured emoji provider\n- Use `emoji: \"from-font\"` if your fonts include emoji glyphs and external CDN access is restricted\n\n**Vercel cannot load Takumi native bindings?**\n\n- Ensure `astroAssetsGeneration()` is present in `astro.config`\n- Ensure optional dependencies are installed during deployment (`@takumi-rs/core-linux-x64-gnu`)\n\n**Styling issues?**\n\n- Use the `style` prop with inline CSS objects\n- Test in debug mode (`.debug` extension)\n- Stick to well-supported CSS features\n\n## Example: Blog OG Image\n\n```tsx\n// src/pages/blog/[slug]/assets/_og-image.tsx\nimport { FontWrapper } from \"@bearstudio/astro-assets-generation\";\nimport { getEntry } from \"astro:content\";\n\nexport const config = { width: 1200, height: 630 };\n\nexport default async function BlogOgImage({\n  params,\n}: {\n  params: { slug: string };\n}) {\n  const post = await getEntry(\"blog\", params.slug);\n\n  return (\n    <FontWrapper fontFamily=\"Geist\" style={{ width: \"100%\", height: \"100%\" }}>\n      <div\n        style={{\n          display: \"flex\",\n          flexDirection: \"column\",\n          width: \"100%\",\n          height: \"100%\",\n          padding: 64,\n          background: \"linear-gradient(135deg, #667eea 0%, #764ba2 100%)\",\n        }}\n      >\n        <div\n          style={{\n            display: \"flex\",\n            alignItems: \"center\",\n            marginBottom: \"auto\",\n          }}\n        >\n          <h1 style={{ color: \"white\", fontSize: 72, fontWeight: \"bold\" }}>\n            {post.data.title}\n          </h1>\n        </div>\n        <div\n          style={{\n            display: \"flex\",\n            alignItems: \"center\",\n            justifyContent: \"space-between\",\n          }}\n        >\n          <p style={{ color: \"white\", fontSize: 24 }}>{post.data.author}</p>\n          <p style={{ color: \"white\", fontSize: 24 }}>\n            {new Date(post.data.date).toLocaleDateString()}\n          </p>\n        </div>\n      </div>\n    </FontWrapper>\n  );\n}\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}