diff --git a/package.json b/package.json index 46cac1aa..a4d18313 100644 --- a/package.json +++ b/package.json @@ -27,10 +27,10 @@ "dms2dec": "^1.1.0", "fast-exif": "^1.0.1", "fraction.js": "^4.0.9", - "gatsby": "^2.0.7", + "gatsby": "^2.0.8", "gatsby-awesome-pagination": "^0.2.1", - "gatsby-image": "^2.0.8", - "gatsby-plugin-catch-links": "^2.0.2", + "gatsby-image": "^2.0.9", + "gatsby-plugin-catch-links": "^2.0.3", "gatsby-plugin-feed": "^2.0.5", "gatsby-plugin-lunr": "^1.2.0", "gatsby-plugin-matomo": "^0.5.0", @@ -43,12 +43,12 @@ "gatsby-redirect-from": "^0.1.1", "gatsby-remark-autolink-headers": "^2.0.6", "gatsby-remark-copy-linked-files": "^2.0.5", - "gatsby-remark-images": "^2.0.1", + "gatsby-remark-images": "^2.0.2", "gatsby-remark-prismjs": "^3.0.0", "gatsby-remark-smartypants": "^2.0.5", "gatsby-source-filesystem": "^2.0.1", "gatsby-transformer-remark": "^2.1.3", - "gatsby-transformer-sharp": "^2.1.1", + "gatsby-transformer-sharp": "^2.1.2", "gatsby-transformer-yaml": "^2.1.1", "graphql": "^0.13.2", "intersection-observer": "^0.5.0", @@ -84,7 +84,7 @@ "stylelint": "^9.5.0", "stylelint-config-css-modules": "^1.3.0", "stylelint-config-standard": "^18.2.0", - "stylelint-scss": "^3.3.0" + "stylelint-scss": "^3.3.1" }, "engines": { "node": "^10.0.0" diff --git a/src/components/atoms/SEO.jsx b/src/components/atoms/SEO.jsx new file mode 100644 index 00000000..e9d8c320 --- /dev/null +++ b/src/components/atoms/SEO.jsx @@ -0,0 +1,145 @@ +import React, { Component } from 'react' +import PropTypes from 'prop-types' +import { StaticQuery, graphql } from 'gatsby' +import Helmet from 'react-helmet' + +const query = graphql` + query { + contentYaml { + title + tagline + url + author { + name + twitter + avatar { + childImageSharp { + resize(width: 160) { + src + } + } + } + } + } + } +` + +class SEO extends Component { + static propTypes = { + post: PropTypes.object, + slug: PropTypes.string, + postSEO: PropTypes.bool + } + + render() { + return ( + { + const siteMeta = data.contentYaml + const { post, slug, postSEO } = this.props + let title + let description + let image + let postURL + + if (postSEO) { + const postMeta = post.frontmatter + title = `${postMeta.title} ¦ ${siteMeta.tagline}` + description = postMeta.description + ? postMeta.description + : post.excerpt + image = postMeta.image.childImageSharp.fluid.src + postURL = `${siteMeta.url}${slug}` + } else { + title = `${siteMeta.title} ¦ ${siteMeta.tagline}` + description = siteMeta.tagline + image = siteMeta.author.avatar.childImageSharp.resize.src + } + + image = `${siteMeta.url}${image}` + const blogURL = siteMeta.url + const url = postSEO ? postURL : blogURL + + const schemaOrgJSONLD = [ + { + '@context': 'http://schema.org', + '@type': 'WebSite', + url: blogURL, + name: title, + alternateName: siteMeta.titleAlt ? siteMeta.titleAlt : '' + } + ] + + if (postSEO) { + schemaOrgJSONLD.push( + { + '@context': 'http://schema.org', + '@type': 'BreadcrumbList', + itemListElement: [ + { + '@type': 'ListItem', + position: 1, + item: { + '@id': postURL, + name: title, + image + } + } + ] + }, + { + '@context': 'http://schema.org', + '@type': 'BlogPosting', + url: blogURL, + name: title, + alternateName: siteMeta.titleAlt ? siteMeta.titleAlt : '', + headline: title, + image: { + '@type': 'ImageObject', + url: image + }, + description + } + ) + } + + return ( + + + + {/* General tags */} + + + + + {/* Schema.org tags */} + + + {/* OpenGraph tags */} + + {postSEO && } + + + + + {/* Twitter Card tags */} + + + + + + + ) + }} + /> + ) + } +} + +export default SEO diff --git a/src/templates/Post.jsx b/src/templates/Post.jsx index 487df9d1..9c9cc07a 100644 --- a/src/templates/Post.jsx +++ b/src/templates/Post.jsx @@ -8,6 +8,7 @@ import PostTitle from '../components/atoms/PostTitle' import PostLead from '../components/atoms/PostLead' import PostContent from '../components/atoms/PostContent' import PostActions from '../components/atoms/PostActions' +import SEO from '../components/atoms/SEO' import PostMeta from '../components/molecules/PostMeta' import Exif from '../components/atoms/Exif' import styles from './Post.module.scss' @@ -16,6 +17,7 @@ const Post = ({ data, location }) => { const { markdownRemark: post } = data const { contentYaml: meta } = data const { title, image, type, linkurl, style } = post.frontmatter + const { slug } = post.fields return ( @@ -23,19 +25,15 @@ const Post = ({ data, location }) => { {style && } + +
- - {image && } - {image && image.fields && } - - - - +
diff --git a/src/templates/Posts.jsx b/src/templates/Posts.jsx index b1103037..1618e15a 100644 --- a/src/templates/Posts.jsx +++ b/src/templates/Posts.jsx @@ -8,6 +8,7 @@ import PostLead from '../components/atoms/PostLead' import PostContent from '../components/atoms/PostContent' import PostMore from '../components/atoms/PostMore' import PostLinkActions from '../components/atoms/PostLinkActions' +import SEO from '../components/atoms/SEO' import Pagination from '../components/molecules/Pagination' import Featured from '../components/molecules/Featured' import styles from './Posts.module.scss' @@ -54,6 +55,7 @@ const Posts = ({ data, location, pageContext }) => { return ( + {location.pathname === '/' && } {tag &&

{tag}

} {previousPagePath && (