diff --git a/web/public/android-chrome-192x192.png b/web/public/android-chrome-192x192.png new file mode 100644 index 00000000..66699d85 Binary files /dev/null and b/web/public/android-chrome-192x192.png differ diff --git a/web/public/android-chrome-512x512.png b/web/public/android-chrome-512x512.png new file mode 100644 index 00000000..349347fa Binary files /dev/null and b/web/public/android-chrome-512x512.png differ diff --git a/web/public/apple-touch-icon.png b/web/public/apple-touch-icon.png new file mode 100644 index 00000000..08698e08 Binary files /dev/null and b/web/public/apple-touch-icon.png differ diff --git a/web/public/favicon-16x16.png b/web/public/favicon-16x16.png new file mode 100644 index 00000000..50f49a1d Binary files /dev/null and b/web/public/favicon-16x16.png differ diff --git a/web/public/favicon-32x32.png b/web/public/favicon-32x32.png new file mode 100644 index 00000000..613f3a7d Binary files /dev/null and b/web/public/favicon-32x32.png differ diff --git a/web/public/favicon.ico b/web/public/favicon.ico index 98fa22ce..9034ea55 100644 Binary files a/web/public/favicon.ico and b/web/public/favicon.ico differ diff --git a/web/public/favicon.png b/web/public/favicon.png deleted file mode 100644 index c3275d00..00000000 Binary files a/web/public/favicon.png and /dev/null differ diff --git a/web/public/favicon.svg b/web/public/favicon.svg deleted file mode 100644 index d3f858ca..00000000 --- a/web/public/favicon.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/web/public/site.webmanifest b/web/public/site.webmanifest new file mode 100644 index 00000000..d8091890 --- /dev/null +++ b/web/public/site.webmanifest @@ -0,0 +1 @@ +{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#FA5252","background_color":"#1B1B1D","display":"standalone"} \ No newline at end of file diff --git a/web/src/app/icons/[icon]/page.tsx b/web/src/app/icons/[icon]/page.tsx index 6e685a3c..e1e5021b 100644 --- a/web/src/app/icons/[icon]/page.tsx +++ b/web/src/app/icons/[icon]/page.tsx @@ -30,16 +30,26 @@ export async function generateMetadata({ params, searchParams }: Props, parent: const authorData = await getAuthorData(iconsData[icon].update.author.id) const authorName = authorData.name || authorData.login const updateDate = new Date(iconsData[icon].update.timestamp) + const totalIcons = Object.keys(iconsData).length console.debug(`Generated metadata for ${icon} by ${authorName} (${authorData.html_url}) updated at ${updateDate.toLocaleString()}`) const iconImageUrl = `${BASE_URL}/png/${icon}.png` const pageUrl = `${BASE_URL}/icons/${icon}` + const formattedIconName = icon.split('-').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ') return { - title: `${icon} icon · Dashboard Icons`, - description: `Download and use the ${icon} icon from Dashboard Icons for your applications`, - keywords: [`${icon} icon`, "dashboard icon", "free icon", "open source icon", "application icon"], + title: `${formattedIconName} Icon | Dashboard Icons`, + description: `Download the ${formattedIconName} icon in SVG, PNG, and WEBP formats. Part of a collection of ${totalIcons} curated icons for services, applications and tools, designed specifically for dashboards and app directories.`, + keywords: [ + `${formattedIconName} icon`, + "dashboard icon", + "service icon", + "application icon", + "tool icon", + "web dashboard", + "app directory", + ], authors: [ { name: "homarr", @@ -51,8 +61,8 @@ export async function generateMetadata({ params, searchParams }: Props, parent: }, ], openGraph: { - title: `${icon} icon · Dashboard Icons`, - description: `Download and use the ${icon} icon from Dashboard Icons for your applications`, + title: `${formattedIconName} Icon | Dashboard Icons`, + description: `Download the ${formattedIconName} icon in SVG, PNG, and WEBP formats. Part of a collection of ${totalIcons} curated icons for services, applications and tools, designed specifically for dashboards and app directories.`, type: "article", url: pageUrl, images: [ @@ -60,7 +70,7 @@ export async function generateMetadata({ params, searchParams }: Props, parent: url: iconImageUrl, width: 512, height: 512, - alt: `${icon} icon`, + alt: `${formattedIconName} Icon`, type: "image/png", }, ...previousImages, @@ -71,10 +81,10 @@ export async function generateMetadata({ params, searchParams }: Props, parent: }, twitter: { card: "summary_large_image", - title: `${icon} icon · Dashboard Icons`, - description: `Download and use the ${icon} icon from Dashboard Icons for your applications`, + title: `${formattedIconName} Icon | Dashboard Icons`, + description: `Download the ${formattedIconName} icon in SVG, PNG, and WEBP formats. Part of a collection of ${totalIcons} curated icons for services, applications and tools, designed specifically for dashboards and app directories.`, images: [iconImageUrl], - creator: "@ajnavocado", + creator: "@homarr_app", }, alternates: { canonical: pageUrl, diff --git a/web/src/app/icons/page.tsx b/web/src/app/icons/page.tsx index eb825316..9acaa359 100644 --- a/web/src/app/icons/page.tsx +++ b/web/src/app/icons/page.tsx @@ -3,34 +3,48 @@ import { getIconsArray } from "@/lib/api" import type { Metadata } from "next" import { IconSearch } from "./components/icon-search" -export const metadata: Metadata = { - title: "Browse icons | Dashboard Icons", - description: "Search and browse through our collection of beautiful dashboard icons for your applications", - keywords: ["dashboard icons", "browse icons", "icon search", "free icons", "open source icons"], - openGraph: { - title: "Browse Dashboard Icons Collection", - description: "Search and browse through our collection of beautiful dashboard icons for your applications", - type: "website", - url: `${BASE_URL}/icons`, - images: [ - { - url: "/og-image-browse.png", - width: 1200, - height: 630, - alt: "Browse Dashboard Icons", - type: "image/png", - }, +export async function generateMetadata(): Promise { + const icons = await getIconsArray() + const totalIcons = icons.length + + return { + title: "Browse Icons | Dashboard Icons", + description: `Search and browse through our collection of ${totalIcons} curated icons for services, applications and tools, designed specifically for dashboards and app directories.`, + keywords: [ + "browse icons", + "dashboard icons", + "icon search", + "service icons", + "application icons", + "tool icons", + "web dashboard", + "app directory", ], - }, - twitter: { - card: "summary_large_image", - title: "Browse Dashboard Icons Collection", - description: "Search and browse through our collection of beautiful dashboard icons for your applications", - images: ["/og-image-browse.png"], - }, - alternates: { - canonical: `${BASE_URL}/icons`, - }, + openGraph: { + title: "Browse Dashboard Icons Collection", + description: `Search and browse through our collection of ${totalIcons} curated icons for services, applications and tools, designed specifically for dashboards and app directories.`, + type: "website", + url: `${BASE_URL}/icons`, + images: [ + { + url: "/og-image-browse.png", + width: 1200, + height: 630, + alt: "Browse Dashboard Icons Collection", + type: "image/png", + }, + ], + }, + twitter: { + card: "summary_large_image", + title: "Browse Dashboard Icons Collection", + description: `Search and browse through our collection of ${totalIcons} curated icons for services, applications and tools, designed specifically for dashboards and app directories.`, + images: ["/og-image-browse.png"], + }, + alternates: { + canonical: `${BASE_URL}/icons`, + }, + } } export const dynamic = "force-static" diff --git a/web/src/app/layout.tsx b/web/src/app/layout.tsx index cdb8e9d0..bb631a4a 100644 --- a/web/src/app/layout.tsx +++ b/web/src/app/layout.tsx @@ -6,6 +6,7 @@ import { Inter } from "next/font/google"; import { Toaster } from "sonner"; import "./globals.css"; import { ThemeProvider } from "./theme-provider"; +import { getTotalIcons } from "@/lib/api" const inter = Inter({ variable: "--font-inter", @@ -18,76 +19,85 @@ export const viewport: Viewport = { themeColor: "#ffffff", }; -export const metadata: Metadata = { - metadataBase: new URL("https://icons.homarr.dev"), - title: "Dashboard Icons", - description: "Curated icons for your dashboard", - keywords: [ - "dashboard", - "icons", - "open source", - "free icons", - "dashboard design", - ], - robots: { - index: true, - follow: true, - "max-image-preview": "large", - "max-snippet": -1, - "max-video-preview": -1, - googleBot: "index, follow", - }, - openGraph: { - siteName: "Dashboard Icons", - type: "website", - locale: "en_US", - title: "Dashboard Icons", - description: "Curated icons for your dashboard", - url: "https://icons.homarr.dev", - images: [ - { - url: "/og-image.png", - width: 1200, - height: 630, - alt: "Dashboard Icons", - type: "image/png", - }, +export async function generateMetadata(): Promise { + const { totalIcons } = await getTotalIcons() + + return { + metadataBase: new URL("https://dashboardicons.com"), + title: "Dashboard Icons - Your definitive source for dashboard icons", + description: `A collection of ${totalIcons} curated icons for services, applications and tools, designed specifically for dashboards and app directories.`, + keywords: [ + "dashboard icons", + "service icons", + "application icons", + "tool icons", + "web dashboard", + "app directory", ], - }, - twitter: { - card: "summary_large_image", - site: "@homarr_app", - creator: "@homarr_app", - title: "Dashboard Icons", - description: "Curated icons for your dashboard", - images: ["/og-image.png"], - }, - applicationName: "Dashboard Icons", - appleWebApp: { - title: "Dashboard Icons", - statusBarStyle: "default", - capable: true, - }, - alternates: { - types: { - "application/rss+xml": "https://icons.homarr.dev/rss.xml", + robots: { + index: true, + follow: true, + "max-image-preview": "large", + "max-snippet": -1, + "max-video-preview": -1, + googleBot: "index, follow", }, - }, - icons: { - icon: [ - { - url: "/favicon.ico", - type: "image/x-icon", + openGraph: { + siteName: "Dashboard Icons", + type: "website", + locale: "en_US", + title: "Dashboard Icons - Your definitive source for dashboard icons", + description: `A collection of ${totalIcons} curated icons for services, applications and tools, designed specifically for dashboards and app directories.`, + url: "https://dashboardicons.com", + images: [ + { + url: "/og-image.png", + width: 1200, + height: 630, + alt: "Dashboard Icons", + type: "image/png", + }, + ], + }, + twitter: { + card: "summary_large_image", + site: "@homarr_app", + creator: "@homarr_app", + title: "Dashboard Icons - Your definitive source for dashboard icons", + description: `A collection of ${totalIcons} curated icons for services, applications and tools, designed specifically for dashboards and app directories.`, + images: ["/og-image.png"], + }, + applicationName: "Dashboard Icons", + appleWebApp: { + title: "Dashboard Icons", + statusBarStyle: "default", + capable: true, + }, + alternates: { + types: { + "application/rss+xml": "https://dashboardicons.com/rss.xml", }, - ], - shortcut: [ - { - url: "/favicon.ico", - type: "image/x-icon", - }, - ], - }, -}; + }, + icons: { + icon: [ + { url: "/favicon.ico", sizes: "any" }, + { url: "/favicon-16x16.png", sizes: "16x16", type: "image/png" }, + { url: "/favicon-32x32.png", sizes: "32x32", type: "image/png" }, + ], + apple: [ + { url: "/apple-touch-icon.png", sizes: "180x180", type: "image/png" }, + ], + other: [ + { + rel: "mask-icon", + url: "/safari-pinned-tab.svg", + color: "#000000", + }, + ], + }, + manifest: "/site.webmanifest", + } +} export default function RootLayout({ children, diff --git a/web/src/app/page.tsx b/web/src/app/page.tsx index 5dfc2bc8..0a1d82ff 100644 --- a/web/src/app/page.tsx +++ b/web/src/app/page.tsx @@ -3,33 +3,44 @@ import { BASE_URL } from "@/constants" import { getTotalIcons } from "@/lib/api" import type { Metadata } from "next" -export const metadata: Metadata = { - title: "Dashboard Icons - Beautiful icons for your dashboard", - description: "Free, open-source icons for your dashboard. Choose from hundreds of high-quality icons for your web applications.", - keywords: ["self hosted", "dashboard icons", "free icons", "open source icons", "web dashboard", "application icons"], - openGraph: { - title: "Dashboard Icons - Your definitive source for dashboard icons", - description: "Free, open-source icons for your dashboard. Choose from thousands of high-quality icons.", - type: "website", - url: BASE_URL, - images: [ - { - url: "/og-image.png", - width: 1200, - height: 630, - alt: "Dashboard Icons", - }, +export async function generateMetadata(): Promise { + const { totalIcons } = await getTotalIcons() + + return { + title: "Dashboard Icons - Beautiful icons for your dashboard", + description: `A collection of ${totalIcons} curated icons for services, applications and tools, designed specifically for dashboards and app directories.`, + keywords: [ + "dashboard icons", + "service icons", + "application icons", + "tool icons", + "web dashboard", + "app directory", ], - }, - twitter: { - title: "Dashboard Icons - Your definitive source for dashboard icons", - description: "Free, open-source icons for your dashboard. Choose from thousands of high-quality icons.", - card: "summary_large_image", - images: ["/og-image.png"], - }, - alternates: { - canonical: BASE_URL, - }, + openGraph: { + title: "Dashboard Icons - Your definitive source for dashboard icons", + description: `A collection of ${totalIcons} curated icons for services, applications and tools, designed specifically for dashboards and app directories.`, + type: "website", + url: BASE_URL, + images: [ + { + url: "/og-image.png", + width: 1200, + height: 630, + alt: "Dashboard Icons", + }, + ], + }, + twitter: { + title: "Dashboard Icons - Your definitive source for dashboard icons", + description: `A collection of ${totalIcons} curated icons for services, applications and tools, designed specifically for dashboards and app directories.`, + card: "summary_large_image", + images: ["/og-image.png"], + }, + alternates: { + canonical: BASE_URL, + }, + } } export default async function Home() {