diff --git a/lib/seo.ts b/lib/seo.ts new file mode 100644 index 00000000..feff1c00 --- /dev/null +++ b/lib/seo.ts @@ -0,0 +1,134 @@ +import * as config from "./config"; + +import type { DefaultSeoProps } from "next-seo"; +import type { SocialProfileJsonLdProps } from "next-seo/lib/jsonld/socialProfile"; +import type { ArticleJsonLdProps } from "next-seo/lib/jsonld/article"; + +import faviconIco from "../public/static/favicons/favicon.ico"; +import faviconPng from "../public/static/favicons/favicon.png"; +import appleTouchIconPng from "../public/static/favicons/apple-touch-icon.png"; +import meJpg from "../public/static/images/me.jpg"; + +// Most of this file simply takes the data already defined in ./config.js and translates it into objects that are +// compatible with next-seo's props: +// https://github.com/garmeeh/next-seo#default-seo-configuration + +export const defaultSeo: DefaultSeoProps = { + defaultTitle: `${config.siteName} – ${config.shortDescription}`, + titleTemplate: `%s – ${config.siteName}`, // appends `– siteName` to title provided by each page + description: config.longDescription, + openGraph: { + site_name: config.siteName, + title: `${config.siteName} – ${config.shortDescription}`, + locale: config.siteLocale, + type: "website", + images: [ + { + url: `${config.baseUrl}${meJpg.src}`, + alt: `${config.siteName} – ${config.shortDescription}`, + }, + ], + }, + twitter: { + handle: `@${config.authorSocial?.twitter}`, + site: `@${config.authorSocial?.twitter}`, + cardType: "summary", + }, + additionalMetaTags: [ + { + name: "viewport", + content: "width=device-width, initial-scale=1", + }, + { + name: "author", + content: config.authorName, + }, + { + name: "google-site-verification", + content: config.verifyGoogle, + }, + { + name: "msvalidate.01", + content: config.verifyBing, + }, + { + name: "facebook-domain-verification", + content: config.verifyFacebook, + }, + ], + additionalLinkTags: [ + { + rel: "icon", + href: faviconIco.src, + }, + { + rel: "icon", + href: faviconPng.src, + type: "image/png", + }, + { + rel: "apple-touch-icon", + href: appleTouchIconPng.src, + sizes: `${appleTouchIconPng.width}x${appleTouchIconPng.height}`, + }, + { + rel: "manifest", + href: "/site.webmanifest", + }, + { + rel: "alternate", + href: "/feed.xml", + type: "application/rss+xml", + // @ts-ignore + title: `${config.siteName} (RSS)`, + }, + { + rel: "alternate", + href: "/feed.atom", + type: "application/atom+xml", + // @ts-ignore + title: `${config.siteName} (Atom)`, + }, + { + rel: "webmention", + href: `https://webmention.io/${config.webmentionId}/webmention`, + }, + { + rel: "pingback", + href: `https://webmention.io/${config.webmentionId}/xmlrpc`, + }, + { + rel: "humans", + href: "/humans.txt", + }, + { + rel: "pgpkey", + href: "/pubkey.asc", + type: "application/pgp-keys", + }, + ], +}; + +// https://github.com/garmeeh/next-seo#social-profile +export const socialProfileJsonLd: SocialProfileJsonLdProps = { + type: "Person", + name: config.authorName, + url: `${config.baseUrl}/`, + sameAs: [ + `${config.baseUrl}/`, + `https://github.com/${config.authorSocial?.github}`, + `https://keybase.io/${config.authorSocial?.keybase}`, + `https://twitter.com/${config.authorSocial?.twitter}`, + `https://medium.com/@${config.authorSocial?.medium}`, + `https://www.linkedin.com/in/${config.authorSocial?.linkedin}/`, + `https://www.facebook.com/${config.authorSocial?.facebook}`, + `https://www.instagram.com/${config.authorSocial?.instagram}/`, + ], +}; + +// https://github.com/garmeeh/next-seo#article-1 +export const articleJsonLd: Pick = { + authorName: [config.authorName], + publisherName: config.siteName, + publisherLogo: `${config.baseUrl}${meJpg.src}`, +}; diff --git a/package.json b/package.json index 9dc27f3e..476213d7 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "date-fns": "^2.28.0", "escape-goat": "^4.0.0", "fathom-client": "^3.4.0", - "faunadb": "^4.4.2", + "faunadb": "^4.5.0", "feather-icons": "^4.28.0", "feed": "^4.2.2", "formik": "^2.2.9", @@ -49,7 +49,7 @@ "next": "12.0.10", "next-compose-plugins": "^2.2.1", "next-mdx-remote": "4.0.0-rc.1", - "next-seo": "^5.0.0", + "next-seo": "^5.1.0", "next-themes": "^0.0.15", "next-transpile-modules": "^9.0.0", "node-fetch": "^3.2.0", diff --git a/pages/_app.tsx b/pages/_app.tsx index 7f25f1c1..b55e794e 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -5,13 +5,9 @@ import { DefaultSeo, SocialProfileJsonLd } from "next-seo"; import * as Fathom from "fathom-client"; import Layout from "../components/Layout/Layout"; import * as config from "../lib/config"; +import { defaultSeo, socialProfileJsonLd } from "../lib/seo"; import type { AppProps } from "next/app"; -import faviconIco from "../public/static/favicons/favicon.ico"; -import faviconPng from "../public/static/favicons/favicon.png"; -import appleTouchIconPng from "../public/static/favicons/apple-touch-icon.png"; -import meJpg from "../public/static/images/me.jpg"; - // global webfonts -- imported here so they're processed through PostCSS import "@fontsource/inter/latin-400.css"; import "@fontsource/inter/latin-500.css"; @@ -60,120 +56,18 @@ const App = ({ Component, pageProps }: AppProps) => { return ( <> - {/* @ts-ignore */} - + diff --git a/pages/notes/[slug].tsx b/pages/notes/[slug].tsx index 21c14b6e..f841d88e 100644 --- a/pages/notes/[slug].tsx +++ b/pages/notes/[slug].tsx @@ -9,6 +9,7 @@ import Comments from "../../components/Comments/Comments"; import * as mdxComponents from "../../lib/mdx-components"; import { getNote, getNoteSlugs } from "../../lib/parse-notes"; import * as config from "../../lib/config"; +import { articleJsonLd } from "../../lib/seo"; import type { GetStaticProps, GetStaticPaths } from "next"; import type { NoteType } from "../../types"; @@ -47,9 +48,7 @@ const Note = ({ frontMatter, source }: NoteType) => { datePublished={frontMatter.date} dateModified={frontMatter.date} images={frontMatter.image && [`${config.baseUrl}${frontMatter.image}`]} - authorName={[config.authorName]} - publisherName={config.siteName} - publisherLogo={`${config.baseUrl}/static/images/me.jpg`} + {...articleJsonLd} /> diff --git a/yarn.lock b/yarn.lock index 188bfeb7..306eefc5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2569,9 +2569,9 @@ eastasianwidth@^0.2.0: integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== electron-to-chromium@^1.4.17: - version "1.4.59" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.59.tgz#657f2588c048fb95975779f8fea101fad854de89" - integrity sha512-AOJ3cAE0TWxz4fQ9zkND5hWrQg16nsZKVz9INOot1oV//u4wWu5xrj9CQMmPTYskkZRunSRc9sAnr4EkexXokg== + version "1.4.60" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.60.tgz#2b824d862f068a9794b2b75d66ad40ff44745f18" + integrity sha512-h53hbEiKC6hijelDgxgkgAUC3PKyR7TmIfvjHnBjUGPMg/3sBuTyG6eDormw+lY24uUJvHkUPzB8dpK8b2u3Sw== emoji-regex@^8.0.0: version "8.0.0" @@ -3052,10 +3052,10 @@ fathom-client@^3.4.0: resolved "https://registry.yarnpkg.com/fathom-client/-/fathom-client-3.4.0.tgz#424b6732d035b68fa1139f0317d10fd4106dc75f" integrity sha512-9ZgVLSP5GLXrIOLqY2ipar2Pw2/Dw6YNsqix9SbbrK9XpFA318VYf0GeKUBqZQQM+z7fbyDTWkBjl+UMe+eQwA== -faunadb@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/faunadb/-/faunadb-4.4.2.tgz#f5ea92469aab7854dd45a4953bf42fd36aa71ffe" - integrity sha512-kbyfN18hmFTuJ3EwU9wsnQG1F5xsHpSZHXl7H79fMZ0TX28CVQY5A64g13z2PR+fcR5WiACqcWfkJQLMpQSaAw== +faunadb@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/faunadb/-/faunadb-4.5.0.tgz#e9864272ca5b6bc85c753b1a1a07b067fb123911" + integrity sha512-QNSw4XD53aHdikld1rt3kiiVbgx8DiXeeL5Z1/1TfhoiwgAEfYZ9VyGfXjwmthrlLy3YilU+bRPFyysK8q+kMg== dependencies: abort-controller "^3.0.0" base64-js "^1.2.0" @@ -4823,10 +4823,10 @@ next-mdx-remote@4.0.0-rc.1: vfile "^5.2.0" vfile-matter "^3.0.1" -next-seo@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/next-seo/-/next-seo-5.0.0.tgz#8a5c82279edcbd74c4ce58efa5588528e47c0d72" - integrity sha512-uCa8hoE5VQz4D2NqZAPhqR64hY5LSmaq70wmfGK09U57TMY7XzsDI+MjfZo0MgHJM87bj3Fd/oMQbDcZ/YWhJQ== +next-seo@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/next-seo/-/next-seo-5.1.0.tgz#aa9fd6249a11bf93e6da06fa2a6bc89268936edf" + integrity sha512-ampuQfNTOi1x+xtRIb6CZGunIo6rQXtMo2Tyu861d5GjJFIwfOXsA4lzCa4+e2rLkyXDyVpavNNUZWa3US9ELw== next-themes@^0.0.15: version "0.0.15"