mirror of
https://github.com/vercel/commerce.git
synced 2025-08-11 19:31:23 +00:00
.github
.vscode
ISSUE_TEMPLATE
cypress
packages
site
assets
components
auth
cart
checkout
common
Avatar
FeatureBar
Footer
Head
HomeAllProductsGrid
I18nWidget
Layout
Navbar
SEO
SEO.tsx
index.ts
Searchbar
SidebarLayout
UserNav
index.ts
icons
product
ui
wishlist
search.tsx
config
lib
pages
public
.env.template
.eslintrc
.gitignore
.prettierignore
.prettierrc
comments.md
commerce-config.js
commerce.config.json
global.d.ts
next-env.d.ts
next.config.js
package.json
postcss.config.js
tailwind.config.js
tsconfig.json
.editorconfig
.gitignore
.prettierignore
.prettierrc
README.md
cypress.json
license.md
package.json
turbo.json
yarn.lock
* replace next-seo with custom solution * Updated check Co-authored-by: LFades <luis@vercel.com>
158 lines
3.9 KiB
TypeScript
158 lines
3.9 KiB
TypeScript
import Head from 'next/head'
|
|
import { FC, Fragment, ReactNode } from 'react'
|
|
import config from '@config/seo_meta.json'
|
|
|
|
const storeUrl =
|
|
process.env.NEXT_PUBLIC_STORE_URL || process.env.NEXT_PUBLIC_VERCEL_URL
|
|
const storeBaseUrl = storeUrl ? `https://${storeUrl}` : null
|
|
|
|
interface OgImage {
|
|
url?: string
|
|
width?: string
|
|
height?: string
|
|
alt?: string
|
|
}
|
|
|
|
interface Props {
|
|
title?: string
|
|
description?: string
|
|
robots?: string
|
|
openGraph?: {
|
|
title?: string
|
|
type?: string
|
|
locale?: string
|
|
description?: string
|
|
site_name?: string
|
|
url?: string
|
|
images?: OgImage[]
|
|
}
|
|
children?: ReactNode
|
|
}
|
|
|
|
const ogImage = ({ url, width, height, alt }: OgImage, index: number) => {
|
|
// generate full URL for OG image url with store base URL
|
|
const imgUrl = storeBaseUrl ? new URL(url!, storeBaseUrl).toString() : url
|
|
return (
|
|
<Fragment key={`og:image:${index}`}>
|
|
<meta
|
|
key={`og:image:url:${index}`}
|
|
property="og:image"
|
|
content={imgUrl}
|
|
/>
|
|
<meta
|
|
key={`og:image:width:${index}`}
|
|
property="og:image:width"
|
|
content={width}
|
|
/>
|
|
<meta
|
|
key={`og:image:height:${index}`}
|
|
property="og:image:height"
|
|
content={height}
|
|
/>
|
|
<meta
|
|
key={`og:image:alt:${index}`}
|
|
property="og:image:alt"
|
|
content={alt}
|
|
/>
|
|
</Fragment>
|
|
)
|
|
}
|
|
|
|
const SEO: FC<Props> = ({
|
|
title,
|
|
description,
|
|
openGraph,
|
|
robots,
|
|
children,
|
|
}) => {
|
|
/**
|
|
* @see https://nextjs.org/docs/api-reference/next/head
|
|
*
|
|
* meta or any other elements need to be contained as direct children of the Head element,
|
|
* or wrapped into maximum one level of <React.Fragment> or arrays
|
|
* otherwise the tags won't be correctly picked up on client-side navigations.
|
|
*
|
|
* The `key` property makes the tag is only rendered once,
|
|
*/
|
|
return (
|
|
<Head>
|
|
<title key="title">
|
|
{title ? `${config.titleTemplate.replace(/%s/g, title)}` : config.title}
|
|
</title>
|
|
<meta
|
|
key="description"
|
|
name="description"
|
|
content={description || config.description}
|
|
/>
|
|
<meta
|
|
key="og:type"
|
|
property="og:type"
|
|
content={openGraph?.type ?? config.openGraph.type}
|
|
/>
|
|
<meta
|
|
key="og:title"
|
|
property="og:title"
|
|
content={
|
|
openGraph?.title ?? config.openGraph.title ?? title ?? config.title
|
|
}
|
|
/>
|
|
<meta
|
|
key="og:description"
|
|
property="og:description"
|
|
content={
|
|
openGraph?.description ??
|
|
config.openGraph.description ??
|
|
description ??
|
|
config.description
|
|
}
|
|
/>
|
|
<meta
|
|
key="og:site_name"
|
|
property="og:site_name"
|
|
content={openGraph?.site_name ?? config.openGraph.site_name}
|
|
/>
|
|
<meta
|
|
key="og:url"
|
|
property="og:url"
|
|
content={openGraph?.url ?? config.openGraph.url}
|
|
></meta>
|
|
{openGraph?.locale && (
|
|
<meta key="og:locale" property="og:locale" content={openGraph.locale} />
|
|
)}
|
|
{openGraph?.images?.length
|
|
? openGraph.images.map((img, index) => ogImage(img, index))
|
|
: ogImage(config.openGraph.images[0], 0)}
|
|
{config.twitter.cardType && (
|
|
<meta
|
|
key="twitter:card"
|
|
name="twitter:card"
|
|
content={config.twitter.cardType}
|
|
/>
|
|
)}
|
|
{config.twitter.site && (
|
|
<meta
|
|
key="twitter:site"
|
|
name="twitter:site"
|
|
content={config.twitter.site}
|
|
/>
|
|
)}
|
|
{config.twitter.handle && (
|
|
<meta
|
|
key="twitter:creator"
|
|
name="twitter:creator"
|
|
content={config.twitter.handle}
|
|
/>
|
|
)}
|
|
<meta key="robots" name="robots" content={robots ?? 'index,follow'} />
|
|
<meta
|
|
key="googlebot"
|
|
name="googlebot"
|
|
content={robots ?? 'index,follow'}
|
|
></meta>
|
|
{children}
|
|
</Head>
|
|
)
|
|
}
|
|
|
|
export default SEO
|