Add more structured metadata

This commit is contained in:
Kevin Kandlbinder 2021-09-25 14:00:50 +02:00
parent df9e2b2bb8
commit 412ee72112
10 changed files with 148 additions and 5 deletions

View file

@ -1,3 +1,4 @@
{
"i18n-ally.localesPaths": "locales"
"i18n-ally.localesPaths": "locales",
"i18n-ally.keystyle": "nested"
}

View file

@ -10,9 +10,18 @@ module.exports = {
languages: ["en", "de"],
contactEmail: "kevin@kevink.dev",
contactPhone: "+4941068068004",
address: "25451 Quickborn, Schleswig-Holstein, Germany",
mapsLink: "https://goo.gl/maps/KVq9z1PVaVP2",
contactTwitter: "Unkn0wnKevin",
contactGitHub: "Unkn0wnCat",
contactMastodon: "@kevin@1in1.net",
contactMastodonHref: "https://mastodon.1in1.net/@kevin",
givenName: "Kevin",
familyName: "Kandlbinder",
birthDate: "2001-03-11",
gender: "Male",
height: "168 cm",
nationality: "Germany",
personImage: "./content/images/kevin-kandlbinder-04.jpg",
sameAs: ["https://mastodon.1in1.net/@kevin", "https://github.com/Unkn0wnCat", "https://unkn0wncat.net/", "https://twitter.com/@Unkn0wnKevin", "https://unsplash.com/@unkn0wncat"]
};

View file

