Add og meta tags to pages
All checks were successful
Build And Publish / BuildAndPublish (push) Successful in 2m45s

This commit is contained in:
Ryan Freeman 2024-10-11 22:01:19 +01:00
parent 18161a50e8
commit de968c4ed9
12 changed files with 119 additions and 89 deletions

View File

@ -7,10 +7,19 @@ import {GitHubIcon, LinkedInIcon} from '@/components/icons/SocialIcons'
import clsx from 'clsx' import clsx from 'clsx'
import me from '@/public/images/me.jpg' import me from '@/public/images/me.jpg'
import awsCCPBadge from '@/public/images/aws-certified-cloud-practitioner-badge.png' import awsCCPBadge from '@/public/images/aws-certified-cloud-practitioner-badge.png'
import {generateMetadata as _generateMetadata} from '@/lib/generateMetadata'
export const metadata = { const meta = {
title: 'About - Ryan Freeman', title: 'About',
description: 'Im Ryan. I live in Dublin, Ireland where I work as a software engineer.' heading: 'I\'m Ryan. I live in Dublin, Ireland where I work as a software engineer.',
description: 'I\'ve always had an affinity for technology, and loved making things for as long as I can remember. ' +
'My first computer was an Amstrad CPC 464 way back in the 90s, which is ancient by modern standards. ' +
'My passion for tinkering continued through my teens and into adulthood where I eventually found my way into software engineering.',
type: 'website'
}
export async function generateMetadata() {
return _generateMetadata(meta)
} }
function SocialLink({ function SocialLink({
@ -55,14 +64,11 @@ export default async function About() {
</div> </div>
<div className="lg:order-first lg:row-span-2"> <div className="lg:order-first lg:row-span-2">
<h1 className="text-4xl font-bold tracking-tight text-zinc-800 sm:text-5xl bg-clip-text dark:text-transparent bg-gradient-to-r from-blue-400 to-emerald-400"> <h1 className="text-4xl font-bold tracking-tight text-zinc-800 sm:text-5xl bg-clip-text dark:text-transparent bg-gradient-to-r from-blue-400 to-emerald-400">
Im Ryan. I live in Dublin, Ireland where I work as a software engineer. {meta.heading}
</h1> </h1>
<div className="mt-6 space-y-7 text-base text-zinc-600 dark:text-zinc-400"> <div className="mt-6 space-y-7 text-base text-zinc-600 dark:text-zinc-400">
<p> <p>
I&apos;ve always had an affinity for technology, and loved making things for as long as I can {meta.description}
remember. My first computer was an Amstrad CPC 464 way back in the 90s, which is ancient by modern
standards. My passion for tinkering continued through my teens and into adulthood where I
eventually found my way into software engineering.
</p> </p>
<p> <p>
In terms of my experience to date, I have a strong foundation in both front-end and back-end In terms of my experience to date, I have a strong foundation in both front-end and back-end

View File

@ -29,11 +29,11 @@ export async function GET(request: Request) {
width: '100%', width: '100%',
height: '100%', height: '100%',
display: 'flex', display: 'flex',
textAlign: 'center', textAlign: 'left',
alignItems: 'center', alignItems: 'center',
justifyContent: 'center', justifyContent: 'center',
lineHeight: '1', lineHeight: '1.1',
padding: '0 128px' padding: '0 64px'
}} }}
> >
<div <div

View File

@ -6,7 +6,10 @@ import {Footer} from '@/components/common/Footer'
import '@/styles/tailwind.css' import '@/styles/tailwind.css'
export const metadata = { export const metadata = {
title: 'Ryan Freeman - Full-stack software engineer from Dublin, Ireland.', title: {
default: 'Ryan Freeman - Full-stack software engineer based in Dublin, Ireland.',
template: '%s - Ryan Freeman'
},
description: 'Full-stack software engineer who enjoys building cloud-native applications.', description: 'Full-stack software engineer who enjoys building cloud-native applications.',
metadataBase: new URL('https://ryanfreeman.dev'), metadataBase: new URL('https://ryanfreeman.dev'),
alternates: { alternates: {

View File

@ -8,6 +8,20 @@ import {GitHubIcon, LinkedInIcon} from '@/components/icons/SocialIcons'
import {getAllArticles} from '@/lib/getAllArticles' import {getAllArticles} from '@/lib/getAllArticles'
import {formatDate} from '@/lib/formatDate' import {formatDate} from '@/lib/formatDate'
import type {Article} from '@/types' import type {Article} from '@/types'
import {generateMetadata as _generateMetadata} from '@/lib/generateMetadata'
const meta = {
title: 'Ryan Freeman - Full-stack software engineer based in Dublin, Ireland.',
heading: 'Full-stack software engineer who enjoys building cloud-native applications.',
description: 'Hi. I\'m Ryan, a software engineer based in Dublin, Ireland. I\'m currently working in the aviation industry for Aer Lingus. ' +
'I am passionate about personal growth and progressing in my career. ' +
'This is my personal website where you can learn more about me, read articles I\'ve written and see projects I\'ve worked on.',
type: 'website'
}
export async function generateMetadata() {
return _generateMetadata(meta)
}
function Article(article: Article) { function Article(article: Article) {
return ( return (
@ -41,13 +55,10 @@ export default async function Home() {
<Container className="mt-9"> <Container className="mt-9">
<div className="max-w-2xl"> <div className="max-w-2xl">
<h1 className="text-4xl font-bold tracking-tight text-zinc-800 sm:text-5xl bg-clip-text dark:text-transparent bg-gradient-to-r from-pink-500 via-red-500 to-yellow-500"> <h1 className="text-4xl font-bold tracking-tight text-zinc-800 sm:text-5xl bg-clip-text dark:text-transparent bg-gradient-to-r from-pink-500 via-red-500 to-yellow-500">
Full-stack software engineer who enjoys building cloud-native applications. {meta.heading}
</h1> </h1>
<p className="mt-6 text-base text-zinc-600 dark:text-zinc-400"> <p className="mt-6 text-base text-zinc-600 dark:text-zinc-400">
Hi. I&apos;m Ryan, a software engineer based in Dublin, Ireland. I&apos;m currently working in the {meta.description}
aviation industry for Aer Lingus. I am passionate about personal growth and progressing in my career. This
is my personal website where you can learn more about me, read articles I&apos;ve written and see projects
I&apos;ve worked on.
</p> </p>
<div className="mt-6 flex gap-6"> <div className="mt-6 flex gap-6">
<SocialLink <SocialLink

View File

@ -4,11 +4,18 @@ import {SimpleLayout} from '@/components/layouts/SimpleLayout'
import {Card} from '@/components/ui/Card' import {Card} from '@/components/ui/Card'
import {getPinnedRepos} from '@/lib/github' import {getPinnedRepos} from '@/lib/github'
import {numberFormat} from '@/lib/numberFormat' import {numberFormat} from '@/lib/numberFormat'
import React from 'react'; import {generateMetadata as _generateMetadata} from '@/lib/generateMetadata'
import React from 'react'
export const metadata = { const meta = {
title: 'Projects - Ryan Freeman', title: 'Projects',
description: 'Here\'s a selection of academic and personal projects that I have worked on. Many of them are open-source, so if you see something that piques your interest, check out the code and contribute if you have ideas for how it can be improved.' heading: 'Things I\'ve made and projects I\'ve worked on.',
description: 'Here\'s a selection of academic and personal projects that I have worked on. Many of them are open-source, so if you see something that piques your interest, check out the code and contribute if you have ideas for how it can be improved.',
type: 'website'
}
export async function generateMetadata() {
return _generateMetadata(meta)
} }
export const revalidate = 0 export const revalidate = 0
@ -18,8 +25,8 @@ export default async function Projects() {
return ( return (
<SimpleLayout <SimpleLayout
heading="Things I've made and projects I've worked on." heading={meta.heading}
description={metadata.description} description={meta.description}
gradient="bg-gradient-to-r from-sky-400 to-blue-500"> gradient="bg-gradient-to-r from-sky-400 to-blue-500">
<ul <ul
role="list" role="list"

View File

@ -1,10 +1,17 @@
import {SimpleLayout} from '@/components/layouts/SimpleLayout' import {SimpleLayout} from '@/components/layouts/SimpleLayout'
import {Card} from '@/components/ui/Card' import {Card} from '@/components/ui/Card'
import React from 'react'; import React from 'react'
import {generateMetadata as _generateMetadata} from '@/lib/generateMetadata'
export const metadata = { const meta = {
title: 'Reading - Ryan Freeman', title: 'Reading',
description: 'Take a look at my curated reading list.' heading: 'Books I\'m reading at the moment',
description: 'Take a look at my curated reading list.',
type: 'website'
}
export async function generateMetadata() {
return _generateMetadata(meta)
} }
type Book = { type Book = {
@ -69,8 +76,8 @@ export default async function Reading() {
return ( return (
<SimpleLayout <SimpleLayout
heading="Books I'm reading at the moment" heading={meta.heading}
description={metadata.description} description={meta.description}
gradient="bg-gradient-to-r from-sky-400 to-blue-500"> gradient="bg-gradient-to-r from-sky-400 to-blue-500">
<ul <ul
role="list" role="list"

View File

@ -9,30 +9,18 @@ import {ShieldIcon} from '@/components/icons/ShieldIcon'
import {EmailIcon} from '@/components/icons/EmailIcon' import {EmailIcon} from '@/components/icons/EmailIcon'
import {RocketIcon} from '@/components/icons/RocketIcon' import {RocketIcon} from '@/components/icons/RocketIcon'
import {ShoppingBagIcon} from '@/components/icons/ShoppingBagIcon' import {ShoppingBagIcon} from '@/components/icons/ShoppingBagIcon'
import {generateMetadata as _generateMetadata} from '@/lib/generateMetadata'
const meta = { const meta = {
title: 'Services - Ryan Freeman', title: 'Services',
heading: 'I offer a wide range of digital services to elevate and transform your business', heading: 'I offer a wide range of digital services to elevate and transform your business',
description: 'Whether you need a WordPress website, React app, AWS support or odd coding jobs, I\'m here to help. ' + description: 'Whether you need a WordPress website, React app, AWS support or odd coding jobs, I\'m here to help. ' +
'As an experienced software engineer, I produce high-quality software that will deliver immediate value for you and your customers.', 'As an experienced software engineer, I produce high-quality software that will deliver immediate value for you and your customers.',
type: 'website'
} }
export const metadata = { export async function generateMetadata() {
...meta, return _generateMetadata(meta)
openGraph: {
title: meta.title,
description: meta.description,
images: [
{
url: `/api/og-image?text=${meta.heading}`,
width: 1200,
height: 600,
alt: meta.heading,
type: 'image/png'
}
],
type: 'website'
}
} }
type Services = { type Services = {
@ -99,8 +87,8 @@ export default function Services() {
return ( return (
<SimpleLayout <SimpleLayout
heading={metadata.heading} heading={meta.heading}
description={metadata.description} description={meta.description}
gradient="bg-gradient-to-r from-pink-300 via-purple-300 to-indigo-400"> gradient="bg-gradient-to-r from-pink-300 via-purple-300 to-indigo-400">
<ul <ul
role="list" role="list"

View File

@ -2,10 +2,17 @@ import React, {ReactNode} from 'react'
import {SimpleLayout} from '@/components/layouts/SimpleLayout' import {SimpleLayout} from '@/components/layouts/SimpleLayout'
import {Card} from '@/components/ui/Card' import {Card} from '@/components/ui/Card'
import {Section} from '@/components/ui/Section' import {Section} from '@/components/ui/Section'
import {generateMetadata as _generateMetadata} from '@/lib/generateMetadata'
export const metadata = { const meta = {
title: 'Uses - Ryan Freeman', title: 'Uses',
description: 'Software I use, equipment that makes my job easier, and other things I recommend.' heading: 'Software I use, equipment that makes my job easier, and other things I recommend.',
description: 'I get asked a lot about the things I use to build software and stay productive. Heres a big list of all of my favourite gear.',
type: 'website'
}
export async function generateMetadata() {
return _generateMetadata(meta)
} }
function ToolsSection({children, title}: { children: ReactNode, title: string }) { function ToolsSection({children, title}: { children: ReactNode, title: string }) {
@ -32,8 +39,8 @@ function Tool({title, href, children}: { title: string, href: string, children:
export default function Uses() { export default function Uses() {
return ( return (
<SimpleLayout <SimpleLayout
heading="Software I use, equipment that makes my job easier, and other things I recommend." heading={meta.heading}
description="I get asked a lot about the things I use to build software and stay productive. Heres a big list of all of my favourite gear." description={meta.description}
gradient="bg-gradient-to-r from-orange-400 to-rose-400"> gradient="bg-gradient-to-r from-orange-400 to-rose-400">
<div className="space-y-20"> <div className="space-y-20">
<ToolsSection title="Workstation"> <ToolsSection title="Workstation">

View File

@ -24,7 +24,7 @@ export const metadata = {
type: 'image/png' type: 'image/png'
} }
], ],
type: 'website' type: 'article'
} }
} }

View File

@ -4,30 +4,18 @@ import {Card} from '@/components/ui/Card'
import {Views} from '@/components/ui/Views' import {Views} from '@/components/ui/Views'
import {formatDate} from '@/lib/formatDate' import {formatDate} from '@/lib/formatDate'
import {getAllArticles} from '@/lib/getAllArticles' import {getAllArticles} from '@/lib/getAllArticles'
import {generateMetadata as _generateMetadata} from '@/lib/generateMetadata'
import type {Article} from '@/types' import type {Article} from '@/types'
const meta = { const meta = {
title: 'Writing - Ryan Freeman', title: 'Writing',
heading: 'Writing on software engineering, and everything in between.', heading: 'Writing on software engineering, and everything in between.',
description: 'All of my long-form thoughts on software engineering, and more, displayed in chronological order.' description: 'All of my long-form thoughts on software engineering, and more, displayed in chronological order.',
type: 'website'
} }
export const metadata = { export async function generateMetadata() {
...meta, return _generateMetadata(meta)
openGraph: {
title: meta.title,
description: meta.description,
images: [
{
url: `/api/og-image?text=${meta.heading}`,
width: 1200,
height: 600,
alt: meta.heading,
type: 'image/png'
}
],
type: 'website'
}
} }
function Article({article}: { article: Article }) { function Article({article}: { article: Article }) {
@ -57,8 +45,8 @@ export default async function Writing() {
return ( return (
<SimpleLayout <SimpleLayout
heading={metadata.heading} heading={meta.heading}
description={metadata.description} description={meta.description}
gradient="bg-gradient-to-r from-pink-500 to-violet-500" gradient="bg-gradient-to-r from-pink-500 to-violet-500"
> >
<div className="mx-auto grid max-w-xl grid-cols-1 gap-y-20 lg:max-w-none"> <div className="mx-auto grid max-w-xl grid-cols-1 gap-y-20 lg:max-w-none">

27
lib/generateMetadata.ts Normal file
View File

@ -0,0 +1,27 @@
type Meta = {
title: string
heading: string
description: string
type: string
[name: string]: string | Object
}
export async function generateMetadata(meta: Meta) {
return {
...meta,
openGraph: {
title: meta.title,
description: meta.description,
images: [
{
url: `/api/og-image?text=${meta.heading}`,
width: 1200,
height: 600,
alt: meta.heading,
type: 'image/png'
}
],
type: meta.type
}
}
}

View File

@ -22,18 +22,4 @@ export type Repo = {
name: string name: string
color: string color: string
} }
} }
export type Metric = {
title: string
value: number | string
group: string
href: string
}
export type MetricGroup = [
{
groupName: string,
groupItems: Metric[]
}
]