Skip to content

Commit 539dfe0

Browse files
committed
feat: enabled support for seo into pages
1 parent 0fb38d0 commit 539dfe0

File tree

12 files changed

+123
-25
lines changed

12 files changed

+123
-25
lines changed

src/assets/images/meta-default.jpg

1010 KB
Loading

src/components/partials/Head.astro

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
---
2+
import { getImage } from 'astro:assets';
3+
import type { Seo } from '@/lib/constants'
4+
import { DEFAULT_CONFIGURATION } from '@/lib/constants';
5+
import { generateAbsoluteUrl } from '@/lib/utils';
6+
7+
interface Props {
8+
seo?: Seo;
9+
}
10+
11+
const defaultSeo = DEFAULT_CONFIGURATION.seo;
12+
const { seo } = Astro.props;
13+
14+
const image = await getImage({ src: seo?.image || defaultSeo.image, format: 'png'});
15+
const seoImage = generateAbsoluteUrl(image.src);
16+
---
17+
<head>
18+
<meta charset="utf-8" />
19+
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
20+
{ seo?.canonicalUrl && <link rel="canonical" href={seo?.canonicalUrl} />}
21+
<title>{seo?.title || defaultSeo.title}</title>
22+
<meta name="viewport" content="width=device-width, initial-scale=1" />
23+
<meta name="generator" content={Astro.generator} />
24+
<meta name="description" content={seo?.description || defaultSeo.description} />
25+
<slot name="keywords">
26+
<meta name="keywords" content={seo?.keywords || defaultSeo.keywords} />
27+
</slot>
28+
<meta name="generator" content={Astro.generator} />
29+
<!-- OpenGraph Meta -->
30+
<meta property="og:type" content={seo?.type ?? 'website'} />
31+
<meta property="og:site_name" content={defaultSeo.title} />
32+
<meta property="og:title" content={seo?.title || defaultSeo.title} />
33+
<meta property="og:description" content={seo?.description || defaultSeo.description} />
34+
<meta property="og:image" content={seoImage} />
35+
<meta property="og:image:width" content="1280" />
36+
<meta property="og:image:height" content="720" />
37+
<!-- Twitter Meta -->
38+
<meta property="twitter:card" content="summary_large_image" />
39+
<meta property="twitter:creator" content={seo?.twitter?.creator || defaultSeo.twitter?.creator} />
40+
<meta property="twitter:site" content={seo?.twitter?.creator || defaultSeo.twitter?.creator} />
41+
<meta property="twitter:title" content={seo?.title || defaultSeo.title} />
42+
<meta property="twitter:description" content={seo?.description || defaultSeo.description} />
43+
<meta property="twitter:image" content={seoImage} />
44+
<script is:inline>
45+
// Prevent FOUC by applying theme before page renders
46+
(function() {
47+
const theme = localStorage.getItem('theme') ||
48+
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
49+
if (theme === 'dark') {
50+
document.documentElement.classList.add('dark');
51+
}
52+
})();
53+
</script>
54+
<slot />
55+
</head>

src/content/pages/homepage/index.mdx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
---
2-
title: About
2+
title: Javier Diaz — Software Engineer
3+
seo:
4+
title: Javier Diaz — Software Engineer
5+
description: Hey I'm Javier, a software engineer passionate about interface design and web experiences
6+
type: website
7+
keywords: keyword, example, demo cv folio
38
---
49

510
Hi, I'm Javier Díaz, also known as coderdiaz. I'm a software engineer passionate about interface design and web experiences. I reside in Mexico City with my wife Becky and my dogs.

src/content/pages/posts/index.mdx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
---
2-
title: Posts
2+
title: My posts — Javier Diaz
3+
seo:
4+
title: My posts — Javier Diaz
5+
description: My personal space, where I share more about my experience.
6+
type: website
7+
keywords: blog, articles, web development blog, software blog,
38
---

src/content/posts/code-example/index.mdx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
title: Example Post with Code
33
date: 2021-01-01
44
image: ./meta.jpg
5+
seo:
6+
title: Example Post with Code
7+
description: Demo example of write posts using block of codes
8+
type: article
9+
keywords: blog code, example shiki
510
---
611

712
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

src/content/posts/example-post/index.mdx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
title: Example Post
33
date: 2021-01-01
44
image: ./meta.jpg
5+
seo:
6+
title: Example Post with Code
7+
description: Demo example for write posts
8+
type: article
9+
keywords: blog code, example shiki
510
---
611

712
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

