diff --git a/README.md b/README.md
index e804335..d7ce089 100644
--- a/README.md
+++ b/README.md
@@ -191,14 +191,6 @@ Static files served directly to the browser are within the `public` directory at
```md
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/
│ └── vendor/
│ ├── gsap/ # Animations powered by GSAP (GreenSock Animation Platform)
diff --git a/package.json b/package.json
index fce6831..06a0fd6 100644
--- a/package.json
+++ b/package.json
@@ -22,6 +22,8 @@
"gsap": "^3.12.5",
"html-minifier": "^4.0.0",
"preline": "^2.0.3",
+ "sharp": "^0.33.3",
+ "sharp-ico": "^0.1.5",
"tailwindcss": "^3.4.1"
},
"devDependencies": {
diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png
deleted file mode 100644
index 709d945..0000000
Binary files a/public/apple-touch-icon.png and /dev/null differ
diff --git a/public/favicon.ico b/public/favicon.ico
deleted file mode 100644
index 456b3a7..0000000
Binary files a/public/favicon.ico and /dev/null differ
diff --git a/public/icon-192.png b/public/icon-192.png
deleted file mode 100644
index 7a83b88..0000000
Binary files a/public/icon-192.png and /dev/null differ
diff --git a/public/manifest.webmanifest b/public/manifest.webmanifest
deleted file mode 100644
index ac95964..0000000
--- a/public/manifest.webmanifest
+++ /dev/null
@@ -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"
- }
\ No newline at end of file
diff --git a/public/maskable_icon_x512.png b/public/maskable_icon_x512.png
deleted file mode 100644
index 0c37558..0000000
Binary files a/public/maskable_icon_x512.png and /dev/null differ
diff --git a/src/components/Meta.astro b/src/components/Meta.astro
index d642a37..b3bd33e 100644
--- a/src/components/Meta.astro
+++ b/src/components/Meta.astro
@@ -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.
// 'title' sets the default page title for the website.
// '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
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
+
+// 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',
+});
+
---
-
+
-
+
-
-
+
+
diff --git a/public/maskable_icon.png b/src/images/icon-maskable.png
similarity index 100%
rename from public/maskable_icon.png
rename to src/images/icon-maskable.png
diff --git a/public/icon-512.png b/src/images/icon.png
similarity index 100%
rename from public/icon-512.png
rename to src/images/icon.png
diff --git a/public/icon.svg b/src/images/icon.svg
similarity index 100%
rename from public/icon.svg
rename to src/images/icon.svg
diff --git a/src/pages/favicon.ico.ts b/src/pages/favicon.ico.ts
new file mode 100644
index 0000000..891b87c
--- /dev/null
+++ b/src/pages/favicon.ico.ts
@@ -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" },
+ });
+};
diff --git a/src/pages/manifest.json.ts b/src/pages/manifest.json.ts
new file mode 100644
index 0000000..bab70e0
--- /dev/null
+++ b/src/pages/manifest.json.ts
@@ -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));
+};