Skip to content

Commit 45f0669

Browse files
committed
Better metadata in head elements
1 parent 23a12a5 commit 45f0669

2 files changed

Lines changed: 92 additions & 18 deletions

File tree

README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,31 @@ Having produced a build in `_site`, the entire directory is pushed up on a `gh-p
1919
A new blog post should be authored within the `/src/blog` directory. It should have its own subdirectory. The name of the subdirectory will become the URL route, e.g. `/src/blog/42-foo/index.md` will become `rupertmckay.com/blog/42-foo`. I maintain a convention of prefixing the directories with a number in order to keep the directories chronologically ordered in the source code. The markdown file must be named `index.md` or else its name will be appended to the route URL, e.g. `/src/blog/42-foo/foo.md` will become `rupertmckay.com/blog/42-foo/foo`, which we don't want.
2020

2121
If the post requires any other files, such as images, these can be colocated and referenced plainly using relative URLs.
22+
23+
### Front matter for blog posts
24+
25+
Each blog post should include the following front matter:
26+
27+
```yaml
28+
---
29+
title: Your Post Title
30+
description: A brief description for SEO and social sharing
31+
date: 2024-01-01
32+
layout: layouts/post.njk
33+
socialImage: https://example.com/custom-image.png # Optional: custom social media image
34+
---
35+
```
36+
37+
The `socialImage` field is optional. If not provided, a default image will be used for social media sharing (Open Graph and Twitter cards).
38+
39+
## SEO Features
40+
41+
The site includes comprehensive SEO optimizations:
42+
43+
- **Canonical URLs**: Each page has a canonical URL to prevent duplicate content issues
44+
- **Open Graph tags**: Proper OG tags for social media sharing (Facebook, LinkedIn, etc.)
45+
- **Twitter Cards**: Large image cards for Twitter sharing
46+
- **Structured Data**: JSON-LD schema.org markup for articles and website
47+
- **RSS/Atom Feed**: Available at `/feed.xml` with the 10 most recent posts
48+
- **Sitemap**: Auto-generated at `/sitemap.xml` with all blog posts
49+
- **robots.txt**: Search engine crawler instructions at `/static/robots.txt`

src/_includes/layouts/base.njk

Lines changed: 64 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,38 +5,84 @@
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
66
<title>{{ title or metadata.title }}</title>
77
<meta name="description" content="{{ description or metadata.description }}">
8+
<link rel="canonical" href="https://rupertmckay.com{{ page.url }}">
89
<link rel="shortcut icon" type="image/x-icon" href="{{ '/static/favicon.ico' | url }}">
910
<link rel="stylesheet" href="{{ '/static/styles.css' | url }}">
1011
<link rel="stylesheet" href="{{ '/static/prism.css' | url }}">
1112
<link rel="alternate" type="application/atom+xml" title="{{ metadata.title }}" href="/feed.xml">
12-
<meta
13-
property="og:description"
14-
content="{{ description or metadata.description }}"
15-
/>
16-
<meta
17-
property="og:image"
18-
content="https://raw.githubusercontent.com/fildon/train-ride/main/train-ride.png"
19-
/>
13+
14+
<!-- Open Graph / Facebook -->
15+
<meta property="og:type" content="{% if layout == 'layouts/post.njk' %}article{% else %}website{% endif %}" />
16+
<meta property="og:url" content="https://rupertmckay.com{{ page.url }}" />
17+
<meta property="og:site_name" content="{{ metadata.title }}" />
18+
<meta property="og:title" content="{{ title or metadata.title }}" />
19+
<meta property="og:description" content="{{ description or metadata.description }}" />
20+
<meta property="og:image" content="{{ socialImage or 'https://raw.githubusercontent.com/fildon/train-ride/main/train-ride.png' }}" />
2021
<meta property="og:image:type" content="image/png" />
2122
<meta property="og:image:width" content="1280" />
2223
<meta property="og:image:height" content="640" />
24+
{% if layout == 'layouts/post.njk' %}
25+
<meta property="article:published_time" content="{{ date | htmlDateString }}" />
26+
<meta property="article:author" content="{{ metadata.title }}" />
27+
{% endif %}
28+
29+
<!-- Twitter -->
2330
<meta name="twitter:card" content="summary_large_image" />
2431
<meta property="twitter:domain" content="rupertmckay.com" />
25-
<meta property="twitter:url" content="https://rupertmckay.com" />
32+
<meta property="twitter:url" content="https://rupertmckay.com{{ page.url }}" />
2633
<meta name="twitter:title" content="{{ title or metadata.title }}" />
27-
<meta
28-
name="twitter:description"
29-
content="{{ description or metadata.description }}"
30-
/>
31-
<meta
32-
name="twitter:image"
33-
content="https://raw.githubusercontent.com/fildon/train-ride/main/train-ride.png"
34-
/>
34+
<meta name="twitter:description" content="{{ description or metadata.description }}" />
35+
<meta name="twitter:image" content="{{ socialImage or 'https://raw.githubusercontent.com/fildon/train-ride/main/train-ride.png' }}" />
36+
37+
<!-- JSON-LD Structured Data -->
38+
{% if layout == 'layouts/post.njk' %}
39+
<script type="application/ld+json">
40+
{
41+
"@context": "https://schema.org",
42+
"@type": "BlogPosting",
43+
"headline": "{{ title }}",
44+
"description": "{{ description or metadata.description }}",
45+
"author": {
46+
"@type": "Person",
47+
"name": "{{ metadata.title }}",
48+
"url": "https://rupertmckay.com"
49+
},
50+
"datePublished": "{{ date | htmlDateString }}",
51+
"dateModified": "{{ date | htmlDateString }}",
52+
"url": "https://rupertmckay.com{{ page.url }}",
53+
"image": "{{ socialImage or 'https://raw.githubusercontent.com/fildon/train-ride/main/train-ride.png' }}",
54+
"publisher": {
55+
"@type": "Person",
56+
"name": "{{ metadata.title }}",
57+
"url": "https://rupertmckay.com"
58+
},
59+
"mainEntityOfPage": {
60+
"@type": "WebPage",
61+
"@id": "https://rupertmckay.com{{ page.url }}"
62+
}
63+
}
64+
</script>
65+
{% else %}
66+
<script type="application/ld+json">
67+
{
68+
"@context": "https://schema.org",
69+
"@type": "WebSite",
70+
"name": "{{ metadata.title }}",
71+
"description": "{{ metadata.description }}",
72+
"url": "https://rupertmckay.com",
73+
"author": {
74+
"@type": "Person",
75+
"name": "{{ metadata.title }}",
76+
"url": "https://rupertmckay.com"
77+
}
78+
}
79+
</script>
80+
{% endif %}
3581
</head>
3682
<body>
3783
<header class="horizontal-spread">
3884
<img
39-
src="../../static/headshot.jpeg"
85+
src="/static/headshot.jpeg"
4086
alt="Headshot of Rupert"
4187
class="rounded wonky"
4288
height="64"

0 commit comments

Comments
 (0)