src/layouts/BaseLayout.astro

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,29 @@
11
---
22
import '@/styles/global.css';
33
import '@/assets/fonts/inter.css';
4+
import type { Seo } from '@/lib/constants';
45
import BannerFloat from '@/components/BannerFloat.astro';
56
import Header from '@/components/partials/Header.astro';
67
import Footer from '@/components/partials/Footer.astro';
8+
import Head from '@/components/partials/Head.astro';
79
import SwitchTheme from '@/components/SwitchTheme.tsx';
10+
11+
interface Props {
12+
seo?: Seo
13+
}
14+
15+
const { seo } = Astro.props;
816
---
917

1018
<html lang="en">
11-
<head>
12-
<meta charset="utf-8" />
13-
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
14-
<meta name="viewport" content="width=device-width" />
15-
<meta name="generator" content={Astro.generator} />
16-
<title>Astro</title>
17-
<script is:inline>
18-
// Prevent FOUC by applying theme before page renders
19-
(function() {
20-
const theme = localStorage.getItem('theme') ||
21-
(window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light');
22-
if (theme === 'dark') {
23-
document.documentElement.classList.add('dark');
24-
}
25-
})();
26-
</script>
27-
</head>
19+
<Head seo={seo} />
2820
<body class="bg-background text-foreground py-8 pb-12">
2921
<Header />
3022
<main>
3123
<slot />
3224
</main>
3325
<Footer />
34-
<SwitchTheme client:load />
26+
<SwitchTheme client:only="react" />
3527
<BannerFloat />
3628
</body>
3729
</html>

src/lib/constants.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
import Avatar from '@/assets/images/avatar.jpeg';
21
import type { GetImageResult } from 'astro';
2+
import type { z } from 'astro/zod';
33
import { getImage } from 'astro:assets';
4+
import MetaDefaultImage from '@/assets/images/meta-default.jpg';
5+
import Avatar from '@/assets/images/avatar.jpeg';
6+
import type { seoSchemaWithoutImage } from '@/content.config';
7+
import astroConfig from 'astro.config.mjs';
48

59
const avatar = await getImage({ src: Avatar, width: 92, height: 92 , format: 'png'});
610

@@ -13,11 +17,18 @@ export type AuthorInfo = {
1317
pronouns?: string;
1418
}
1519

20+
export type Seo = z.infer<typeof seoSchemaWithoutImage> & {
21+
image?: any;
22+
}
23+
1624
type DefaultConfigurationType = {
25+
baseUrl: string,
1726
author: AuthorInfo;
27+
seo: Seo;
1828
}
1929

2030
export const DEFAULT_CONFIGURATION: DefaultConfigurationType = {
31+
baseUrl: astroConfig.site || 'https://getcvfolio.com',
2132
author: {
2233
avatar,
2334
name: 'Javier Diaz Chamorro',
@@ -26,4 +37,13 @@ export const DEFAULT_CONFIGURATION: DefaultConfigurationType = {
2637
location: 'Mexico City',
2738
pronouns: 'He/Him',
2839
},
40+
seo: {
41+
title: 'CV Folio — An Astro template inspired on Read.cv',
42+
description: 'Clean and aesthetic portfolio website for developers and designers',
43+
type: 'website',
44+
image: MetaDefaultImage,
45+
twitter: {
46+
creator: '@cvfolio'
47+
}
48+
}
2949
};

src/lib/utils.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { DEFAULT_CONFIGURATION } from './constants';
2+
13
export const formatDate = (date: Date) => {
24
const formatter = new Intl.DateTimeFormat('en-US', {
35
year: 'numeric',
@@ -8,4 +10,13 @@ export const formatDate = (date: Date) => {
810

911
// Ensure we're parsing the date correctly
1012
return formatter.format(new Date(date));
11-
}
13+
}
14+
15+
export const generateAbsoluteUrl = (path: string) => DEFAULT_CONFIGURATION.baseUrl.concat(path);
16+
17+
export const isDevelopment = () => import.meta.env.MODE === 'development';
18+
19+
export const includeDraft = (draft: boolean) => {
20+
if (isDevelopment()) return true;
21+
return draft !== true;
22+
};

src/pages/index.astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const jobs = await getCollection('jobs');
2020
const talks = await getCollection('talks');
2121
---
2222

23-
<BaseLayout>
23+
<BaseLayout seo={entry.data.seo}>
2424
<section class="py-6">
2525
<Container>
2626
<Author {...DEFAULT_CONFIGURATION.author} />

0 commit comments

Comments
 (0)