Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
feat(website): improve SEO
  • Loading branch information
plouc committed Dec 26, 2021
1 parent 74d9872 commit f39dc01
Show file tree
Hide file tree
Showing 5 changed files with 225 additions and 95 deletions.
72 changes: 39 additions & 33 deletions website/gatsby-config.js
@@ -1,36 +1,42 @@
const siteUrl = process.env.SITE_URL || 'https://nivo.rocks' // no trailing slash

module.exports = {
siteMetadata: {
title: `nivo`,
description: `Supercharged React dataviz components, built on top of d3js.`,
author: `Raphaël Benitte`,
},
plugins: [
`gatsby-plugin-react-helmet`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `assets`,
path: `${__dirname}/src/assets`,
},
siteMetadata: {
title: `nivo`,
description: `Supercharged React dataviz components.`,
siteUrl,
og: {
siteName: 'nivo',
twitterCreator: '@benitteraphael',
},
},
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
{
resolve: `gatsby-plugin-styled-components`,
options: {},
},
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `nivo`,
short_name: `nivo`,
start_url: `/`,
background_color: `#3c91e8`,
theme_color: `#3c91e8`,
display: `minimal-ui`,
icon: `src/assets/icons/nivo-icon.png`, // This path is relative to the root of the site.
},
},
`gatsby-plugin-offline`,
],
plugins: [
`gatsby-plugin-react-helmet`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `assets`,
path: `${__dirname}/src/assets`,
},
},
`gatsby-plugin-image`,
`gatsby-transformer-sharp`,
`gatsby-plugin-sharp`,
{
resolve: `gatsby-plugin-styled-components`,
options: {},
},
{
resolve: `gatsby-plugin-manifest`,
options: {
name: `nivo`,
short_name: `nivo`,
start_url: `/`,
background_color: `#3c91e8`,
theme_color: `#3c91e8`,
display: `minimal-ui`,
icon: `src/assets/icons/nivo-icon.png`, // This path is relative to the root of the site.
},
},
],
}
1 change: 1 addition & 0 deletions website/package.json
Expand Up @@ -39,6 +39,7 @@
"dedent-js": "^1.0.1",
"gatsby": "^4.4.0",
"gatsby-image": "^3.11.0",
"gatsby-plugin-image": "^2.4.0",
"gatsby-plugin-manifest": "^4.4.0",
"gatsby-plugin-offline": "^5.4.0",
"gatsby-plugin-react-helmet": "^5.4.0",
Expand Down
177 changes: 120 additions & 57 deletions website/src/components/Seo.tsx
@@ -1,87 +1,150 @@
import React from 'react'
import Helmet from 'react-helmet'
import { useStaticQuery, graphql } from 'gatsby'
import { IGatsbyImageData, getSrc } from 'gatsby-plugin-image'
// @ts-ignore
import { useLocation } from '@gatsbyjs/reach-router'

interface Meta {
name: string
content: string
}

interface SeoProps {
title: string
description?: string
image?: IGatsbyImageData
lang?: string
meta?: object[]
meta?: Meta[]
keywords?: string[]
}

interface SiteData {
site: {
siteMetadata: {
title: string
description: string
siteUrl: string
og: {
siteName: string
twitterCreator: string
}
}
}
}

export const Seo = ({
title,
description = '',
title: _title,
description: _description,
image,
lang = 'en',
meta = [],
keywords = [],
keywords,
}: SeoProps) => {
const { site } = useStaticQuery(
const location = useLocation()

const { site } = useStaticQuery<SiteData>(
graphql`
query SiteMetaData {
site {
siteMetadata {
title
description
author
siteUrl
og {
siteName
twitterCreator
}
}
}
}
`
)

const metaDescription = description || site.siteMetadata.description
const title = _title || site.siteMetadata.title
const description = _description || site.siteMetadata.description

const metas: Meta[] = [
// TITLE
{
name: 'og:title',
content: title,
},
{
name: 'twitter:title',
content: title,
},
// DESCRIPTION
{
name: 'description',
content: description,
},
{
name: 'og:description',
content: description,
},
{
name: 'twitter:description',
content: description,
},
// OTHERS
{
name: 'og:type',
content: 'website',
},
{
name: 'og:site_name',
content: site.siteMetadata.og.siteName,
},
{
name: 'twitter:card',
content: 'summary_large_image',
},
{
name: 'twitter:creator',
content: site.siteMetadata.og.twitterCreator,
},
{
name: 'og:url',
content: `${site.siteMetadata.siteUrl}${location.pathname}`,
},
]

if (keywords) {
metas.push({
name: `keywords`,
content: keywords.join(`, `),
})
}

if (image) {
metas.push({
name: 'og:image:width',
content: `${image.width}`,
})
metas.push({
name: 'og:image:height',
content: `${image.height}`,
})

const imageSrc = `${site.siteMetadata.siteUrl}${getSrc(image)!}`
metas.push({
name: 'og:image:secure_url',
content: imageSrc,
})
metas.push({
name: 'twitter:image',
content: imageSrc,
})
}

return (
<Helmet
htmlAttributes={{
lang,
}}
title={title}
titleTemplate={`%s | ${site.siteMetadata.title}`}
meta={[
{
name: `description`,
content: metaDescription,
},
{
property: `og:title`,
content: title,
},
{
property: `og:description`,
content: metaDescription,
},
{
property: `og:type`,
content: `website`,
},
{
name: `twitter:card`,
content: `summary`,
},
{
name: `twitter:creator`,
content: site.siteMetadata.author,
},
{
name: `twitter:title`,
content: title,
},
{
name: `twitter:description`,
content: metaDescription,
},
...meta,
].concat(
keywords.length > 0
? {
name: `keywords`,
content: keywords.join(`, `),
}
: []
)}
/>
<Helmet titleTemplate={`%s | ${site.siteMetadata.title}`}>
<html lang={lang} />
<meta charSet="utf-8" />
<title>{title}</title>
{metas.map(meta => (
<meta key={meta.name} name={meta.name} content={meta.content} />
))}
</Helmet>
)
}
6 changes: 5 additions & 1 deletion website/src/components/components/ComponentTemplate.tsx
@@ -1,5 +1,6 @@
import React, { useState, useCallback, useMemo } from 'react'
import { Theme as NivoTheme } from '@nivo/core'
import { startCase } from 'lodash'
import { Seo } from '../Seo'
import Layout from '../Layout'
import { useTheme } from '../../theming/context'
Expand Down Expand Up @@ -61,6 +62,7 @@ export const ComponentTemplate = <
dataKey,
getDataSize,
getTabData = data => data,
image,
children,
}: ComponentTemplateProps<UnmappedProps, Props, Data>) => {
const theme = useTheme()
Expand Down Expand Up @@ -93,14 +95,16 @@ export const ComponentTemplate = <

const hasStories = meta.stories !== undefined && meta.stories.length > 0

const title = `${startCase(name)} chart`
const description = `${meta.package} package ${startCase(name)} chart.`
const tags = useMemo(() => [meta.package, ...meta.tags], [meta])

const flavorKeys = useMemo(() => flavors.map(flavor => flavor.flavor), [flavors])

return (
<Layout>
<ComponentPage>
<Seo title={name} keywords={tags} />
<Seo title={title} description={description} image={image} keywords={tags} />
<ComponentHeader chartClass={name} tags={tags} />
<ComponentFlavorSelector flavors={flavors} current={currentFlavor} />
<ComponentDescription description={meta.description} />
Expand Down

0 comments on commit f39dc01

Please sign in to comment.