import Head from 'next/head'; import { useRouter } from 'next/router'; const defaultMeta = { title: 'Modern UI components with smooth transitions.', siteName: 'Fluid Design', description: 'A starter for Next.js, Tailwind CSS, and TypeScript with Absolute Import, Seo, Link component, pre-configured with Husky', /** Without additional '/' on the end, e.g. https://theodorusclarence.com */ url: 'https://fluid-design.io', type: 'website', robots: 'follow, index', /** * No need to be filled, will be populated with openGraph function * If you wish to use a normal image, just specify the path below */ image: '', author: 'Oliver Pan', }; type SeoProps = { date?: string; templateTitle?: string; category?: string; tags?: string[]; } & Partial; const openGraph = ({ title, author, cover, date, tags = [], category }) => { return ( `${process.env.NEXT_PUBLIC_BASE_URL}/api/og?` + `title=${encodeURIComponent(title)}` + `&author=${encodeURIComponent(author)}` + `&cover=${encodeURIComponent(cover)}` + `&date=${date}` + `&category=${category}` + `&tags=${tags.join(',') || ''}` ); }; export default function Seo(props: SeoProps) { const router = useRouter(); const meta = { ...defaultMeta, ...props, }; meta['title'] = props.templateTitle ? `${props.templateTitle} | ${meta.siteName}` : meta.title; meta['image'] = openGraph({ title: props.templateTitle ? meta.siteName : meta.title, author: meta?.author, cover: meta?.image, date: meta?.date, category: meta?.category, tags: meta?.tags, }); return ( {meta.title} {/* Open Graph */} {/* Twitter */} {meta.date && ( <> )} {/* Favicons */} {favicons.map((linkProps) => ( ))} ); } type Favicons = { rel: string; href: string; sizes?: string; type?: string; }; const favicons: Array = [ { rel: 'apple-touch-icon', sizes: '57x57', href: '/favicon/apple-icon-57x57.png', }, { rel: 'apple-touch-icon', sizes: '60x60', href: '/favicon/apple-icon-60x60.png', }, { rel: 'apple-touch-icon', sizes: '72x72', href: '/favicon/apple-icon-72x72.png', }, { rel: 'apple-touch-icon', sizes: '76x76', href: '/favicon/apple-icon-76x76.png', }, { rel: 'apple-touch-icon', sizes: '114x114', href: '/favicon/apple-icon-114x114.png', }, { rel: 'apple-touch-icon', sizes: '120x120', href: '/favicon/apple-icon-120x120.png', }, { rel: 'apple-touch-icon', sizes: '144x144', href: '/favicon/apple-icon-144x144.png', }, { rel: 'apple-touch-icon', sizes: '152x152', href: '/favicon/apple-icon-152x152.png', }, { rel: 'apple-touch-icon', sizes: '180x180', href: '/favicon/apple-icon-180x180.png', }, { rel: 'icon', type: 'image/png', sizes: '192x192', href: '/favicon/android-icon-192x192.png', }, { rel: 'icon', type: 'image/png', sizes: '32x32', href: '/favicon/favicon-32x32.png', }, { rel: 'icon', type: 'image/png', sizes: '96x96', href: '/favicon/favicon-96x96.png', }, { rel: 'icon', type: 'image/png', sizes: '16x16', href: '/favicon/favicon-16x16.png', }, { rel: 'manifest', href: '/manifest.json', }, ];