@ -11,10 +11,19 @@ module.exports = {
contactEmail: extConfig.contactEmail,
contactPhone: extConfig.contactPhone,
mapsLink: extConfig.mapsLink,
address: extConfig.address,
contactTwitter: extConfig.contactTwitter,
contactGitHub: extConfig.contactGitHub,
contactMastodon: extConfig.contactMastodon,
contactMastodonHref: extConfig.contactMastodonHref,
givenName: extConfig.givenName,
familyName: extConfig.familyName,
birthDate: extConfig.birthDate,
gender: extConfig.gender,
height: extConfig.height,
nationality: extConfig.nationality,
personImage: extConfig.personImage,
sameAs: extConfig.sameAs
},
plugins: [
`gatsby-plugin-eslint`,

View file

@ -2,9 +2,11 @@ import React from "react";
import PropTypes from "prop-types";
import { Helmet } from "gatsby-plugin-react-i18next";
import { useStaticQuery, graphql } from "gatsby";
import { useLocation } from "@reach/router"
import { useTranslation } from "gatsby-plugin-react-i18next";
import useSiteMetadata from "../helpers/useSiteMetadata";
function SEO({ description, meta, title }) {
function SEO({ description, meta, title, speakable, image, children }) {
const { t } = useTranslation();
const { site } = useStaticQuery(
graphql`
@ -22,6 +24,10 @@ function SEO({ description, meta, title }) {
const metaDescription = description || t("siteDescription");
const siteMeta = useSiteMetadata();
const location = useLocation();
return (
<Helmet
title={title}
@ -79,6 +85,45 @@ function SEO({ description, meta, title }) {
data-domain="kevink.dev"
src="https://analytics.kevink.dev/js/plausible.js"
></script>
{
image && [
<meta name="twitter:image" content={meta.siteUrl + image} key="twimg"/>,
<meta name="og:image" content={meta.siteUrl + image} key="ogimg"/>,
]
}
<script type="application/ld+json">
{JSON.stringify({
"@context": "https://schema.org/",
"@type": "WebPage",
"name": title,
"url": siteMeta.siteUrl+location.pathname,
"speakable": speakable,
"image": meta.siteUrl + image,
"about": {
"@type": "Person",
"name": siteMeta.givenName + " " + siteMeta.familyName,
"givenName": siteMeta.givenName,
"familyName": siteMeta.familyName,
"birthDate": siteMeta.birthDate,
"address": siteMeta.address,
"email": siteMeta.contactEmail,
"telephone": siteMeta.contactPhone,
"gender": siteMeta.gender,
"height": siteMeta.height,
"nationality": {
"@type": "Country",
"name": siteMeta.nationality
},
"image": siteMeta.siteUrl + "/owner.jpg",
"sameAs": siteMeta.sameAs
}
})}
</script>
{children}
</Helmet>
);
}
@ -92,6 +137,9 @@ SEO.propTypes = {
description: PropTypes.string,
meta: PropTypes.arrayOf(PropTypes.object),
title: PropTypes.string.isRequired,
speakable: PropTypes.any,
image: PropTypes.string,
children: PropTypes.any
};
export default SEO;

View file

@ -0,0 +1,37 @@
import { useStaticQuery, graphql } from 'gatsby';
const useSiteMetadata = () => {
const { site } = useStaticQuery(
graphql`
query {
site {
siteMetadata {
title
keywords
author
siteUrl
payPalMail
contactEmail
contactPhone
mapsLink
contactTwitter
contactGitHub
contactMastodon
contactMastodonHref
givenName
familyName
birthDate
address
gender
height
nationality
sameAs
}
}
}
`,
);
return site.siteMetadata;
};
export default useSiteMetadata;

View file

@ -16,7 +16,9 @@ class Layout extends React.Component {
lang={this.props.lang}
meta={this.props.meta}
title={this.props.title}
/>
image={this.props.image}
speakable={this.props.speakable}
>{this.props.seoAdditional ?? null}</SEO>
<Navigation isHome={this.props.transparentTopbar} />
<div id="content" role="main">
{this.props.children}
@ -57,6 +59,9 @@ Layout.propTypes = {
title: PropTypes.string.isRequired,
transparentTopbar: PropTypes.bool,
children: PropTypes.any.isRequired,
seoAdditional: PropTypes.any,
image: PropTypes.string,
speakable: PropTypes.any
};
export default Layout;

View file

@ -112,7 +112,16 @@ const IndexPage = (props) => {
let file = props.data.file;
return (
<Layout title="Kevin Kandlbinder" transparentTopbar={true} description={t("siteDescription")}>
<Layout title="Kevin Kandlbinder" transparentTopbar={true} description={t("siteDescription")}
image={meta.siteUrl + "/owner.jpg"}
speakable={{
"@type": "SpeakableSpecification",
"xPath": [
"/html/head/title",
"/html/head/meta[@name='description']/@content",
"article"
]
}}>
<section className={styles.heroSection}>
<div
className={styles.heroSectionBg}

View file

@ -6,6 +6,7 @@ import PropTypes from "prop-types";
import * as styles from "./projects.module.scss";
import { GatsbyImage } from "gatsby-plugin-image";
import useSiteMetadata from "../helpers/useSiteMetadata";
export const query = graphql`
query GetProjects($language: String) {
@ -21,6 +22,7 @@ export const query = graphql`
childImageSharp {
gatsbyImageData(placeholder: BLURRED, layout: FULL_WIDTH)
}
publicURL
}
shortDescription
}
@ -39,8 +41,29 @@ export const query = graphql`
const ProjectsPage = ({ data }) => {
const { t } = useI18next();
const meta = useSiteMetadata();
return (
<Layout title={t("projects")} description={t("projectsDescription")}>
<Layout title={t("projects")} description={t("projectsDescription")} seoAdditional={
<script type="application/ld+json">
{JSON.stringify(
{
"@context":"https://schema.org",
"@type":"ItemList",
"itemListElement":data.allProjectsJson.nodes.map((project, i) => {
return {
"@type":"ListItem",
"position":i,
"url": meta.siteUrl+"/projects/"+project.urlname,
"image": project.image.publicURL,
"name": project.name,
"description": project.shortDescription
}
})
}
)}
</script>
}>
<section>
<article>
<h1>

View file

@ -26,6 +26,7 @@ export const query = graphql`
childImageSharp {
gatsbyImageData(placeholder: BLURRED, layout: FULL_WIDTH)
}
publicURL
}
shortDescription
}
@ -64,6 +65,7 @@ const ProjectTemplate = ({ data }) => {
description={project.shortDescription}
title={t("project") + ": " + projectName}
transparentTopbar={true}
image={project.image.publicURL}
>
<section className={styles.projectHeader}>
<div style={{ paddingTop: 0 }}>

BIN
static/owner.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB