11---
22import " ../styles/global.css" ;
3+ import { siteSeo } from " ../data/seo" ;
34import { footerBrand , footerColumns , navItems } from " ../data/site" ;
45import { withBase } from " ../utils/base" ;
56
@@ -9,14 +10,16 @@ interface Props {
910 image? : string ;
1011 type? : " website" | " article" ;
1112 noindex? : boolean ;
13+ structuredData? : Record <string , unknown > | Record <string , unknown >[];
1214}
1315
1416const {
1517 title,
1618 description = " RapidAI 是一个专注 AI 工程化落地的开源组织。" ,
1719 image = " /images/RapidAIv6.png" ,
1820 type = " website" ,
19- noindex = false
21+ noindex = false ,
22+ structuredData
2023} = Astro .props ;
2124const pathname = Astro .url .pathname ;
2225const normalizePath = (value : string ) => {
@@ -29,6 +32,52 @@ const isHome = normalizedPathname === normalizePath(homeHref);
2932const siteUrl = Astro .site ?? new URL (" https://rapidai.org" );
3033const canonical = new URL (pathname , siteUrl ).toString ();
3134const resolvedImage = / ^ (https? :)? \/\/ / .test (image ) ? image : new URL (withBase (image ), siteUrl ).toString ();
35+ const organizationStructuredData = {
36+ " @context" : " https://schema.org" ,
37+ " @type" : " Organization" ,
38+ name: siteSeo .name ,
39+ alternateName: siteSeo .alternateName ,
40+ url: new URL (withBase (" /" ), siteUrl ).toString (),
41+ logo: new URL (withBase (siteSeo .logo ), siteUrl ).toString (),
42+ description: siteSeo .description ,
43+ sameAs: siteSeo .sameAs
44+ };
45+ const websiteStructuredData = {
46+ " @context" : " https://schema.org" ,
47+ " @type" : " WebSite" ,
48+ name: siteSeo .name ,
49+ url: new URL (withBase (" /" ), siteUrl ).toString (),
50+ inLanguage: siteSeo .language ,
51+ description: siteSeo .description ,
52+ publisher: {
53+ " @type" : " Organization" ,
54+ name: siteSeo .name
55+ }
56+ };
57+ const pageStructuredData = {
58+ " @context" : " https://schema.org" ,
59+ " @type" : type === " article" ? " Article" : " WebPage" ,
60+ headline: title ,
61+ name: title ,
62+ description ,
63+ url: canonical ,
64+ image: resolvedImage ,
65+ inLanguage: siteSeo .language ,
66+ publisher: {
67+ " @type" : " Organization" ,
68+ name: siteSeo .name ,
69+ logo: {
70+ " @type" : " ImageObject" ,
71+ url: new URL (withBase (siteSeo .logo ), siteUrl ).toString ()
72+ }
73+ }
74+ };
75+ const structuredDataItems = [
76+ organizationStructuredData ,
77+ websiteStructuredData ,
78+ pageStructuredData ,
79+ ... (Array .isArray (structuredData ) ? structuredData : structuredData ? [structuredData ] : [])
80+ ];
3281---
3382
3483<!doctype html >
@@ -37,13 +86,17 @@ const resolvedImage = /^(https?:)?\/\//.test(image) ? image : new URL(withBase(i
3786 <meta charset =" UTF-8" />
3887 <meta name =" viewport" content =" width=device-width, initial-scale=1.0" />
3988 <meta name =" description" content ={ description } />
89+ <meta name =" keywords" content ={ siteSeo .keywords .join (" , " )} />
90+ <meta name =" author" content ={ siteSeo .name } />
4091 <meta name =" generator" content ={ Astro .generator } />
4192 <meta name =" theme-color" content =" #06111f" media =" (prefers-color-scheme: dark)" />
4293 <meta name =" theme-color" content =" #f4f8ff" media =" (prefers-color-scheme: light)" />
4394 <meta name =" color-scheme" content =" dark light" />
4495 <meta name =" robots" content ={ noindex ? " noindex, nofollow" : " index, follow" } />
4596 <link rel =" canonical" href ={ canonical } />
4697 <link rel =" icon" type =" image/png" href ={ withBase (" /images/RapidAIv6.png" )} />
98+ <link rel =" alternate" type =" text/plain" href ={ withBase (" /llms.txt" )} title =" RapidAI AI-readable summary" />
99+ <link rel =" alternate" type =" text/markdown" href ={ withBase (" /llms-full.txt" )} title =" RapidAI full AI-readable context" />
47100 <meta property =" og:site_name" content =" RapidAI" />
48101 <meta property =" og:locale" content =" zh_CN" />
49102 <meta property =" og:type" content ={ type } />
@@ -56,6 +109,7 @@ const resolvedImage = /^(https?:)?\/\//.test(image) ? image : new URL(withBase(i
56109 <meta name =" twitter:title" content ={ title } />
57110 <meta name =" twitter:description" content ={ description } />
58111 <meta name =" twitter:image" content ={ resolvedImage } />
112+ <script type =" application/ld+json" set:html ={ JSON .stringify (structuredDataItems )} />
59113 <title >{ title } </title >
60114 <script is:inline >
61115 (() => {
0 commit comments