Added SEO

This commit is contained in:
ClovertaTheTrilobita 2026-03-25 17:26:22 +02:00
parent be54fad794
commit 5da8e71344
16 changed files with 149 additions and 8 deletions

View file

@ -1,6 +1,6 @@
// @ts-check
import { defineConfig } from 'astro/config';
import sitemap from "@astrojs/sitemap";
// https://astro.build/config
import { fileURLToPath } from 'node:url'
@ -16,4 +16,5 @@ export default defineConfig({
redirects: {
"/": "/zh",
},
integrations: [sitemap()],
})

69
package-lock.json generated
View file

@ -9,6 +9,7 @@
"version": "0.0.1",
"dependencies": {
"@astrojs/rss": "^4.0.17",
"@astrojs/sitemap": "^3.7.1",
"astro": "^6.0.8",
"url": "^0.11.4"
},
@ -86,6 +87,17 @@
"zod": "^4.3.6"
}
},
"node_modules/@astrojs/sitemap": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/@astrojs/sitemap/-/sitemap-3.7.1.tgz",
"integrity": "sha512-IzQqdTeskaMX+QDZCzMuJIp8A8C1vgzMBp/NmHNnadepHYNHcxQdGLQZYfkbd2EbRXUfOS+UDIKx8sKg0oWVdw==",
"license": "MIT",
"dependencies": {
"sitemap": "^9.0.0",
"stream-replace-string": "^2.0.0",
"zod": "^4.3.6"
}
},
"node_modules/@astrojs/telemetry": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.3.0.tgz",
@ -1739,7 +1751,6 @@
"version": "25.5.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.0.tgz",
"integrity": "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw==",
"devOptional": true,
"license": "MIT",
"dependencies": {
"undici-types": "~7.18.0"
@ -1752,6 +1763,15 @@
"dev": true,
"license": "MIT"
},
"node_modules/@types/sax": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz",
"integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==",
"license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/through2": {
"version": "2.0.41",
"resolved": "https://registry.npmjs.org/@types/through2/-/through2-2.0.41.tgz",
@ -1916,6 +1936,12 @@
"node": ">= 6"
}
},
"node_modules/arg": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
"integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
"license": "MIT"
},
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
@ -6822,6 +6848,40 @@
"integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
"license": "MIT"
},
"node_modules/sitemap": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/sitemap/-/sitemap-9.0.1.tgz",
"integrity": "sha512-S6hzjGJSG3d6if0YoF5kTyeRJvia6FSTBroE5fQ0bu1QNxyJqhhinfUsXi9fH3MgtXODWvwo2BDyQSnhPQ88uQ==",
"license": "MIT",
"dependencies": {
"@types/node": "^24.9.2",
"@types/sax": "^1.2.1",
"arg": "^5.0.0",
"sax": "^1.4.1"
},
"bin": {
"sitemap": "dist/esm/cli.js"
},
"engines": {
"node": ">=20.19.5",
"npm": ">=10.8.2"
}
},
"node_modules/sitemap/node_modules/@types/node": {
"version": "24.12.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.12.0.tgz",
"integrity": "sha512-GYDxsZi3ChgmckRT9HPU0WEhKLP08ev/Yfcq2AstjrDASOYCSXeyjDsHg4v5t4jOj7cyDX3vmprafKlWIG9MXQ==",
"license": "MIT",
"dependencies": {
"undici-types": "~7.16.0"
}
},
"node_modules/sitemap/node_modules/undici-types": {
"version": "7.16.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
"integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
"license": "MIT"
},
"node_modules/smart-buffer": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
@ -6954,6 +7014,12 @@
"through": "~2.3.4"
}
},
"node_modules/stream-replace-string": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/stream-replace-string/-/stream-replace-string-2.0.0.tgz",
"integrity": "sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==",
"license": "MIT"
},
"node_modules/stream-shift": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz",
@ -7366,7 +7432,6 @@
"version": "7.18.2",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
"devOptional": true,
"license": "MIT"
},
"node_modules/unified": {

View file

@ -14,6 +14,7 @@
},
"dependencies": {
"@astrojs/rss": "^4.0.17",
"@astrojs/sitemap": "^3.7.1",
"astro": "^6.0.8",
"url": "^0.11.4"
},

