diff --git a/package.json b/package.json index 71fbd70c..16990835 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,8 @@ "lint": "biome check", "lint:fix": "biome check --write", "check": "astro check", - "build:data": "node scripts/postinstall.mjs" + "build:data": "node scripts/postinstall.mjs", + "generate:og-assets": "node scripts/generate-og-assets.mjs" }, "dependencies": { "@astrojs/mdx": "^7.0.5", diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png new file mode 100644 index 00000000..8877c801 Binary files /dev/null and b/public/apple-touch-icon.png differ diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png new file mode 100644 index 00000000..e014abb2 Binary files /dev/null and b/public/favicon-32x32.png differ diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 00000000..c8155b4c Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/og-image.png b/public/og-image.png new file mode 100644 index 00000000..eb769dc0 Binary files /dev/null and b/public/og-image.png differ diff --git a/public/site.webmanifest b/public/site.webmanifest new file mode 100644 index 00000000..4a8ead31 --- /dev/null +++ b/public/site.webmanifest @@ -0,0 +1,19 @@ +{ + "name": "Fastify", + "short_name": "Fastify", + "description": "Fast and low overhead web framework, for Node.js", + "start_url": "/", + "display": "standalone", + "background_color": "#0a0b0d", + "theme_color": "#0a0b0d", + "icons": [ + { "src": "/favicon-32x32.png", "sizes": "32x32", "type": "image/png" }, + { "src": "/apple-touch-icon.png", "sizes": "180x180", "type": "image/png" }, + { + "src": "/og-image.png", + "sizes": "1200x630", + "type": "image/png", + "purpose": "any" + } + ] +} diff --git a/scripts/generate-og-assets.mjs b/scripts/generate-og-assets.mjs new file mode 100644 index 00000000..0227fa26 --- /dev/null +++ b/scripts/generate-og-assets.mjs @@ -0,0 +1,47 @@ +#!/usr/bin/env node +// @ts-nocheck +import { readFile, writeFile } from "node:fs/promises"; +import sharp from "sharp"; + +const ROOT = new URL("..", import.meta.url).pathname; +const SRC = `${ROOT}public/favicon.svg`; +const OUT = `${ROOT}public`; + +const svg = await readFile(SRC); + +// 1200x630 OG card: dark bg, logo centered inside a rounded inset square. +const OG_W = 1200; +const OG_H = 630; +const LOGO_PX = 360; +const logoB64 = svg.toString("base64"); +const ogSvg = Buffer.from( + ``, +); +await sharp(ogSvg).png().toFile(`${OUT}/og-image.png`); + +await sharp(svg).resize(180, 180).png().toFile(`${OUT}/apple-touch-icon.png`); + +await sharp(svg).resize(32, 32).png().toFile(`${OUT}/favicon-32x32.png`); + +// Wrap a 32x32 PNG in a minimal ICO container (1 image, type=icon) so Safari +// and IE accept it as a real .ico instead of guessing by filename. +const png = await sharp(svg).resize(32, 32).png().toBuffer(); +const header = Buffer.alloc(6 + 16); +header.writeUInt16LE(0, 0); +header.writeUInt16LE(1, 2); +header.writeUInt16LE(1, 4); +header.writeUInt8(32, 6); +header.writeUInt8(32, 7); +header.writeUInt16LE(1, 10); +header.writeUInt16LE(32, 12); +header.writeUInt32LE(png.length, 14); +header.writeUInt32LE(6 + 16, 18); +await writeFile(`${OUT}/favicon.ico`, Buffer.concat([header, png])); + +console.log( + "wrote: og-image.png, apple-touch-icon.png, favicon-32x32.png, favicon.ico", +); diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index 088d7fc2..8cbf5da1 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -18,20 +18,45 @@ const { description = SITE.description, } = Astro.props; const canonical = new URL(Astro.url.pathname, Astro.site ?? SITE.url).href; +const socialImage = new URL(withBase("/og-image.png"), Astro.site ?? SITE.url).href; +const jsonLd = JSON.stringify({ + "@context": "https://schema.org", + "@type": "WebSite", + name: SITE.name, + url: SITE.url, + description: SITE.description, +}); ---
-