Skip to content

Commit 8520db2

Browse files
committed
set metadata in a lesson
1 parent a08e974 commit 8520db2

File tree

13 files changed

+91
-40
lines changed

13 files changed

+91
-40
lines changed

docs/tutorialkit.dev/src/content/docs/guides/deployment.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ You can learn more about the build process in the [Astro documentation](https://
3636

3737
## Environment variables
3838

39-
The `BASE_URL` environment variable should point to your website's absolute URL.
39+
The [`BASE_URL`](https://docs.astro.build/en/guides/environment-variables/#default-environment-variables) environment variable should point to your website's absolute URL.
4040
This will allow to compute absolute URLs for SEO metadata.
4141

4242
Example:
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
import type { MetaTagsConfig } from '@tutorialkit/types';
3+
import { readFaviconFile } from '../utils/favicon';
4+
import { readLogoFile } from '../utils/logo';
5+
import { readPublicImage } from '../utils/publicImage';
6+
7+
interface Props {
8+
meta?: MetaTagsConfig;
9+
}
10+
const { meta = {} } = Astro.props;
11+
let imageUrl;
12+
if (meta.image) {
13+
imageUrl = readPublicImage(meta.image);
14+
if (!imageUrl) {
15+
console.warn(`Image ${meta.image} not found in "/public" folder`);
16+
}
17+
}
18+
imageUrl ??= readLogoFile();
19+
const faviconUrl = readFaviconFile();
20+
---
21+
22+
<meta charset="UTF-8" />
23+
<meta name="viewport" content="width=device-width" />
24+
<meta name="generator" content={Astro.generator} />
25+
{meta.description ? <meta name="description" content={meta.description} /> : null}
26+
{meta.title ? <title>{meta.title}</title> : null}
27+
{faviconUrl ? <link rel="icon" type="image/svg+xml" href={faviconUrl} /> : null}
28+
{/* open graph */}
29+
{meta.title ? <meta name="og:title" content={meta.title} /> : null}
30+
{meta.description ? <meta name="og:description" content={meta.description} /> : null}
31+
{imageUrl ? <meta name="og:image" content={imageUrl} /> : null}
32+
{/* twitter */}
33+
{meta.title ? <meta name="twitter:title" content={meta.title} /> : null}
34+
{meta.description ? <meta name="twitter:description" content={meta.description} /> : null}
35+
{imageUrl ? <meta name="twitter:image" content={imageUrl} /> : null}

packages/astro/src/default/layouts/Layout.astro

Lines changed: 5 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,18 @@
11
---
22
import { ViewTransitions } from 'astro:transitions';
3-
import { readFaviconFile } from '../utils/favicon';
4-
import { readLogoFile } from '../utils/logo';
3+
import type { MetaTagsConfig } from '@tutorialkit/types';
4+
import MetaTags from '../components/MetaTags.astro';
55
66
interface Props {
7-
title: string;
8-
description?: string;
7+
meta?: MetaTagsConfig;
98
}
10-
11-
const { title, description = 'TutorialKit' } = Astro.props;
12-
const logoUrl = readLogoFile();
13-
const faviconUrl = readFaviconFile();
9+
const { meta } = Astro.props;
1410
---
1511

1612
<!doctype html>
1713
<html lang="en" transition:animate="none" class="h-full overflow-hidden">
1814
<head>
19-
<meta charset="UTF-8" />
20-
<meta name="description" content={description} />
21-
<meta name="viewport" content="width=device-width" />
22-
<meta name="generator" content={Astro.generator} />
23-
<meta name="og:title" content={title} />
24-
<meta name="og:description" content={description} />
25-
{logoUrl ? <meta name="og:image" content={logoUrl} /> : null}
26-
<meta name="twitter:title" content={title} />
27-
<meta name="twitter:description" content={description} />
28-
{logoUrl ? <meta name="twitter:image" content={logoUrl} /> : null}
29-
<title>{title}</title>
30-
{faviconUrl ? <link rel="icon" type="image/svg+xml" href={faviconUrl} /> : null}
15+
<MetaTags meta={meta} />
3116
<link rel="preconnect" href="https://fonts.googleapis.com" />
3217
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
3318
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet" />

packages/astro/src/default/pages/[...slug].astro

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,13 @@ export async function getStaticPaths() {
1515
type Props = InferGetStaticPropsType<typeof getStaticPaths>;
1616
1717
const { lesson, logoLink, navList, title } = Astro.props as Props;
18+
const meta = lesson.data?.meta || {};
19+
// Use lesson default title and a default description for SEO metadata
20+
meta.title ??= title;
21+
meta.description ??= 'A TutorialKit interactive lesson';
1822
---
1923

20-
<Layout title={title} description="A TutorialKit interactive lesson">
24+
<Layout meta={meta}>
2125
<PageLoadingIndicator />
2226
<div id="previews-container"></div>
2327
<main class="max-w-full flex flex-col h-full overflow-hidden" data-swap-root>

packages/astro/src/default/utils/content.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ export async function getTutorial(): Promise<Tutorial> {
245245
'editor',
246246
'focus',
247247
'i18n',
248+
'meta',
248249
'editPageLink',
249250
'openInStackBlitz',
250251
'filesystem',
Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,6 @@
1-
import fs from 'node:fs';
2-
import path from 'node:path';
3-
import { joinPaths } from './url';
1+
import { readPublicImage } from './publicImage';
42

53
export function readFaviconFile(faviconPrefix: string = 'favicon') {
6-
let favicon;
7-
84
const faviconFilename = `${faviconPrefix}.svg`;
9-
const exists = fs.existsSync(path.join('public', faviconFilename));
10-
11-
if (exists) {
12-
favicon = joinPaths(import.meta.env.BASE_URL, faviconFilename);
13-
}
14-
15-
return favicon;
5+
return readPublicImage(faviconFilename);
166
}

packages/astro/src/default/utils/logo.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,14 @@
1-
import fs from 'node:fs';
2-
import path from 'node:path';
31
import { LOGO_EXTENSIONS } from './constants';
4-
import { joinPaths } from './url';
2+
import { readPublicImage } from './publicImage';
53

64
export function readLogoFile(logoPrefix: string = 'logo') {
75
let logo;
86

97
for (const logoExt of LOGO_EXTENSIONS) {
108
const logoFilename = `${logoPrefix}.${logoExt}`;
11-
const exists = fs.existsSync(path.join('public', logoFilename));
9+
logo = readPublicImage(logoFilename);
1210

13-
if (exists) {
14-
logo = joinPaths(import.meta.env.BASE_URL, logoFilename);
11+
if (logo) {
1512
break;
1613
}
1714
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import fs from 'node:fs';
2+
import path from 'node:path';
3+
import { joinPaths } from './url';
4+
5+
export function readPublicImage(filename: string) {
6+
let image;
7+
const exists = fs.existsSync(path.join('public', filename));
8+
9+
if (exists) {
10+
image = joinPaths(import.meta.env.BASE_URL, filename);
11+
}
12+
13+
return image;
14+
}

packages/astro/src/default/utils/routes.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export async function generateStaticRoutes() {
2626
logoLink: tutorial.logoLink,
2727
navList: generateNavigationList(tutorial, import.meta.env.BASE_URL),
2828
title: `${part.data.title} / ${chapter.data.title} / ${lesson.data.title}`,
29+
meta: lesson.data.meta,
2930
lesson: lesson as Lesson<AstroComponentFactory>,
3031
},
3132
} satisfies GetStaticPathsItem);

packages/template/src/content/tutorial/1-basics/1-introduction/1-welcome/content.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ prepareCommands:
1111
- ['node -e setTimeout(()=>{process.exit(1)},5000)', 'This is going to fail']
1212
terminal:
1313
panels: ['terminal', 'output']
14+
meta:
15+
description: "This is lesson 1"
16+
image: "/logo.svg"
1417
---
1518

1619
# Kitchen Sink [Heading 1]

0 commit comments

Comments
 (0)