From bbb67d779b44eb973dd36e3a0cef9159d63eb232 Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Thu, 22 Nov 2018 20:58:42 +0100 Subject: [PATCH] SEO component * Twitter Cards * OpenGraph * schema.org --- src/components/Seo.jsx | 104 ++++++++++++++++++++++++++++++++++------- src/pages/404.jsx | 4 +- src/templates/Doc.jsx | 72 ++++++++++++++-------------- static/favicon.ico | Bin 32038 -> 0 bytes 4 files changed, 128 insertions(+), 52 deletions(-) delete mode 100644 static/favicon.ico diff --git a/src/components/Seo.jsx b/src/components/Seo.jsx index 40356978..251fc775 100644 --- a/src/components/Seo.jsx +++ b/src/components/Seo.jsx @@ -17,10 +17,65 @@ const query = graphql` } } } + + logo: allFile(filter: { name: { eq: "favicon-black" } }) { + edges { + node { + relativePath + } + } + } } ` -const MetaTags = ({ title, description, url, image, schema, siteMeta }) => ( +const createSchemaOrg = (title, description, image, url, siteMeta, article) => { + const schemaOrgJSONLD = [ + { + '@context': 'http://schema.org', + '@type': 'WebSite', + url: siteMeta.siteUrl, + name: title + } + ] + + if (article) { + schemaOrgJSONLD.push( + { + '@context': 'http://schema.org', + '@type': 'BreadcrumbList', + itemListElement: [ + { + '@type': 'ListItem', + position: 1, + item: { '@id': url, name: title, image } + } + ] + }, + { + // https://schema.org/TechArticle + '@context': 'http://schema.org', + '@type': 'TechArticle', + name: title, + headline: title, + description, + url, + image: { '@type': 'URL', url: image } + } + ) + } + + return schemaOrgJSONLD +} + +const MetaTags = ({ + title, + description, + url, + image, + schema, + siteMeta, + article +}) => ( ( {/* OpenGraph tags */} - {documentSEO && } + {article && } {/* Twitter Card tags */} - + @@ -59,27 +111,46 @@ const MetaTags = ({ title, description, url, image, schema, siteMeta }) => ( ) MetaTags.propTypes = { - description: PropTypes.string, - image: PropTypes.string, - url: PropTypes.string, - schema: PropTypes.string, title: PropTypes.string, - siteMeta: PropTypes.object + description: PropTypes.string, + url: PropTypes.string, + image: PropTypes.string, + schema: PropTypes.string, + siteMeta: PropTypes.object, + article: PropTypes.bool } -const SEO = ({ title, description, slug }) => ( +const SEO = ({ title, description, slug, article }) => ( { const siteMeta = data.site.siteMetadata + const logo = data.logo.edges[0].node.relativePath + + title = title || siteMeta.siteTitle + description = description || siteMeta.siteDescription + let url = siteMeta.siteUrl || siteMeta.siteUrl + slug + let image = `${siteMeta.siteUrl}/${logo}` + + let schema = createSchemaOrg( + title, + description, + image, + url, + siteMeta, + article + ) + schema = JSON.stringify(schema) return ( ) }} @@ -89,7 +160,8 @@ const SEO = ({ title, description, slug }) => ( SEO.propTypes = { title: PropTypes.string, description: PropTypes.string, - slug: PropTypes.string + slug: PropTypes.string, + article: PropTypes.bool } export default SEO diff --git a/src/pages/404.jsx b/src/pages/404.jsx index d6f3b96b..77c36fd8 100755 --- a/src/pages/404.jsx +++ b/src/pages/404.jsx @@ -6,7 +6,7 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' import { Link } from 'gatsby' import giphyAPI from 'giphy-js-sdk-core' -import Helmet from 'react-helmet' +import SEO from '../components/Seo' import Layout from '../components/Layout' import Content from '../components/Content' import styles from './404.module.scss' @@ -45,7 +45,7 @@ export default class NotFoundPage extends Component { render() { return ( <> - +
diff --git a/src/templates/Doc.jsx b/src/templates/Doc.jsx index e4fcd4d7..cf8d6005 100644 --- a/src/templates/Doc.jsx +++ b/src/templates/Doc.jsx @@ -13,6 +13,25 @@ import DocFooter from '../components/DocFooter' import SEO from '../components/Seo' import styles from './Doc.module.scss' +const DocMain = ({ title, description, tableOfContents, post, single }) => ( +
+ + + {tableOfContents && } + + + +
+) + +DocMain.propTypes = { + title: PropTypes.string.isRequired, + description: PropTypes.string.isRequired, + tableOfContents: PropTypes.string.isRequired, + post: PropTypes.object.isRequired, + single: PropTypes.bool +} + export default class DocTemplate extends Component { static propTypes = { data: PropTypes.object.isRequired, @@ -41,7 +60,12 @@ export default class DocTemplate extends Component { - + @@ -55,42 +79,21 @@ export default class DocTemplate extends Component { sidebar={section} /> -
- - - {tableOfContents && ( - - )} - - - -
- - ) : ( -
- - - {tableOfContents && ( - - )} - - - -
+ + ) : ( + )}
@@ -112,6 +115,7 @@ export const pageQuery = graphql` } fields { section + slug } ...PageFooter } diff --git a/static/favicon.ico b/static/favicon.ico deleted file mode 100644 index 7db1da346cf289d0d2f08199dd4b64f94a079c1e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32038 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