Skip to content

Commit ce91bee

Browse files
author
hashpanda
committed
feat(web): add SEO metadata, OG images and analytics
- Add complete SEO metadata: Open Graph, Twitter Cards, canonical URLs - Add hreflang alternate links for i18n - Add robots.txt and sitemap.xml (110 URLs with i18n) - Add dynamic OG image generation (1200x630) with dark terminal style - Add Google Analytics (gtag) tracking code Made-with: Cursor
1 parent 43bc004 commit ce91bee

4 files changed

Lines changed: 425 additions & 2 deletions

File tree

web/public/robots.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
User-agent: *
2+
Allow: /
3+
4+
Sitemap: https://build.funagent.app/sitemap.xml

web/public/sitemap.xml

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
3+
xmlns:xhtml="http://www.w3.org/1999/xhtml">
4+
<!-- Homepage -->
5+
<url>
6+
<loc>https://build.funagent.app/zh/</loc>
7+
<xhtml:link rel="alternate" hreflang="zh" href="https://build.funagent.app/zh/"/>
8+
<xhtml:link rel="alternate" hreflang="en" href="https://build.funagent.app/en/"/>
9+
<changefreq>weekly</changefreq>
10+
<priority>1.0</priority>
11+
</url>
12+
<url>
13+
<loc>https://build.funagent.app/en/</loc>
14+
<xhtml:link rel="alternate" hreflang="zh" href="https://build.funagent.app/zh/"/>
15+
<xhtml:link rel="alternate" hreflang="en" href="https://build.funagent.app/en/"/>
16+
<changefreq>weekly</changefreq>
17+
<priority>1.0</priority>
18+
</url>
19+
20+
<!-- Timeline -->
21+
<url>
22+
<loc>https://build.funagent.app/zh/timeline/</loc>
23+
<xhtml:link rel="alternate" hreflang="zh" href="https://build.funagent.app/zh/timeline/"/>
24+
<xhtml:link rel="alternate" hreflang="en" href="https://build.funagent.app/en/timeline/"/>
25+
<changefreq>weekly</changefreq>
26+
<priority>0.8</priority>
27+
</url>
28+
<url>
29+
<loc>https://build.funagent.app/en/timeline/</loc>
30+
<xhtml:link rel="alternate" hreflang="zh" href="https://build.funagent.app/zh/timeline/"/>
31+
<xhtml:link rel="alternate" hreflang="en" href="https://build.funagent.app/en/timeline/"/>
32+
<changefreq>weekly</changefreq>
33+
<priority>0.8</priority>
34+
</url>
35+
36+
<!-- Architecture -->
37+
<url>
38+
<loc>https://build.funagent.app/zh/architecture/</loc>
39+
<xhtml:link rel="alternate" hreflang="zh" href="https://build.funagent.app/zh/architecture/"/>
40+
<xhtml:link rel="alternate" hreflang="en" href="https://build.funagent.app/en/architecture/"/>
41+
<changefreq>weekly</changefreq>
42+
<priority>0.8</priority>
43+
</url>
44+
<url>
45+
<loc>https://build.funagent.app/en/architecture/</loc>
46+
<xhtml:link rel="alternate" hreflang="zh" href="https://build.funagent.app/zh/architecture/"/>
47+
<xhtml:link rel="alternate" hreflang="en" href="https://build.funagent.app/en/architecture/"/>
48+
<changefreq>weekly</changefreq>
49+
<priority>0.8</priority>
50+
</url>
51+
52+
<!-- Compare -->
53+
<url>
54+
<loc>https://build.funagent.app/zh/compare/</loc>
55+
<xhtml:link rel="alternate" hreflang="zh" href="https://build.funagent.app/zh/compare/"/>
56+
<xhtml:link rel="alternate" hreflang="en" href="https://build.funagent.app/en/compare/"/>
57+
<changefreq>weekly</changefreq>
58+
<priority>0.7</priority>
59+
</url>
60+
<url>
61+
<loc>https://build.funagent.app/en/compare/</loc>
62+
<xhtml:link rel="alternate" hreflang="zh" href="https://build.funagent.app/zh/compare/"/>
63+
<xhtml:link rel="alternate" hreflang="en" href="https://build.funagent.app/en/compare/"/>
64+
<changefreq>weekly</changefreq>
65+
<priority>0.7</priority>
66+
</url>
67+
68+
<!-- Lessons s00-s48 (zh) -->
69+
<url><loc>https://build.funagent.app/zh/s00/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
70+
<url><loc>https://build.funagent.app/zh/s01/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
71+
<url><loc>https://build.funagent.app/zh/s02/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
72+
<url><loc>https://build.funagent.app/zh/s03/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
73+
<url><loc>https://build.funagent.app/zh/s04/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
74+
<url><loc>https://build.funagent.app/zh/s05/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
75+
<url><loc>https://build.funagent.app/zh/s06/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
76+
<url><loc>https://build.funagent.app/zh/s07/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
77+
<url><loc>https://build.funagent.app/zh/s08/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
78+
<url><loc>https://build.funagent.app/zh/s09/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
79+
<url><loc>https://build.funagent.app/zh/s10/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
80+
<url><loc>https://build.funagent.app/zh/s11/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
81+
<url><loc>https://build.funagent.app/zh/s12/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
82+
<url><loc>https://build.funagent.app/zh/s13/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
83+
<url><loc>https://build.funagent.app/zh/s14/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
84+
<url><loc>https://build.funagent.app/zh/s15/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
85+
<url><loc>https://build.funagent.app/zh/s16/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
86+
<url><loc>https://build.funagent.app/zh/s17/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
87+
<url><loc>https://build.funagent.app/zh/s18/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
88+
<url><loc>https://build.funagent.app/zh/s19/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
89+
<url><loc>https://build.funagent.app/zh/s20/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
90+
<url><loc>https://build.funagent.app/zh/s21/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
91+
<url><loc>https://build.funagent.app/zh/s22/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
92+
<url><loc>https://build.funagent.app/zh/s23/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
93+
<url><loc>https://build.funagent.app/zh/s24/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
94+
<url><loc>https://build.funagent.app/zh/s25/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
95+
<url><loc>https://build.funagent.app/zh/s26/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
96+
<url><loc>https://build.funagent.app/zh/s27/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
97+
<url><loc>https://build.funagent.app/zh/s28/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
98+
<url><loc>https://build.funagent.app/zh/s29/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
99+
<url><loc>https://build.funagent.app/zh/s30/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
100+
<url><loc>https://build.funagent.app/zh/s31/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
101+
<url><loc>https://build.funagent.app/zh/s32/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
102+
<url><loc>https://build.funagent.app/zh/s33/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
103+
<url><loc>https://build.funagent.app/zh/s34/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
104+
<url><loc>https://build.funagent.app/zh/s35/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
105+
<url><loc>https://build.funagent.app/zh/s36/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
106+
<url><loc>https://build.funagent.app/zh/s37/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
107+
<url><loc>https://build.funagent.app/zh/s38/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
108+
<url><loc>https://build.funagent.app/zh/s39/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
109+
<url><loc>https://build.funagent.app/zh/s40/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
110+
<url><loc>https://build.funagent.app/zh/s41/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
111+
<url><loc>https://build.funagent.app/zh/s42/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
112+
<url><loc>https://build.funagent.app/zh/s43/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
113+
<url><loc>https://build.funagent.app/zh/s44/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
114+
<url><loc>https://build.funagent.app/zh/s45/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
115+
<url><loc>https://build.funagent.app/zh/s46/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
116+
<url><loc>https://build.funagent.app/zh/s47/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
117+
<url><loc>https://build.funagent.app/zh/s48/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
118+
119+
<!-- Lessons s00-s48 (en) -->
120+
<url><loc>https://build.funagent.app/en/s00/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
121+
<url><loc>https://build.funagent.app/en/s01/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
122+
<url><loc>https://build.funagent.app/en/s02/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
123+
<url><loc>https://build.funagent.app/en/s03/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
124+
<url><loc>https://build.funagent.app/en/s04/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
125+
<url><loc>https://build.funagent.app/en/s05/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
126+
<url><loc>https://build.funagent.app/en/s06/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
127+
<url><loc>https://build.funagent.app/en/s07/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
128+
<url><loc>https://build.funagent.app/en/s08/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
129+
<url><loc>https://build.funagent.app/en/s09/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
130+
<url><loc>https://build.funagent.app/en/s10/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
131+
<url><loc>https://build.funagent.app/en/s11/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
132+
<url><loc>https://build.funagent.app/en/s12/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
133+
<url><loc>https://build.funagent.app/en/s13/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
134+
<url><loc>https://build.funagent.app/en/s14/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
135+
<url><loc>https://build.funagent.app/en/s15/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
136+
<url><loc>https://build.funagent.app/en/s16/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
137+
<url><loc>https://build.funagent.app/en/s17/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
138+
<url><loc>https://build.funagent.app/en/s18/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
139+
<url><loc>https://build.funagent.app/en/s19/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
140+
<url><loc>https://build.funagent.app/en/s20/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
141+
<url><loc>https://build.funagent.app/en/s21/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
142+
<url><loc>https://build.funagent.app/en/s22/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
143+
<url><loc>https://build.funagent.app/en/s23/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
144+
<url><loc>https://build.funagent.app/en/s24/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
145+
<url><loc>https://build.funagent.app/en/s25/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
146+
<url><loc>https://build.funagent.app/en/s26/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
147+
<url><loc>https://build.funagent.app/en/s27/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
148+
<url><loc>https://build.funagent.app/en/s28/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
149+
<url><loc>https://build.funagent.app/en/s29/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
150+
<url><loc>https://build.funagent.app/en/s30/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
151+
<url><loc>https://build.funagent.app/en/s31/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
152+
<url><loc>https://build.funagent.app/en/s32/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
153+
<url><loc>https://build.funagent.app/en/s33/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
154+
<url><loc>https://build.funagent.app/en/s34/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
155+
<url><loc>https://build.funagent.app/en/s35/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
156+
<url><loc>https://build.funagent.app/en/s36/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
157+
<url><loc>https://build.funagent.app/en/s37/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
158+
<url><loc>https://build.funagent.app/en/s38/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
159+
<url><loc>https://build.funagent.app/en/s39/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
160+
<url><loc>https://build.funagent.app/en/s40/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
161+
<url><loc>https://build.funagent.app/en/s41/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
162+
<url><loc>https://build.funagent.app/en/s42/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
163+
<url><loc>https://build.funagent.app/en/s43/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
164+
<url><loc>https://build.funagent.app/en/s44/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
165+
<url><loc>https://build.funagent.app/en/s45/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
166+
<url><loc>https://build.funagent.app/en/s46/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
167+
<url><loc>https://build.funagent.app/en/s47/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
168+
<url><loc>https://build.funagent.app/en/s48/</loc><changefreq>monthly</changefreq><priority>0.6</priority></url>
169+
</urlset>

