Skip to content

Commit f09e050

Browse files
authored
[add] Enhance PageHead component with Open Graph and Twitter meta tags; [add] robots.txt and sitemap.xml for SEO optimization (#75)
1 parent b27f03c commit f09e050

File tree

5 files changed

+88
-16
lines changed

5 files changed

+88
-16
lines changed

components/PageHead.tsx

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,47 @@
11
import Head from 'next/head';
22
import type { FC, PropsWithChildren } from 'react';
33

4-
import { Name, Summary } from '../models/configuration';
4+
import { Name, SiteUrl, Summary } from '../models/configuration';
55

6-
export type PageHeadProps = PropsWithChildren<{
7-
title?: string;
8-
description?: string;
9-
}>;
6+
export type PageHeadProps = PropsWithChildren<
7+
Partial<Record<'title' | 'description' | 'ogImage' | 'type' | 'url', string>>
8+
>;
109

11-
export const PageHead: FC<PageHeadProps> = ({ title, description = Summary, children }) => (
12-
<Head>
13-
<title>{(title ? `${title} - ` : '') + Name}</title>
10+
export const PageHead: FC<PageHeadProps> = ({
11+
title,
12+
description = Summary,
13+
ogImage = 'https://github.com/idea2app.png',
14+
type = 'website',
15+
url = SiteUrl,
16+
children,
17+
}) => {
18+
const fullTitle = (title ? `${title} - ` : '') + Name;
19+
const fullUrl = url.startsWith('/') ? `${SiteUrl}${url}` : url;
1420

15-
{description && <meta name="description" content={description} />}
21+
return (
22+
<Head>
23+
{/* 基础 meta 标签 */}
24+
<title>{fullTitle}</title>
25+
<meta name="description" content={description} />
1626

17-
{children}
18-
</Head>
19-
);
27+
{/* Open Graph */}
28+
<meta property="og:title" content={fullTitle} />
29+
<meta property="og:description" content={description} />
30+
<meta property="og:type" content={type} />
31+
<meta property="og:image" content={ogImage} />
32+
<meta property="og:url" content={fullUrl} />
33+
<meta property="og:site_name" content={Name} />
34+
35+
{/* Twitter */}
36+
<meta name="twitter:card" content="summary_large_image" />
37+
<meta name="twitter:title" content={fullTitle} />
38+
<meta name="twitter:description" content={description} />
39+
<meta name="twitter:image" content={ogImage} />
40+
41+
{/* 规范链接 */}
42+
<link rel="canonical" href={fullUrl} />
43+
44+
{children}
45+
</Head>
46+
);
47+
};

models/configuration.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export const Name = process.env.NEXT_PUBLIC_SITE_NAME,
22
Summary = process.env.NEXT_PUBLIC_SITE_SUMMARY,
3-
DefaultImage = process.env.NEXT_PUBLIC_LOGO || '/og.png';
3+
DefaultImage = process.env.NEXT_PUBLIC_LOGO || '/idea2app.svg',
4+
SiteUrl = `https://${process.env.VERCEL_URL || 'idea2.app'}`;
45

56
export const isServer = () => typeof window === 'undefined';
67

pages/_document.tsx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import InitColorSchemeScript from '@mui/material/InitColorSchemeScript';
22
import Document, { DocumentContext, Head, Html, Main, NextScript } from 'next/document';
33
import Script from 'next/script';
44

5-
import { DefaultImage } from '../models/configuration';
5+
import { DefaultImage, Name, SiteUrl } from '../models/configuration';
66
import { LanguageCode, parseSSRContext } from '../models/Translation';
77

88
/**
@@ -12,8 +12,18 @@ import { LanguageCode, parseSSRContext } from '../models/Translation';
1212
const siteNameJsonLd = {
1313
'@context': 'https://schema.org',
1414
'@type': 'WebSite',
15-
name: 'Ameliorate',
16-
url: 'https://idea2.app/',
15+
name: Name,
16+
url: SiteUrl,
17+
};
18+
19+
const organizationJsonLd = {
20+
'@context': 'https://schema.org',
21+
'@type': 'Organization',
22+
name: Name,
23+
url: SiteUrl,
24+
logo: DefaultImage,
25+
sameAs: ['https://github.com/idea2app'],
26+
1727
};
1828

1929
interface CustomDocumentProps {
@@ -59,6 +69,7 @@ export default class CustomDocument extends Document<CustomDocumentProps> {
5969
href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,0,0&display=swap"
6070
/>
6171
<script type="application/ld+json">{JSON.stringify(siteNameJsonLd)}</script>
72+
<script type="application/ld+json">{JSON.stringify(organizationJsonLd)}</script>
6273
</Head>
6374

6475
<body>

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://idea2.app/sitemap.xml

public/sitemap.xml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
3+
<url>
4+
<loc>https://idea2.app/</loc>
5+
<changefreq>daily</changefreq>
6+
<priority>1.0</priority>
7+
</url>
8+
<url>
9+
<loc>https://idea2.app/project</loc>
10+
<changefreq>weekly</changefreq>
11+
<priority>0.8</priority>
12+
</url>
13+
<url>
14+
<loc>https://idea2.app/requirement</loc>
15+
<changefreq>weekly</changefreq>
16+
<priority>0.8</priority>
17+
</url>
18+
<url>
19+
<loc>https://idea2.app/member</loc>
20+
<changefreq>weekly</changefreq>
21+
<priority>0.7</priority>
22+
</url>
23+
<url>
24+
<loc>https://idea2.app/open-source</loc>
25+
<changefreq>weekly</changefreq>
26+
<priority>0.7</priority>
27+
</url>
28+
</urlset>

0 commit comments

Comments
 (0)