/ src / components / SEO.astro
SEO.astro
 1  ---
 2  import data from "~/data/sites";
 3  
 4  export type Props = {
 5  	title: string;
 6  	isPost?: boolean;
 7  	description?: string;
 8  	keywords?: string[];
 9  	thumbnail?: string;
10  	publishedAt?: string;
11  };
12  
13  const defaultThumbnail =
14  	"https://avatars3.githubusercontent.com/u/51877647?s=240&v=4";
15  
16  function getThumbnailUrl(thumbnail: string | undefined): string {
17  	if (!thumbnail) return defaultThumbnail;
18  	return thumbnail.toString();
19  }
20  
21  function getTwitterCardType(thumbnail: string | undefined): string {
22  	return thumbnail ? "summary_large_image" : "summary";
23  }
24  
25  const {
26  	isPost = false,
27  	thumbnail,
28  	description = data.description,
29  	keywords = data.keywords,
30  	publishedAt,
31  	...props
32  } = Astro.props as Props;
33  const { siteName, siteUrl, author, twitter } = data;
34  const currentUrl = `${siteUrl}${Astro.url.pathname}`;
35  const thumbnailUrl = getThumbnailUrl(thumbnail);
36  const twitterCard = getTwitterCardType(thumbnail);
37  ---
38  
39  <title>{props.title} | {siteName}</title>
40  <meta charset="UTF-8">
41  <meta name="viewport" content="width=device-width,initial-scale=1.0" />
42  <meta name="theme-color" content="#fff1f2" />
43  <link rel="canonical" href={currentUrl} />
44  <meta name="author" content={author} />
45  <meta name="description" content={description} />
46  <meta name="keywords" content={keywords.join(",").toLowerCase()} />
47  
48  <!-- favicon -->
49  <link rel="icon" type="image/png" href="/favicon.png" />
50  
51  <!-- Open Graph / Facebook -->
52  <meta property="og:type" content={isPost ? "article" : "website"} />
53  <meta property="og:url" content={currentUrl} />
54  <meta property="og:title" content={props.title || siteName} />
55  <meta property="og:description" content={description} />
56  <meta property="og:image" content={thumbnailUrl} />
57  <meta property="og:site_name" content={siteName} />
58  <meta property="og:locale" content="en_GB" />
59  
60  {isPost && (
61  	<>
62  		<meta property="article:author" content={author} />
63  		<meta property="article:published_time" content={publishedAt} />
64  		<meta property="article:tag" content={keywords.join(",")} />
65  	</>
66  )}
67  
68  <!-- Twitter -->
69  <meta property="twitter:site" content={"@" + twitter.split("/").pop()} />
70  <meta property="twitter:creator" content={"@" + twitter.split("/").pop()} />
71  <meta property="twitter:card" content={twitterCard} />
72  <meta property="twitter:url" content={currentUrl} />
73  <meta property="twitter:title" content={props.title || siteName} />
74  <meta property="twitter:description" content={description} />
75  <meta property="twitter:image" content={thumbnailUrl} />
76  <meta property="twitter:image:alt" content={props.title || siteName} />