labnotes

Adding seo and social to astro

Simple stuff but its important

tags
astro
seo

I've been working on an astro site, and wanted to add some seo stuff to the headers. This is a slightly different way to generate the images from previous post in that it gets generated during the build process on github actions, but its more or less the same.

RSS

1
  npm install @astrojs/rss

Then in astro.config.mjs add a site configuration, for example:

1
site: 'https://thefocus.ai'

And then add src/pages/rss.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import rss from "@astrojs/rss";
import { getPosts } from "../utils/posts";

export async function GET(context) {
  const posts = await getPosts();
  /*
  posts.forEach((post) => {
    console.log("title", post.data.title || post.slug);
    console.log("date", post.data.date);
    console.log(
      "description",
      post.data.description || post.data.title || post.slug
    );
    console.log("link", `/posts/${post.slug}`);
    console.log("---");
  });
  */

  //   console.log(blog);
  return rss({
    title: "The Focus AI",
    description:
      "Keep up to date with the latest news and updates from The Focus AI",
    site: context.site || "https://thefocus.ai",
    items: posts.map((post) => ({
      title: post.data.title || post.slug,
      pubDate: post.data.date,
      description: post.data.description || post.data.title || post.slug,
      // Compute RSS link from post `slug`
      link: `/posts/${post.slug}`,
    })),
  });
}

And then in the <head> add the reference:

1
2
3
4
5
6
  <link
    rel="alternate"
    type="application/rss+xml"
    title="Your Site's Title"
    href={new URL("rss.xml", Astro.site)}
/>

SEO and OG-Images

1
2
3
4
  npm install astro-seo
  npx astro add astro-opengraph-images
  npm i -D react
  npm install @fontsource/dm-sans

Lets first create a renderer for our images. We'll put it in src/components/ogimage.tsx:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
  import React from "react";
  import type { RenderFunctionInput } from "astro-opengraph-images";
  export async function ogimage({
    title,
    description,
  }: RenderFunctionInput): Promise<React.ReactNode> {
    return Promise.resolve(
      <div
        style={{
          height: "100%",
          width: "100%",
          display: "flex",
          flexDirection: "column",
          backgroundColor: "#000",
          padding: "55px 70px",
          color: "#fff",
          fontFamily: "DM Sans",
          fontSize: 72,
        }}
      >
        <div
          style={{
            marginTop: 96,
            fontWeight: 700,
            marginBottom: 16,
          }}
        >
          {title}
        </div>
        <div
          style={{
            fontSize: 40,
          }}
        >
          {description ?? ""}
        </div>
      </div>
    );
  }

Now that we have that, lets install astro-seo and astro-opengraph-images into your astro.config.mjs file, and we'll also include a reference to our custom fonts:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  import { defineConfig } from "astro/config";

import tailwind from "@astrojs/tailwind";
import rehypeAstroRelativeMarkdownLinks from "astro-rehype-relative-markdown-links";
import remarkObsidianCallout from "remark-obsidian-callout";
import fs from "fs";
import { ogimage } from "./src/components/ogimage";

import opengraphImages from "astro-opengraph-images";

const opengraphImagesConfig = {
  options: {
    fonts: [
      {
        name: "DM Sans",
        weight: 400,
        style: "normal",
        data: fs.readFileSync(
          "node_modules/@fontsource/dm-sans/files/dm-sans-latin-400-normal.woff"
        ),
      },
    ],
  },
  render: ogimage,
};

// https://astro.build/config
export default defineConfig({
  site: "https://thefocus.ai",
  integrations: [tailwind(), opengraphImages(opengraphImagesConfig)],
  markdown: {
    rehypePlugins: [rehypeAstroRelativeMarkdownLinks],
    remarkPlugins: [remarkObsidianCallout],
  },
});

Inside of our BaseLayout we need to add the seo tag, and make sure that we have a title and a description for all pages. So on the top, something like

1
2
3
4
5
6
7
8
9
  import { SEO } from "astro-seo";
  import { getImagePath } from "astro-opengraph-images";

  const pageTitle = Astro.props.pageTitle || "the focus.ai";
  const bigHeader = Astro.props.bigHeader || false;

  const description = Astro.props.description || "Come a visit us";
  const { url, site } = Astro;
  const openGraphImageUrl = getImagePath({ url, site });

Then inside the layout astro file that has your head tag:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
      <SEO
        title={pageTitle}
        description={description}
        openGraph={{
          basic: {
            title: pageTitle,
            type: "website",
            image: openGraphImageUrl
          },
          optional: {
            description: description,
          }
        }}
        twitter={{
          creator: "@wschenk"
        }}
        extend={{
          // extending the default link tags
          link: [{ rel: "icon", href: "/favicon.ico" }],
          // extending the default meta tags
          meta: [
            {
              name: "twitter:image",
              content: openGraphImageUrl,
            },
            { name: "twitter:title", content: pageTitle },
            { name: "twitter:description", content: description },
          ],
        }}
      />

Previously

howto

Astro and Obsidian

easy editing

tags
obsidian
astro

Next

labnotes

Fixing vite errors when on github pages

save you the google

tags
vite
astro