Skip to main content

Seo Component

Seo component for Next.js

100 views

Code

import Head from 'next/head'; import { useRouter } from 'next/router'; import { openGraph } from '@/lib/helper'; const defaultMeta = { title: 'Next.js + Tailwind CSS + TypeScript Starter', siteName: 'Next.js + Tailwind CSS + TypeScript Starter', description: ' A starter for Next.js, Tailwind CSS, and TypeScript with Absolute Import, Seo, Link component, pre-configured with Husky', url: 'https://tsnext-tw.thcl.dev', image: 'https://edisonpadilla.com/favicon/large-og.jpg', type: 'website', robots: 'follow, index', }; type SeoProps = { date?: string; templateTitle?: string; } & Partial<typeof defaultMeta>; export default function Seo(props: SeoProps) { const router = useRouter(); const meta = { ...defaultMeta, ...props, }; meta['title'] = props.templateTitle ? `${props.templateTitle} | ${meta.siteName}` : meta.title; // Use siteName if there is templateTitle // but show full title if there is none meta.image = openGraph({ description: meta.description, siteName: props.templateTitle ? meta.siteName : meta.title, templateTitle: props.templateTitle, }); return ( <Head> <title>{meta.title}</title> <meta name='robots' content={meta.robots} /> <meta content={meta.description} name='description' /> <meta property='og:url' content={`${meta.url}${router.asPath}`} /> <link rel='canonical' href={`${meta.url}${router.asPath}`} /> {/* Open Graph */} <meta property='og:type' content={meta.type} /> <meta property='og:site_name' content={meta.siteName} /> <meta property='og:description' content={meta.description} /> <meta property='og:title' content={meta.title} /> <meta name='image' property='og:image' content={meta.image} /> {/* Twitter */} <meta name='twitter:card' content='summary_large_image' /> <meta name='twitter:site' content='@th_clarence' /> <meta name='twitter:title' content={meta.title} /> <meta name='twitter:description' content={meta.description} /> <meta name='twitter:image' content={meta.image} /> {meta.date && ( <> <meta property='article:published_time' content={meta.date} /> <meta name='publish_date' property='og:publish_date' content={meta.date} /> <meta name='author' property='article:author' content='Edison J. Padilla' /> </> )} {/* Favicons */} {favicons.map((linkProps) => ( <link key={linkProps.href} {...linkProps} /> ))} <meta name='msapplication-TileColor' content='#ffffff' /> <meta name='msapplication-TileImage' content='/favicon/ms-icon-144x144.png' /> <meta name='theme-color' content='#ffffff' /> </Head> ); } type Favicons = { rel: string; href: string; sizes?: string; type?: string; }; const favicons: Array<Favicons> = [ { 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: '/favicon/manifest.json', }, ];
tsx

Usage

import Seo from '@/components/Seo'; // If we don't want to override anything <Seo /> // Overrides <Seo title='Your page title' description='your description' />
tsx

You can also add props below to override the default SEO

title templateTitle description image type robots date -> {new Date(your date).toISOString()}
text

Open Graph Function

type OpenGraphType = { siteName: string; description: string; templateTitle?: string; logo?: string; }; export function openGraph({ siteName, templateTitle, description, logo = 'https://og.thcl.dev/images/logo.jpg', }: OpenGraphType): string { const ogLogo = encodeURIComponent(logo); const ogSiteName = encodeURIComponent(siteName.trim()); const ogTemplateTitle = templateTitle ? encodeURIComponent(templateTitle.trim()) : undefined; const ogDesc = encodeURIComponent(description.trim()); return `https://og.thcl.dev/api/general?siteName=${ogSiteName}&description=${ogDesc}&logo=${ogLogo}${ ogTemplateTitle ? `&templateTitle=${ogTemplateTitle}` : '' }`; }
ts