Merge pull request #27 from rotary-dev-fellowship/feat-faviconGen

Dynamic manifest and favicon generation
This commit is contained in:
Emil Gulamov 2024-03-28 17:49:58 +04:00 committed by GitHub
commit f1df8825b8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 110 additions and 47 deletions

View file

@ -191,14 +191,6 @@ Static files served directly to the browser are within the `public` directory at
```md ```md
public/ public/
├── apple-touch-icon.png
├── favicon.ico
├── icon-192.png
├── icon-512.png
├── icon.svg
├── manifest.webmanifest
├── maskable_icon.png
├── maskable_icon_x512.png
├── scripts/ ├── scripts/
│ └── vendor/ │ └── vendor/
│ ├── gsap/ # Animations powered by GSAP (GreenSock Animation Platform) │ ├── gsap/ # Animations powered by GSAP (GreenSock Animation Platform)

View file

@ -22,6 +22,8 @@
"gsap": "^3.12.5", "gsap": "^3.12.5",
"html-minifier": "^4.0.0", "html-minifier": "^4.0.0",
"preline": "^2.0.3", "preline": "^2.0.3",
"sharp": "^0.33.3",
"sharp-ico": "^0.1.5",
"tailwindcss": "^3.4.1" "tailwindcss": "^3.4.1"
}, },
"devDependencies": { "devDependencies": {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

View file

@ -1,35 +0,0 @@
{
"short_name": "ScrewFast",
"name": "ScrewFast",
"icons": [
{
"src": "/icon-192.png",
"sizes": "192x192",
"type": "image/png",
"purpose": "any"
},
{
"src": "/icon-512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "any"
},
{
"src": "/maskable_icon_x512.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
},
{
"src": "/maskable_icon.png",
"sizes": "1000x1000",
"type": "image/png",
"purpose": "maskable"
}
],
"display": "minimal-ui",
"id": "/",
"start_url": "/",
"theme_color": "#FFEDD5",
"background_color": "#262626"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

View file

@ -1,4 +1,8 @@
--- ---
import { getImage } from "astro:assets";
import faviconSvgSrc from "@/images/icon.svg";
import faviconSrc from "@/images/icon.png";
// Default properties for the Meta component. These values are used if props are not provided. // Default properties for the Meta component. These values are used if props are not provided.
// 'title' sets the default page title for the website. // 'title' sets the default page title for the website.
// 'meta' sets a default description meta tag to describe the page content. // 'meta' sets a default description meta tag to describe the page content.
@ -35,6 +39,20 @@ const ogDescription: string =
"Equip your projects with ScrewFast's top-quality hardware tools and expert construction services. Trusted by industry leaders, ScrewFast offers simplicity, affordability, and reliability. Experience the difference with user-centric design and cutting-edge tools. Start exploring now!"; // Set the Open Graph description "Equip your projects with ScrewFast's top-quality hardware tools and expert construction services. Trusted by industry leaders, ScrewFast offers simplicity, affordability, and reliability. Experience the difference with user-centric design and cutting-edge tools. Start exploring now!"; // Set the Open Graph description
const URL: string = `${Astro.site}`; // Set the website URL in astro.config.mjs const URL: string = `${Astro.site}`; // Set the website URL in astro.config.mjs
const socialImage: string = `${Astro.site}/social.png`; // Set the path for the social media image const socialImage: string = `${Astro.site}/social.png`; // Set the path for the social media image
// Generate and optimize the favicon images
const faviconSvg = await getImage({
src: faviconSvgSrc,
format: 'svg',
});
const appleTouchIcon = await getImage({
src: faviconSrc,
width: 180,
height: 180,
format: 'png',
});
--- ---
<!-- Inject structured data into the page if provided. This data is formatted as JSON-LD, a method recommended by Google for structured data pass: <!-- Inject structured data into the page if provided. This data is formatted as JSON-LD, a method recommended by Google for structured data pass:
@ -73,15 +91,15 @@ const socialImage: string = `${Astro.site}/social.png`; // Set the path for the
<meta name="twitter:image" content={socialImage} /> <meta name="twitter:image" content={socialImage} />
<!-- Links to the webmanifest and sitemap --> <!-- Links to the webmanifest and sitemap -->
<link rel="manifest" href="/manifest.webmanifest" /> <link rel="manifest" href="/manifest.json" />
<!-- https://docs.astro.build/en/guides/integrations-guide/sitemap/ --> <!-- https://docs.astro.build/en/guides/integrations-guide/sitemap/ -->
<link rel="sitemap" href="/sitemap-index.xml" /> <link rel="sitemap" href="/sitemap-index.xml" />
<!-- Links for favicons --> <!-- Links for favicons -->
<link href="/favicon.ico" rel="icon" sizes="any" type="image/x-icon" /> <link href="/favicon.ico" rel="icon" sizes="any" type="image/x-icon" />
<link href="/icon.svg" rel="icon" type="image/svg+xml" sizes="any" /> <link href={faviconSvg.src} rel="icon" type="image/svg+xml" sizes="any" />
<meta name="mobile-web-app-capable" content="yes" /> <meta name="mobile-web-app-capable" content="yes" />
<link href="/apple-touch-icon.png" rel="apple-touch-icon" /> <link href={appleTouchIcon.src} rel="apple-touch-icon" />
<link href="/apple-touch-icon.png" rel="shortcut icon" /> <link href={appleTouchIcon.src} rel="shortcut icon" />
<!-- Set theme color --> <!-- Set theme color -->
<meta name="theme-color" content="#facc15" /> <meta name="theme-color" content="#facc15" />

View file

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View file

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View file

Before

Width:  |  Height:  |  Size: 987 B

After

Width:  |  Height:  |  Size: 987 B

28
src/pages/favicon.ico.ts Normal file
View file

@ -0,0 +1,28 @@
import type { APIRoute } from "astro";
import sharp from "sharp";
import ico from "sharp-ico";
import path from "node:path";
const faviconSrc = path.resolve("src/images/icon.png");
export const GET: APIRoute = async () => {
// Resize the image to multiple sizes
const sizes = [16, 32, 48, 64, 128, 256];
const buffers = await Promise.all(
sizes.map(async (size) => {
return await sharp(faviconSrc)
.resize(size)
.toFormat("png")
.toBuffer();
})
);
// Convert the image to an ICO file
const icoBuffer = ico.encode(buffers);
return new Response(icoBuffer, {
headers: { "Content-Type": "image/x-icon" },
});
};

View file

@ -0,0 +1,58 @@
import type { APIRoute, ImageMetadata } from "astro";
import { getImage } from "astro:assets";
import icon from "@/images/icon.png";
import maskableIcon from "@/images/icon-maskable.png";
interface Favicon {
purpose: 'any' | 'maskable' | 'monochrome';
src: ImageMetadata;
sizes: number[];
}
const sizes = [192, 512];
const favicons: Favicon[] = [
{
purpose: 'any',
src: icon,
sizes,
},
{
purpose: 'maskable',
src: maskableIcon,
sizes,
},
];
export const GET: APIRoute = async () => {
const icons = await Promise.all(
favicons.flatMap((favicon) =>
favicon.sizes.map(async (size) => {
const image = await getImage({
src: favicon.src,
width: size,
height: size,
format: "png",
});
return {
src: image.src,
sizes: `${image.options.width}x${image.options.height}`,
type: `image/${image.options.format}`,
purpose: favicon.purpose,
};
}),
),
);
const manifest = {
short_name: "ScrewFast",
name: "ScrewFast",
icons,
display: "minimal-ui",
id: "some-unique-id",
start_url: "/",
theme_color: "#FFEDD5",
background_color: "#262626",
};
return new Response(JSON.stringify(manifest));
};