web/src/app/[locale]/layout.tsx

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import zh from "@/i18n/messages/zh.json";
55
import en from "@/i18n/messages/en.json";
66
import "../globals.css";
77

8+
const SITE_URL = "https://build.funagent.app";
89
const locales = ["zh", "en"];
910
const metaMessages: Record<string, typeof zh> = { zh, en };
1011

@@ -19,9 +20,61 @@ export async function generateMetadata({
1920
}): Promise<Metadata> {
2021
const { locale } = await params;
2122
const messages = metaMessages[locale] || metaMessages.zh;
23+
const title = messages.meta?.title || "Build Claude Code";
24+
const description =
25+
messages.meta?.description || "从零构建企业级 AI Agent CLI";
26+
const url = `${SITE_URL}/${locale}/`;
27+
const altLocale = locale === "zh" ? "en" : "zh";
28+
2229
return {
23-
title: messages.meta?.title || "Build Claude Code",
24-
description: messages.meta?.description || "从零构建企业级 AI Agent CLI",
30+
title,
31+
description,
32+
metadataBase: new URL(SITE_URL),
33+
alternates: {
34+
canonical: url,
35+
languages: { [altLocale]: `${SITE_URL}/${altLocale}/` },
36+
},
37+
icons: [
38+
{ rel: "icon", type: "image/png", sizes: "32x32", url: "/favicon.png" },
39+
{ rel: "icon", type: "image/svg+xml", url: "/favicon.svg" },
40+
],
41+
openGraph: {
42+
type: "website",
43+
title,
44+
description,
45+
url,
46+
siteName: "Build Claude Code",
47+
locale: locale === "zh" ? "zh_CN" : "en_US",
48+
},
49+
twitter: {
50+
card: "summary_large_image",
51+
title,
52+
description,
53+
},
54+
robots: {
55+
index: true,
56+
follow: true,
57+
},
58+
keywords:
59+
locale === "zh"
60+
? [
61+
"Claude Code",
62+
"AI Agent",
63+
"CLI",
64+
"TypeScript",
65+
"Anthropic",
66+
"AI 编程",
67+
"Agent 开发教程",
68+
]
69+
: [
70+
"Claude Code",
71+
"AI Agent",
72+
"CLI",
73+
"TypeScript",
74+
"Anthropic",
75+
"AI coding",
76+
"Agent tutorial",
77+
],
2578
};
2679
}
2780

@@ -37,6 +90,10 @@ export default async function RootLayout({
3790
return (
3891
<html lang={locale} suppressHydrationWarning className="font-sans">
3992
<head>
93+
<script async src="https://www.googletagmanager.com/gtag/js?id=G-D20Z4J6G62" />
94+
<script dangerouslySetInnerHTML={{ __html: `
95+
window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}gtag('js',new Date());gtag('config','G-D20Z4J6G62');
96+
`}} />
4097
<script dangerouslySetInnerHTML={{ __html: `
4198
(function() {
4299
var theme = localStorage.getItem('theme');

0 commit comments

Comments
 (0)