Add json-ld schema to frontend/backend roadmaps

faqs/frontend
Kamran Ahmed 2 years ago
parent 9c24ff23e3
commit 4b681c6317
  1. 38
      src/layouts/BaseLayout.astro
  2. 40
      src/lib/jsonld-schema.ts
  3. 29
      src/lib/roadmap.ts
  4. 21
      src/pages/[roadmapId]/index.astro
  5. 6
      src/roadmaps/backend/backend.md
  6. 6
      src/roadmaps/frontend/frontend.md

@ -16,6 +16,7 @@ export interface Props {
noIndex?: boolean;
permalink?: string;
sponsor?: SponsorType;
jsonLd?: Record<string, unknown>;
}
const {
@ -25,14 +26,13 @@ const {
noIndex = false,
permalink = '',
sponsor,
jsonLd,
} = Astro.props;
// Remove trailing slashes to consider the page as canonical
const currentPageAbsoluteUrl = `https://roadmap.sh${permalink}`;
const commitUrl = `https://github.com/kamranahmedse/developer-roadmap/commit/${
import.meta.env.GITHUB_SHA
}`;
const commitUrl = `https://github.com/kamranahmedse/developer-roadmap/commit/${import.meta.env.GITHUB_SHA}`;
---
<!DOCTYPE html>
@ -69,43 +69,23 @@ const commitUrl = `https://github.com/kamranahmedse/developer-roadmap/commit/${
<meta name='mobile-web-app-capable' content='yes' />
<meta name='apple-mobile-web-app-capable' content='yes' />
<meta
name='apple-mobile-web-app-status-bar-style'
content='black-translucent'
/>
<meta name='apple-mobile-web-app-status-bar-style' content='black-translucent' />
<meta name='apple-mobile-web-app-title' content='roadmap.sh' />
<meta name='application-name' content='roadmap.sh' />
<link
rel='apple-touch-icon'
sizes='180x180'
href='/manifest/apple-touch-icon.png'
/>
<link rel='apple-touch-icon' sizes='180x180' href='/manifest/apple-touch-icon.png' />
<meta name='msapplication-TileColor' content='#101010' />
<meta name='theme-color' content='#848a9a' />
<link rel='manifest' href='/manifest/manifest.json' />
<link
rel='icon'
type='image/png'
sizes='32x32'
href='/manifest/icon32.png'
/>
<link
rel='icon'
type='image/png'
sizes='16x16'
href='/manifest/icon16.png'
/>
<link
rel='shortcut icon'
href='/manifest/favicon.ico'
type='image/x-icon'
/>
<link rel='icon' type='image/png' sizes='32x32' href='/manifest/icon32.png' />
<link rel='icon' type='image/png' sizes='16x16' href='/manifest/icon16.png' />
<link rel='shortcut icon' href='/manifest/favicon.ico' type='image/x-icon' />
<link rel='icon' href='/manifest/favicon.ico' type='image/x-icon' />
<slot name='after-header' />
{jsonLd && <script type='application/ld+json' set:html={JSON.stringify(jsonLd)} />}
</head>
<body>
<YouTubeBanner />

@ -0,0 +1,40 @@
type ArticleSchemaProps = {
url: string;
headline: string;
description: string;
imageUrl: string;
datePublished: string;
dateModified: string;
};
export function generateArticleSchema(article: ArticleSchemaProps) {
const { url, headline, description, imageUrl, datePublished, dateModified } =
article;
return {
'@context': 'https://schema.org',
'@type': 'BlogPosting',
mainEntityOfPage: {
'@type': 'WebPage',
'@id': url,
},
headline: headline,
description: description,
image: imageUrl,
author: {
'@type': 'Person',
name: 'Kamran Ahmed',
url: 'https://twitter.com/kamranahmedse',
},
publisher: {
'@type': 'Organization',
name: 'roadmap.sh',
logo: {
'@type': 'ImageObject',
url: 'https://roadmap.sh/images/brand-square.png',
},
},
datePublished: datePublished,
dateModified: dateModified,
};
}

@ -22,6 +22,13 @@ export interface RoadmapFrontmatter {
description: string;
keywords: string[];
};
schema?: {
headline: string;
description: string;
datePublished: string;
dateModified: string;
imageUrl: string;
};
relatedRoadmaps: string[];
sitemap: {
priority: number;
@ -46,12 +53,9 @@ function roadmapPathToId(filePath: string): string {
* @returns string[] Array of roadmap IDs
*/
export async function getRoadmapIds() {
const roadmapFiles = await import.meta.glob<RoadmapFileType>(
'/src/roadmaps/*/*.md',
{
const roadmapFiles = await import.meta.glob<RoadmapFileType>('/src/roadmaps/*/*.md', {
eager: true,
}
);
});
return Object.keys(roadmapFiles).map(roadmapPathToId);
}
@ -62,15 +66,10 @@ export async function getRoadmapIds() {
* @param tag Tag assigned to roadmap
* @returns Promisified RoadmapFileType[]
*/
export async function getRoadmapsByTag(
tag: string
): Promise<RoadmapFileType[]> {
const roadmapFilesMap = await import.meta.glob<RoadmapFileType>(
'/src/roadmaps/*/*.md',
{
export async function getRoadmapsByTag(tag: string): Promise<RoadmapFileType[]> {
const roadmapFilesMap = await import.meta.glob<RoadmapFileType>('/src/roadmaps/*/*.md', {
eager: true,
}
);
});
const roadmapFiles = Object.values(roadmapFilesMap);
const filteredRoadmaps = roadmapFiles
@ -80,7 +79,5 @@ export async function getRoadmapsByTag(
id: roadmapPathToId(roadmapFile.file),
}));
return filteredRoadmaps.sort(
(a, b) => a.frontmatter.order - b.frontmatter.order
);
return filteredRoadmaps.sort((a, b) => a.frontmatter.order - b.frontmatter.order);
}

@ -1,11 +1,11 @@
---
import CaptchaScripts from '../../components/Captcha/CaptchaScripts.astro';
import FAQs from '../../components/FAQs.astro';
import InteractiveRoadmap from '../../components/InteractiveRoadmap/InteractiveRoadmap.astro';
import MarkdownRoadmap from '../../components/MarkdownRoadmap.astro';
import RoadmapHeader from '../../components/RoadmapHeader.astro';
import UpcomingRoadmap from '../../components/UpcomingRoadmap.astro';
import BaseLayout from '../../layouts/BaseLayout.astro';
import { generateArticleSchema } from '../../lib/jsonld-schema';
import { getRoadmapIds, RoadmapFrontmatter } from '../../lib/roadmap';
export async function getStaticPaths() {
@ -24,6 +24,19 @@ const { roadmapId } = Astro.params as Params;
const roadmapFile = await import(`../../roadmaps/${roadmapId}/${roadmapId}.md`);
const questions = await import(`../../roadmaps/${roadmapId}/faqs.astro`);
const roadmapData = roadmapFile.frontmatter as RoadmapFrontmatter;
let articleSchema;
if (roadmapData.schema) {
const roadmapSchema = roadmapData.schema;
articleSchema = generateArticleSchema({
url: `https://roadmap.sh/${roadmapId}`,
headline: roadmapSchema.headline,
description: roadmapSchema.description,
datePublished: roadmapSchema.datePublished,
dateModified: roadmapSchema.dateModified,
imageUrl: roadmapSchema.imageUrl,
});
}
---
<BaseLayout
@ -33,6 +46,7 @@ const roadmapData = roadmapFile.frontmatter as RoadmapFrontmatter;
keywords={roadmapData.seo.keywords}
sponsor={roadmapData.sponsor}
noIndex={roadmapData.isUpcoming}
jsonLd={articleSchema}
>
<RoadmapHeader
description={roadmapData.description}
@ -55,10 +69,7 @@ const roadmapData = roadmapFile.frontmatter as RoadmapFrontmatter;
{
!roadmapData.isUpcoming && !roadmapData.jsonUrl && (
<MarkdownRoadmap
roadmapId={roadmapId}
description={roadmapData.description}
>
<MarkdownRoadmap roadmapId={roadmapId} description={roadmapData.description}>
<roadmapFile.Content />
</MarkdownRoadmap>
)

@ -20,6 +20,12 @@ sponsor:
category: "SponsorClick"
action: "Ambassador Redirect"
label: "Clicked Ambassador Link"
schema:
headline: "Backend Developer Roadmap"
description: "Learn how to become a Backend Developer with this interactive step by step guide in 2023. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place."
imageUrl: "https://roadmap.sh/roadmaps/backend.png"
datePublished: "2023-01-05"
dateModified: "2023-01-20"
seo:
title: "Backend Developer Roadmap"
description: "Learn to become a modern backend developer using this roadmap. Community driven, articles, resources, guides, interview questions, quizzes for modern backend development."

@ -10,6 +10,12 @@ hasTopics: true
dimensions:
width: 968
height: 2734.48
schema:
headline: "Frontend Developer Roadmap"
description: "Learn how to become a Frontend Developer with this interactive step by step guide in 2023. We also have resources and short descriptions attached to the roadmap items so you can get everything you want to learn in one place."
imageUrl: "https://roadmap.sh/roadmaps/frontend.png"
datePublished: "2023-01-05"
dateModified: "2023-01-20"
seo:
title: "Frontend Developer Roadmap"
description: "Learn to become a modern frontend developer using this roadmap. Community driven, articles, resources, guides, interview questions, quizzes for modern frontend development."

Loading…
Cancel
Save