BIN
public/images/Bridget.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 MiB

4
public/robots.txt Normal file
View file

@ -0,0 +1,4 @@
User-agent: *
Allow: /
Sitemap: https://blog.cloverta.top/sitemap-index.xml

View file

@ -4,7 +4,7 @@ pubDate: 2022-07-01
description: 'This is the first post of my new Astro blog.'
author: 'Astro Learner'
image:
url: 'https://docs.astro.build/assets/rose.webp'
url: 'https://s2.loli.net/2022/05/01/UNzy8c6pTHBSuMO.jpg'
alt: 'The Astro logo on a dark background with a pink glow.'
tags: ["astro", "blogging", "learning in public", "Hello"]
---

View file

@ -4,7 +4,7 @@ pubDate: 2022-07-01
description: 'This is the first post of my new Astro blog.'
author: 'Astro Learner'
image:
url: 'https://docs.astro.build/assets/rose.webp'
url: 'https://files.seeusercontent.com/2026/03/25/0rSi/rikka-manga.jpeg'
alt: 'The Astro logo on a dark background with a pink glow.'
tags: ["astro", "blogging", "learning in public"]
---

36
src/components/SEO.astro Normal file
View file

@ -0,0 +1,36 @@
---
interface Props {
title: string;
description: string;
image?: string;
canonical?: string;
type?: "website" | "article";
}
const {
title,
description,
image = "/images/Bridget.png",
canonical,
type = "website",
} = Astro.props;
const url = new URL(Astro.url.pathname, Astro.site);
const canonicalUrl = canonical ?? url.toString();
const imageUrl = new URL(image, Astro.site).toString();
---
<title>{title}</title>
<meta name="description" content={description} />
<link rel="canonical" href={canonicalUrl} />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
<meta property="og:type" content={type} />
<meta property="og:url" content={canonicalUrl} />
<meta property="og:image" content={imageUrl} />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={title} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content={imageUrl} />

View file

@ -2,8 +2,9 @@
import Footer from "@/components/Footer.astro";
import Header from "@/components/Header.astro";
import { ClientRouter } from "astro:transitions";
import SEO from "@/components/SEO.astro";
const { pageTitle } = Astro.props;
const { pageTitle, description = "我的个人博客", image } = Astro.props;
---
<!doctype html>
@ -11,6 +12,7 @@ const { pageTitle } = Astro.props;
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<SEO title={pageTitle} description={description} image={image} />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="icon" href="/favicon.ico" />
<meta name="generator" content={Astro.generator} />

View file

@ -9,7 +9,11 @@ const { frontmatter, lang, postId } = Astro.props;
const t = getTranslations(lang);
---
<BaseLayout pageTitle={frontmatter.title}>
<BaseLayout
pageTitle={frontmatter.title}
description={frontmatter.description}
image={frontmatter.image?.url}
>
<div class="post-header">
<div class="post-meta">
<h1 class="post-title">{frontmatter.title}</h1>
@ -44,6 +48,34 @@ const t = getTranslations(lang);
<Giscus term={postId} />
</BaseLayout>
<script
type="application/ld+json"
set:html={JSON.stringify({
"@context": "https://schema.org",
"@type": "BlogPosting",
headline: frontmatter.title,
description: frontmatter.description,
image: frontmatter.image
? [
new URL(
frontmatter.image.url ?? frontmatter.image,
Astro.site,
).toString(),
]
: undefined,
datePublished: frontmatter.pubDate,
dateModified: frontmatter.updatedDate ?? frontmatter.pubDate,
author: {
"@type": "Person",
name: "CLoverta",
},
mainEntityOfPage: {
"@type": "WebPage",
"@id": new URL(Astro.url.pathname, Astro.site).toString(),
},
})}
/>
<style>
a {
color: var(--post-link-color);