0;
You can either use these flashcards or jump to the questions list
section below to see them in a list format.
-
+
Questions List
diff --git a/src/components/Questions/QuestionsList.tsx b/src/components/Questions/QuestionsList.tsx
index f7fcd5485..e1d42af21 100644
--- a/src/components/Questions/QuestionsList.tsx
+++ b/src/components/Questions/QuestionsList.tsx
@@ -1,10 +1,10 @@
import { useRef, useState } from 'react';
+import type { QuestionType } from '../../lib/guide-renderer';
import { QuestionsProgress } from './QuestionsProgress';
-import { CheckCircle, SkipForward, Sparkles } from 'lucide-react';
-import { QuestionCard } from './QuestionCard';
-import { isLoggedIn } from '../../lib/jwt';
-import type { QuestionType } from '../../lib/question-group';
+import { cn } from '../../lib/classname';
import { QuestionFinished } from './QuestionFinished';
+import { QuestionCard } from './QuestionCard';
+import { CheckCircleIcon, SkipForwardIcon, SparklesIcon } from 'lucide-react';
import { Confetti } from '../Confetti';
type UserQuestionProgress = {
@@ -16,12 +16,12 @@ type UserQuestionProgress = {
export type QuestionProgressType = keyof UserQuestionProgress;
type QuestionsListProps = {
- groupId: string;
questions: QuestionType[];
+ className?: string;
};
export function QuestionsList(props: QuestionsListProps) {
- const { questions } = props;
+ const { questions, className } = props;
const [showConfetti, setShowConfetti] = useState(false);
const [currQuestionIndex, setCurrQuestionIndex] = useState(0);
@@ -73,7 +73,7 @@ export function QuestionsList(props: QuestionsListProps) {
const hasFinished = hasProgress && currQuestionIndex === -1;
return (
-
+
diff --git a/src/components/TableOfContent/TableOfContent.tsx b/src/components/TableOfContent/TableOfContent.tsx
index a71d01bb8..2ce89d578 100644
--- a/src/components/TableOfContent/TableOfContent.tsx
+++ b/src/components/TableOfContent/TableOfContent.tsx
@@ -1,5 +1,5 @@
import { useState } from 'react';
-import type { HeadingGroupType } from '../../lib/guide';
+import type { HeadingGroupType } from '../../lib/guide-renderer';
import { ChevronDown } from 'lucide-react';
import { cn } from '../../lib/classname';
@@ -23,7 +23,7 @@ export function TableOfContent(props: TableOfContentProps) {
return (
{heading.children.length > 0 && (
-
+
{heading.children.map((children) => {
return (
-
diff --git a/src/lib/guide-renderer.tsx b/src/lib/guide-renderer.tsx
new file mode 100644
index 000000000..ac60f8768
--- /dev/null
+++ b/src/lib/guide-renderer.tsx
@@ -0,0 +1,515 @@
+import { Fragment } from 'react';
+import type { JSX } from 'react/jsx-runtime';
+import type { JSONContent } from '@tiptap/core';
+import { slugify } from './slugger';
+import {
+ CodeBlockContent,
+ CodeBlockHeader,
+ CodeBlockItem,
+} from '../components/Global/CodeBlock';
+import { QuestionsList } from '../components/Questions/QuestionsList';
+
+export type HeadingType = {
+ level: number;
+ text: string;
+ slug: string;
+};
+
+export type HeadingGroupType = HeadingType & { children: HeadingType[] };
+
+export type QuestionType = {
+ id: string;
+ question: string;
+ answer: JSONContent;
+ topics: string[];
+};
+
+export interface MarkType {
+ [key: string]: any;
+ type: string;
+ attrs?: Record | undefined;
+}
+
+export class GuideRenderer {
+ private marksOrder = ['underline', 'bold', 'italic', 'textStyle', 'link'];
+
+ render(content: JSONContent): JSX.Element[] {
+ const nodes = content.content || [];
+ const jsxNodes = nodes
+ .map((node, index) => {
+ const component = this.renderNode(node);
+ if (!component) {
+ return null;
+ }
+
+ return {component};
+ })
+ .filter(Boolean) as JSX.Element[];
+
+ return jsxNodes;
+ }
+
+ tableOfContents(node: JSONContent) {
+ const headlines = this.headlines(node);
+ let toc: HeadingGroupType[] = [];
+ let currentGroup: HeadingGroupType | null = null;
+
+ const hasQASection = node.content?.some(
+ (node) => node.type === 'qaSection',
+ );
+
+ headlines
+ .filter((heading) => heading.level !== 1)
+ .forEach((heading) => {
+ if (heading.level === 2) {
+ currentGroup = { ...heading, children: [] };
+ toc.push(currentGroup);
+ } else if (currentGroup && heading.level === 3) {
+ currentGroup.children.push({ ...heading, text: heading.text });
+ }
+ });
+
+ if (toc.length > 5) {
+ toc.forEach((group) => {
+ group.children = [];
+ });
+ }
+
+ const qaSection = node.content?.find((node) => node.type === 'qaSection');
+ if (hasQASection && qaSection) {
+ toc.push({
+ level: 2,
+ text: 'Test yourself with Flashcards',
+ slug: 'test-with-flashcards',
+ children: [],
+ });
+
+ const questions = this.questions(qaSection);
+ const topicsInOrder = [
+ ...new Set(
+ questions
+ .map((question) => question.topics)
+ .flat()
+ .filter(Boolean),
+ ),
+ ];
+
+ toc.push({
+ level: 2,
+ text: 'Questions List',
+ slug: 'questions-list',
+ children: topicsInOrder.map((topic) => {
+ let topicText = topic;
+ let topicSlug = slugify(topic);
+ if (topic.toLowerCase() === 'beginners') {
+ topicText = 'Beginner Level';
+ topicSlug = 'beginner-level';
+ } else if (topic.toLowerCase() === 'intermediate') {
+ topicText = 'Intermediate Level';
+ topicSlug = 'intermediate-level';
+ } else if (topic.toLowerCase() === 'advanced') {
+ topicText = 'Advanced Level';
+ topicSlug = 'advanced-level';
+ }
+
+ return {
+ level: 2,
+ children: [],
+ slug: topicSlug,
+ text: topicText,
+ };
+ }),
+ });
+ }
+
+ return toc;
+ }
+
+ headlines(node: JSONContent) {
+ const nodes = node.content || [];
+ const headlines: Array = [];
+
+ let hasFoundQASection = false;
+ const extractHeadlines = (node: JSONContent) => {
+ if (node.type === 'qaSection' || hasFoundQASection) {
+ hasFoundQASection = true;
+ return;
+ }
+
+ if (node.type === 'heading') {
+ const text = this.getText(node);
+ headlines.push({
+ level: node.attrs?.level || 1,
+ text,
+ slug: slugify(text),
+ });
+ }
+
+ if (node.content) {
+ node.content.forEach((childNode) => {
+ extractHeadlines(childNode);
+ });
+ }
+ };
+
+ nodes.forEach((childNode) => {
+ extractHeadlines(childNode);
+ });
+
+ return headlines;
+ }
+
+ private getText(node: JSONContent): string {
+ if (node.type === 'text') {
+ return node.text || '';
+ }
+
+ if (node.content) {
+ return node.content.map((childNode) => this.getText(childNode)).join('');
+ }
+
+ return '';
+ }
+
+ // `content` will call corresponding node type
+ // and return text content
+ private content(node: JSONContent): JSX.Element[] {
+ const allNodes = node.content || [];
+ return allNodes
+ .map((childNode, index) => {
+ const component = this.renderNode(childNode);
+ if (!component) {
+ return null;
+ }
+
+ return (
+ {component}
+ );
+ })
+ .filter(Boolean) as JSX.Element[];
+ }
+
+ // `renderNode` will call the method of the corresponding node type
+ private renderNode(node: JSONContent): JSX.Element | null {
+ const type = node.type || '';
+
+ if (type in this) {
+ // @ts-expect-error - `this` is not assignable to type 'never'
+ return this[type]?.(node) as JSX.Element;
+ }
+
+ console.log(`Node type "${type}" is not supported.`);
+ return null;
+ }
+
+ // `renderMark` will call the method of the corresponding mark type
+ private renderMark(node: JSONContent): JSX.Element {
+ // It will wrap the text with the corresponding mark type
+ const text = node?.text || <> >;
+ let marks = node?.marks || [];
+ // sort the marks by uderline, bold, italic, textStyle, link
+ // so that the text will be wrapped in the correct order
+ marks.sort((a, b) => {
+ return this.marksOrder.indexOf(a.type) - this.marksOrder.indexOf(b.type);
+ });
+
+ return marks.reduce(
+ (acc, mark) => {
+ const type = mark.type;
+ if (type in this) {
+ // @ts-expect-error - `this` is not assignable to type 'never'
+ return this[type]?.(mark, acc) as JSX.Element;
+ }
+
+ throw new Error(`Mark type "${type}" is not supported.`);
+ },
+ <>{text}>,
+ );
+ }
+
+ private paragraph(node: JSONContent): JSX.Element {
+ const isEmpty =
+ !node.content ||
+ node.content?.every(
+ (child) => child.type === 'text' && child.text === '',
+ );
+ if (isEmpty) {
+ return <>>;
+ }
+
+ return
{this.content(node)}
;
+ }
+
+ private text(node: JSONContent): JSX.Element {
+ if (node.marks) {
+ return this.renderMark(node);
+ }
+
+ const text = node.text;
+ return text ? <>{text}> : <> >;
+ }
+
+ private bold(_: MarkType, text: JSX.Element): JSX.Element {
+ return {text};
+ }
+
+ private italic(_: MarkType, text: JSX.Element): JSX.Element {
+ return {text};
+ }
+
+ private underline(_: MarkType, text: JSX.Element): JSX.Element {
+ return {text};
+ }
+
+ private strike(_: MarkType, text: JSX.Element): JSX.Element {
+ return {text};
+ }
+
+ private textStyle(mark: MarkType, text: JSX.Element): JSX.Element {
+ const { attrs } = mark;
+ const { color = 'inherit' } = attrs || {};
+
+ return (
+
+ {text}
+
+ );
+ }
+
+ private link(mark: MarkType, text: JSX.Element): JSX.Element {
+ const { attrs } = mark;
+ const { href } = attrs || {};
+
+ const isExternal = href?.startsWith('http');
+ const isRoadmapUrl = href?.startsWith('https://roadmap.sh/');
+
+ const rel = isExternal && !isRoadmapUrl ? 'noopener noreferrer' : undefined;
+
+ return (
+
+ {text}
+
+ );
+ }
+
+ private heading(node: JSONContent): JSX.Element {
+ const { attrs } = node;
+ const { level } = attrs || {};
+
+ const text = this.getText(node);
+ const slug = slugify(text);
+
+ let Comp: keyof JSX.IntrinsicElements = 'h1';
+ if (level === 2) {
+ Comp = 'h2';
+ } else if (level === 3) {
+ Comp = 'h3';
+ } else if (level === 4) {
+ Comp = 'h4';
+ } else if (level === 5) {
+ Comp = 'h5';
+ } else if (level === 6) {
+ Comp = 'h6';
+ }
+
+ return {this.content(node)};
+ }
+
+ private horizontalRule(_: JSONContent): JSX.Element {
+ return
;
+ }
+
+ private orderedList(node: JSONContent): JSX.Element {
+ return {this.content(node)}
;
+ }
+
+ private bulletList(node: JSONContent): JSX.Element {
+ return ;
+ }
+
+ private listItem(node: JSONContent): JSX.Element {
+ return - {this.content(node)}
;
+ }
+
+ private hardBreak(_: JSONContent): JSX.Element {
+ return
;
+ }
+
+ private image(node: JSONContent): JSX.Element {
+ const { attrs } = node;
+ const { src, alt } = attrs || {};
+
+ return
;
+ }
+
+ private code(_: MarkType, text: JSX.Element): JSX.Element {
+ return {text};
+ }
+
+ private codeBlock(node: JSONContent): JSX.Element {
+ const code = this.getText(node);
+ const language = node.attrs?.language || 'javascript';
+
+ return (
+
+
+
+
+ {code}
+
+
+ );
+ }
+
+ private blockquote(node: JSONContent): JSX.Element {
+ return {this.content(node)}
;
+ }
+
+ questions(node: JSONContent) {
+ const content = node.content || [];
+ const questions: QuestionType[] = [];
+ let currentTopic: string | null = null;
+ let currentQuestion: QuestionType | null = null;
+
+ for (const childNode of content) {
+ switch (childNode.type) {
+ case 'heading':
+ // if level is 2, it's a topic
+ if (childNode.attrs?.level === 2) {
+ currentTopic = this.getText(childNode);
+ // if level is 3, it's a question
+ } else if (childNode.attrs?.level === 3) {
+ if (currentTopic) {
+ const questionText = this.getText(childNode);
+ currentQuestion = {
+ id: slugify(questionText),
+ question: questionText,
+ answer: {
+ type: 'doc',
+ content: [],
+ },
+ topics: [currentTopic],
+ };
+ questions.push(currentQuestion);
+ }
+ }
+ break;
+ // anything else is an answer
+ default:
+ if (!currentQuestion || !currentQuestion.answer.content) {
+ console.warn('No current question found');
+ continue;
+ }
+
+ currentQuestion.answer.content.push(childNode);
+ break;
+ }
+ }
+
+ return questions;
+ }
+
+ private qaSection(node: JSONContent): JSX.Element {
+ const questions = this.questions(node);
+
+ const questionsGroupedByTopics = questions.reduce(
+ (acc, question) => {
+ question.topics?.forEach((topic) => {
+ acc[topic] = [...(acc[topic] || []), question];
+ });
+ return acc;
+ },
+ {} as Record,
+ );
+
+ const topicsInOrder = [
+ ...new Set(
+ questions
+ .map((question) => question.topics)
+ .flat()
+ .filter(Boolean),
+ ),
+ ];
+
+ return (
+ <>
+ Test yourself with Flashcards
+
+ You can either use these flashcards or jump to the questions list
+ section below to see them in a list format.
+
+
+
+
+
+
+ Questions List
+
+ If you prefer to see the questions in a list format, you can find them
+ below.
+
+
+ {topicsInOrder.map((questionLevel) => (
+
+
+ {questionLevel.toLowerCase() === 'beginners'
+ ? 'Beginner Level'
+ : questionLevel.toLowerCase() === 'intermediate'
+ ? 'Intermediate Level'
+ : questionLevel.toLowerCase() === 'advanced'
+ ? 'Advanced Level'
+ : questionLevel}
+
+ {questionsGroupedByTopics[questionLevel].map((q) => (
+
+
{q.question}
+
{this.render(q.answer)}
+
+ ))}
+
+ ))}
+ >
+ );
+ }
+
+ private table(node: JSONContent): JSX.Element {
+ const content = node.content || [];
+ const rows = content.filter((node) => node.type === 'tableRow');
+ const firstRow = rows?.[0];
+ const hasTableHead = firstRow?.content?.some(
+ (node) => node.type === 'tableHeader',
+ );
+
+ const remainingRows = rows.slice(hasTableHead ? 1 : 0);
+
+ return (
+
+ {hasTableHead && {this.renderNode(firstRow)}}
+
+ {this.render({
+ type: 'doc',
+ content: remainingRows,
+ })}
+
+
+ );
+ }
+
+ private tableRow(node: JSONContent): JSX.Element {
+ return {this.content(node)}
;
+ }
+
+ private tableHeader(node: JSONContent): JSX.Element {
+ return {this.content(node)} | ;
+ }
+
+ private tableCell(node: JSONContent): JSX.Element {
+ return {this.content(node)} | ;
+ }
+}
+
+export const guideRenderer = new GuideRenderer();
diff --git a/src/lib/open-graph.ts b/src/lib/open-graph.ts
index b4debfe7a..020753fcb 100644
--- a/src/lib/open-graph.ts
+++ b/src/lib/open-graph.ts
@@ -3,8 +3,22 @@ type RoadmapOpenGraphQuery = {
resourceId: string;
};
-export function getOpenGraphImageUrl(params: RoadmapOpenGraphQuery) {
- return `${import.meta.env.DEV ? 'http://localhost:3000' : 'https://roadmap.sh'}/og/${params.group}/${params.resourceId}`;
+export function getOpenGraphImageUrl(
+ params: RoadmapOpenGraphQuery,
+ query?: Record,
+) {
+ const baseUrl = import.meta.env.DEV
+ ? 'http://localhost:3000'
+ : 'https://roadmap.sh';
+
+ const url = new URL(`${baseUrl}/og/${params.group}/${params.resourceId}`);
+ if (query) {
+ Object.entries(query).forEach(([key, value]) => {
+ url.searchParams.set(key, value);
+ });
+ }
+
+ return String(url);
}
export async function getDefaultOpenGraphImageBuffer() {
@@ -15,11 +29,18 @@ export async function getDefaultOpenGraphImageBuffer() {
export async function getResourceOpenGraph(
type: 'roadmap' | 'guide' | 'best-practice',
resourceId: string,
+ query?: Record,
) {
const url = new URL(`${import.meta.env.PUBLIC_API_URL}/v1-open-graph`);
url.searchParams.set('type', type);
url.searchParams.set('resourceId', resourceId);
url.searchParams.set('variant', 'image');
+ if (query) {
+ Object.entries(query).forEach(([key, value]) => {
+ url.searchParams.set(key, value);
+ });
+ }
+
const response = await fetch(url.toString());
return response.text();
diff --git a/src/lib/query-http.ts b/src/lib/query-http.ts
index 70e8cec75..a37fe1a5c 100644
--- a/src/lib/query-http.ts
+++ b/src/lib/query-http.ts
@@ -43,15 +43,19 @@ export async function httpCall(
? url
: `${import.meta.env.PUBLIC_API_URL}${url}`;
try {
- const fingerprintPromise = await fp.load();
- const fingerprint = await fingerprintPromise.get();
+ let visitorId = '';
+ if (typeof window !== 'undefined') {
+ const fingerprintPromise = await fp.load();
+ const fingerprint = await fingerprintPromise.get();
+ visitorId = fingerprint.visitorId;
+ }
const isMultiPartFormData = options?.body instanceof FormData;
const headers = new Headers({
Accept: 'application/json',
Authorization: `Bearer ${Cookies.get(TOKEN_COOKIE_NAME)}`,
- fp: fingerprint.visitorId,
+ ...(visitorId ? { fp: visitorId } : {}),
...(options?.headers ?? {}),
});
diff --git a/src/pages/[roadmapId]/[...topicId].astro b/src/pages/[roadmapId]/[...topicId].astro
index 8682a1e2d..488df4c2f 100644
--- a/src/pages/[roadmapId]/[...topicId].astro
+++ b/src/pages/[roadmapId]/[...topicId].astro
@@ -4,6 +4,13 @@ import path from 'node:path';
import matter from 'gray-matter';
import MarkdownIt from 'markdown-it-async';
import { fileURLToPath } from 'node:url';
+import {
+ getOfficialGuide,
+ type OfficialGuideResponse,
+} from '../../queries/official-guide';
+import BaseLayout from '../../layouts/BaseLayout.astro';
+import { GuideContent } from '../../components/Guide/GuideContent';
+import { getOpenGraphImageUrl } from '../../lib/open-graph';
export const prerender = false;
@@ -16,72 +23,108 @@ if (!topicId || !roadmapId) {
return Astro.rewrite('/404');
}
-// Handle nested paths by joining the segments
-const topicPath = Array.isArray(topicId) ? topicId.join('/') : topicId;
+const isTopic = topicId?.includes('@') || topicId?.includes('/');
+let gitHubUrl = '';
+let htmlContent = '';
+let guide: OfficialGuideResponse | null = null;
+let permalink = '';
+let ogImageUrl = '';
-// Get the project root directory
-const __filename = fileURLToPath(import.meta.url);
-const __dirname = path.dirname(__filename);
+if (isTopic) {
+ // Handle nested paths by joining the segments
+ const topicPath = Array.isArray(topicId) ? topicId.join('/') : topicId;
-// hack to make it work. TODO: Fix
-const projectRoot = path.resolve(__dirname, '../../..').replace(/dist$/, '');
+ // Get the project root directory
+ const __filename = fileURLToPath(import.meta.url);
+ const __dirname = path.dirname(__filename);
-// Construct the path to the markdown file
-let contentPath = path.join(
- projectRoot,
- 'src',
- 'data',
- 'roadmaps',
- roadmapId,
- 'content',
- `${topicPath}.md`,
-);
+ // hack to make it work. TODO: Fix
+ const projectRoot = path.resolve(__dirname, '../../..').replace(/dist$/, '');
-// Check if file exists
-if (!fs.existsSync(contentPath)) {
- const indexFilePath = path.join(
+ // Construct the path to the markdown file
+ let contentPath = path.join(
projectRoot,
'src',
'data',
'roadmaps',
roadmapId,
'content',
- `${topicPath}/index.md`,
+ `${topicPath}.md`,
);
- if (!fs.existsSync(indexFilePath)) {
+ // Check if file exists
+ if (!fs.existsSync(contentPath)) {
+ const indexFilePath = path.join(
+ projectRoot,
+ 'src',
+ 'data',
+ 'roadmaps',
+ roadmapId,
+ 'content',
+ `${topicPath}/index.md`,
+ );
+
+ if (!fs.existsSync(indexFilePath)) {
+ Astro.response.status = 404;
+ Astro.response.statusText = 'Not found';
+
+ return Astro.rewrite('/404');
+ }
+
+ contentPath = indexFilePath;
+ }
+
+ // Read and parse the markdown file
+ const fileContent = fs.readFileSync(contentPath, 'utf-8');
+ const { content } = matter(fileContent);
+
+ const fileWithoutBasePath = contentPath.replace(
+ /.+?\/src\/data/,
+ '/src/data',
+ );
+
+ const md = MarkdownIt();
+
+ gitHubUrl = `https://github.com/kamranahmedse/developer-roadmap/tree/master${fileWithoutBasePath}`;
+ htmlContent = await md.renderAsync(content);
+} else {
+ guide = await getOfficialGuide(topicId, roadmapId);
+ if (!guide) {
Astro.response.status = 404;
Astro.response.statusText = 'Not found';
-
return Astro.rewrite('/404');
}
- contentPath = indexFilePath;
+ permalink = `/${roadmapId}/${topicId}`;
+ ogImageUrl =
+ guide?.featuredImage ||
+ getOpenGraphImageUrl(
+ {
+ group: 'guide',
+ resourceId: topicId,
+ },
+ {
+ roadmapId,
+ },
+ );
}
-
-// Read and parse the markdown file
-const fileContent = fs.readFileSync(contentPath, 'utf-8');
-const { data: frontmatter, content } = matter(fileContent);
-
-// Get the roadmap metadata
-const roadmapPath = path.join(
- projectRoot,
- 'src',
- 'data',
- 'roadmaps',
- roadmapId,
- `${roadmapId}.md`,
-);
-const roadmapContent = fs.readFileSync(roadmapPath, 'utf-8');
-const { data: roadmapData } = matter(roadmapContent);
-
-const fileWithoutBasePath = contentPath.replace(/.+?\/src\/data/, '/src/data');
-const gitHubUrl = `https://github.com/kamranahmedse/developer-roadmap/tree/master${fileWithoutBasePath}`;
-
-const md = MarkdownIt();
-const htmlContent = await md.renderAsync(content);
---
-
-
-
+{
+ isTopic ? (
+ <>
+
+
+ >
+ ) : (
+
+
+
+
+ )
+}
diff --git a/src/pages/ai-data-scientist/career-path.astro b/src/pages/ai-data-scientist/career-path.astro
deleted file mode 100644
index bca35672d..000000000
--- a/src/pages/ai-data-scientist/career-path.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'ai-data-scientist-career-path';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/ai-data-scientist/lifecycle.astro b/src/pages/ai-data-scientist/lifecycle.astro
deleted file mode 100644
index 9347bca71..000000000
--- a/src/pages/ai-data-scientist/lifecycle.astro
+++ /dev/null
@@ -1,29 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'ai-data-scientist-lifecycle';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/ai-data-scientist/skills.astro b/src/pages/ai-data-scientist/skills.astro
deleted file mode 100644
index bc3e50c76..000000000
--- a/src/pages/ai-data-scientist/skills.astro
+++ /dev/null
@@ -1,29 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'ai-data-scientist-skills';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/ai-data-scientist/tools.astro b/src/pages/ai-data-scientist/tools.astro
deleted file mode 100644
index 433b6a9fe..000000000
--- a/src/pages/ai-data-scientist/tools.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'ai-data-scientist-tools';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/ai-data-scientist/vs-ai.astro b/src/pages/ai-data-scientist/vs-ai.astro
deleted file mode 100644
index fa7a21766..000000000
--- a/src/pages/ai-data-scientist/vs-ai.astro
+++ /dev/null
@@ -1,29 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'ai-data-scientist-vs-ai';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/ai-data-scientist/vs-business-analytics.astro b/src/pages/ai-data-scientist/vs-business-analytics.astro
deleted file mode 100644
index a1fc61f66..000000000
--- a/src/pages/ai-data-scientist/vs-business-analytics.astro
+++ /dev/null
@@ -1,29 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'ai-data-scientist-vs-business-analytics';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/ai-data-scientist/vs-computer-science.astro b/src/pages/ai-data-scientist/vs-computer-science.astro
deleted file mode 100644
index 6df46bde1..000000000
--- a/src/pages/ai-data-scientist/vs-computer-science.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'ai-data-scientist-vs-computer-science';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/ai-data-scientist/vs-cyber-security.astro b/src/pages/ai-data-scientist/vs-cyber-security.astro
deleted file mode 100644
index 216ef2390..000000000
--- a/src/pages/ai-data-scientist/vs-cyber-security.astro
+++ /dev/null
@@ -1,29 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'ai-data-scientist-vs-cyber-security';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/ai-data-scientist/vs-data-analytics.astro b/src/pages/ai-data-scientist/vs-data-analytics.astro
deleted file mode 100644
index 1df2ac4b9..000000000
--- a/src/pages/ai-data-scientist/vs-data-analytics.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'ai-data-scientist-vs-data-analytics';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/ai-data-scientist/vs-data-engineering.astro b/src/pages/ai-data-scientist/vs-data-engineering.astro
deleted file mode 100644
index abd369879..000000000
--- a/src/pages/ai-data-scientist/vs-data-engineering.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'ai-data-scientist-vs-data-engineering';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/ai-data-scientist/vs-machine-learning.astro b/src/pages/ai-data-scientist/vs-machine-learning.astro
deleted file mode 100644
index b9f38bbcf..000000000
--- a/src/pages/ai-data-scientist/vs-machine-learning.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'ai-data-scientist-vs-machine-learning';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/ai-data-scientist/vs-software-engineering.astro b/src/pages/ai-data-scientist/vs-software-engineering.astro
deleted file mode 100644
index 385b72467..000000000
--- a/src/pages/ai-data-scientist/vs-software-engineering.astro
+++ /dev/null
@@ -1,29 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'ai-data-scientist-vs-software-engineering';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/ai-data-scientist/vs-statistics.astro b/src/pages/ai-data-scientist/vs-statistics.astro
deleted file mode 100644
index f67188ee0..000000000
--- a/src/pages/ai-data-scientist/vs-statistics.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'ai-data-scientist-vs-statistics';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/authors/[authorId].astro b/src/pages/authors/[authorId].astro
deleted file mode 100644
index 2184e8e44..000000000
--- a/src/pages/authors/[authorId].astro
+++ /dev/null
@@ -1,153 +0,0 @@
----
-import AstroIcon from '../../components/AstroIcon.astro';
-import { GuideListItem } from '../../components/FeaturedGuides/GuideListItem';
-import { VideoListItem } from '../../components/FeaturedVideos/VideoListItem';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getAuthorById, getAuthorIds } from '../../lib/author';
-import { getGuidesByAuthor } from '../../lib/guide';
-import { getAllQuestionGroups } from '../../lib/question-group';
-import { getVideosByAuthor } from '../../lib/video';
-
-export const prerender = true;
-
-interface Params extends Record {}
-
-export async function getStaticPaths() {
- const authorIds = await getAuthorIds();
-
- return authorIds.map((authorId) => ({
- params: { authorId },
- }));
-}
-
-const { authorId } = Astro.params;
-
-const author = await getAuthorById(authorId);
-const authorFrontmatter = author.frontmatter;
-
-const guides = await getGuidesByAuthor(authorId);
-const questionGuides = (await getAllQuestionGroups()).filter(
- (group) => group.frontmatter.authorId === authorId,
-);
-const videos = await getVideosByAuthor(authorId);
----
-
-
-
-
-
-
-
- {authorFrontmatter.name}
-
-
-
-
-
- {
- authorFrontmatter.social?.github && (
-
-
-
- )
- }
- {
- authorFrontmatter.social.twitter && (
-
-
-
- )
- }
- {
- authorFrontmatter.social.linkedin && (
-
-
-
- )
- }
- {
- authorFrontmatter.social.website && (
-
-
-
- )
- }
-
-
-
-
-

-
-
-
-
- {
- [...guides, ...questionGuides]
- .sort((a, b) => {
- const aFrontmatter = a.frontmatter as any;
- const bFrontmatter = b.frontmatter as any;
-
- const aDate = aFrontmatter.date || aFrontmatter.publishedAt;
- const bDate = bFrontmatter.date || bFrontmatter.publishedAt;
- return new Date(bDate).getTime() - new Date(aDate).getTime();
- })
- .map((guide) => )
- }
- {videos.map((video) => )}
-
-
-
diff --git a/src/pages/authors/[authorId].json.ts b/src/pages/authors/[authorId].json.ts
deleted file mode 100644
index 43bf20dbf..000000000
--- a/src/pages/authors/[authorId].json.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import type { APIRoute } from 'astro';
-import { getAuthorById, getAuthorIds } from '../../lib/author';
-
-export const prerender = true;
-
-export async function getStaticPaths() {
- const authorIds = await getAuthorIds();
-
- return await Promise.all(
- authorIds.map(async (authorId) => {
- const authorDetails = await getAuthorById(authorId);
-
- return {
- params: { authorId },
- props: {
- authorDetails: authorDetails?.frontmatter || {},
- },
- };
- }),
- );
-}
-
-export const GET: APIRoute = async function ({ params, request, props }) {
- return new Response(JSON.stringify(props.authorDetails), {
- status: 200,
- headers: {
- 'Content-Type': 'application/json',
- },
- });
-};
diff --git a/src/pages/backend/developer-skills.astro b/src/pages/backend/developer-skills.astro
deleted file mode 100644
index 3010e657e..000000000
--- a/src/pages/backend/developer-skills.astro
+++ /dev/null
@@ -1,29 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'backend-developer-skills';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/backend/developer-tools.astro b/src/pages/backend/developer-tools.astro
deleted file mode 100644
index d00f49ca1..000000000
--- a/src/pages/backend/developer-tools.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'backend-developer-tools';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/backend/frameworks.astro b/src/pages/backend/frameworks.astro
deleted file mode 100644
index aef48f7cb..000000000
--- a/src/pages/backend/frameworks.astro
+++ /dev/null
@@ -1,33 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'backend-frameworks';
-const guide = await getGuideById(guideId).catch(() => null);
-if (!guide) {
- return Astro.redirect('/404');
-}
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/backend/job-description.astro b/src/pages/backend/job-description.astro
deleted file mode 100644
index 61af69fca..000000000
--- a/src/pages/backend/job-description.astro
+++ /dev/null
@@ -1,29 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'backend-job-description';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo?.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
diff --git a/src/pages/backend/languages.astro b/src/pages/backend/languages.astro
deleted file mode 100644
index cd00a4719..000000000
--- a/src/pages/backend/languages.astro
+++ /dev/null
@@ -1,33 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'backend-languages';
-const guide = await getGuideById(guideId).catch(() => null);
-if (!guide) {
- return Astro.redirect('/404');
-}
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/backend/project-ideas.astro b/src/pages/backend/project-ideas.astro
deleted file mode 100644
index c9d714942..000000000
--- a/src/pages/backend/project-ideas.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'backend-project-ideas';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/backend/technologies.astro b/src/pages/backend/technologies.astro
deleted file mode 100644
index 0efcd5018..000000000
--- a/src/pages/backend/technologies.astro
+++ /dev/null
@@ -1,33 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'backend-technologies';
-const guide = await getGuideById(guideId).catch(() => null);
-if (!guide) {
- return Astro.redirect('/404');
-}
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/data-analyst/career-path.astro b/src/pages/data-analyst/career-path.astro
deleted file mode 100644
index c4f48dbf5..000000000
--- a/src/pages/data-analyst/career-path.astro
+++ /dev/null
@@ -1,29 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'data-analyst-career-path';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/data-analyst/how-to-become.astro b/src/pages/data-analyst/how-to-become.astro
deleted file mode 100644
index 2d4e2fac6..000000000
--- a/src/pages/data-analyst/how-to-become.astro
+++ /dev/null
@@ -1,29 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'data-analyst-how-to-become';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/data-analyst/vs-data-engineer.astro b/src/pages/data-analyst/vs-data-engineer.astro
deleted file mode 100644
index 71b7f9452..000000000
--- a/src/pages/data-analyst/vs-data-engineer.astro
+++ /dev/null
@@ -1,29 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'data-analyst-vs-data-engineer';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
\ No newline at end of file
diff --git a/src/pages/devops/automation-tools.astro b/src/pages/devops/automation-tools.astro
deleted file mode 100644
index e1b18f847..000000000
--- a/src/pages/devops/automation-tools.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'devops-automation-tools';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/devops/automation.astro b/src/pages/devops/automation.astro
deleted file mode 100644
index c6f1a3d36..000000000
--- a/src/pages/devops/automation.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'devops-automation';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/devops/best-practices.astro b/src/pages/devops/best-practices.astro
deleted file mode 100644
index e0ce7f19f..000000000
--- a/src/pages/devops/best-practices.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'devops-best-practices';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/devops/career-path.astro b/src/pages/devops/career-path.astro
deleted file mode 100644
index 592f9ea57..000000000
--- a/src/pages/devops/career-path.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'devops-career-path';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/devops/devops-engineer.astro b/src/pages/devops/devops-engineer.astro
deleted file mode 100644
index abf33c5a8..000000000
--- a/src/pages/devops/devops-engineer.astro
+++ /dev/null
@@ -1,32 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-export const prerender = false;
-
-const guideId = 'devops-engineer';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/devops/devops-vs-sre.astro b/src/pages/devops/devops-vs-sre.astro
deleted file mode 100644
index b8a83f091..000000000
--- a/src/pages/devops/devops-vs-sre.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'devops-vs-sre';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/devops/how-to-become-devops-engineer.astro b/src/pages/devops/how-to-become-devops-engineer.astro
deleted file mode 100644
index e0d333c09..000000000
--- a/src/pages/devops/how-to-become-devops-engineer.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { replaceVariables } from '../../lib/markdown';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'how-to-become-devops-engineer';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/devops/job-description.astro b/src/pages/devops/job-description.astro
deleted file mode 100644
index e6455932d..000000000
--- a/src/pages/devops/job-description.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'devops-job-description';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/devops/lifecycle.astro b/src/pages/devops/lifecycle.astro
deleted file mode 100644
index cdf5c514d..000000000
--- a/src/pages/devops/lifecycle.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'devops-lifecycle';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/devops/principles.astro b/src/pages/devops/principles.astro
deleted file mode 100644
index 6bad64ced..000000000
--- a/src/pages/devops/principles.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'devops-principles';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/devops/shift-left-testing.astro b/src/pages/devops/shift-left-testing.astro
deleted file mode 100644
index 439e7ffb5..000000000
--- a/src/pages/devops/shift-left-testing.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'devops-shift-left-testing';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/devops/skills.astro b/src/pages/devops/skills.astro
deleted file mode 100644
index b067817a8..000000000
--- a/src/pages/devops/skills.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { replaceVariables } from '../../lib/markdown';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'devops-skills';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/devops/test-automation.astro b/src/pages/devops/test-automation.astro
deleted file mode 100644
index b03226944..000000000
--- a/src/pages/devops/test-automation.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'devops-test-automation';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/devops/tools.astro b/src/pages/devops/tools.astro
deleted file mode 100644
index 2d4be2ac2..000000000
--- a/src/pages/devops/tools.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'devops-tools';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/devops/vs-agile.astro b/src/pages/devops/vs-agile.astro
deleted file mode 100644
index fa497f10b..000000000
--- a/src/pages/devops/vs-agile.astro
+++ /dev/null
@@ -1,29 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'devops-vs-agile';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/devops/vs-developer.astro b/src/pages/devops/vs-developer.astro
deleted file mode 100644
index 08c31adf0..000000000
--- a/src/pages/devops/vs-developer.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'devops-vs-developer';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/devops/vs-devsecops.astro b/src/pages/devops/vs-devsecops.astro
deleted file mode 100644
index c4047865b..000000000
--- a/src/pages/devops/vs-devsecops.astro
+++ /dev/null
@@ -1,29 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'devops-vs-devsecops';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/devops/vs-full-stack.astro b/src/pages/devops/vs-full-stack.astro
deleted file mode 100644
index 0cff40988..000000000
--- a/src/pages/devops/vs-full-stack.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { replaceVariables } from '../../lib/markdown';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'devops-vs-full-stack';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/frontend/developer-skills.astro b/src/pages/frontend/developer-skills.astro
deleted file mode 100644
index dd7c0b5e7..000000000
--- a/src/pages/frontend/developer-skills.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { replaceVariables } from '../../lib/markdown';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'frontend-developer-skills';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/frontend/frameworks.astro b/src/pages/frontend/frameworks.astro
deleted file mode 100644
index fd535680e..000000000
--- a/src/pages/frontend/frameworks.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { replaceVariables } from '../../lib/markdown';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'frontend-frameworks';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/frontend/how-to-become-frontend-developer.astro b/src/pages/frontend/how-to-become-frontend-developer.astro
deleted file mode 100644
index 353f86660..000000000
--- a/src/pages/frontend/how-to-become-frontend-developer.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'how-to-become-frontend-developer';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/frontend/job-description.astro b/src/pages/frontend/job-description.astro
deleted file mode 100644
index 5aaa73729..000000000
--- a/src/pages/frontend/job-description.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'frontend-job-description';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo?.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/frontend/languages.astro b/src/pages/frontend/languages.astro
deleted file mode 100644
index ee1ada208..000000000
--- a/src/pages/frontend/languages.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { replaceVariables } from '../../lib/markdown';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'frontend-languages';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/frontend/technologies.astro b/src/pages/frontend/technologies.astro
deleted file mode 100644
index 4477e9304..000000000
--- a/src/pages/frontend/technologies.astro
+++ /dev/null
@@ -1,32 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'frontend-technologies';
-const guide = await getGuideById(guideId).catch(() => null);
-if (!guide) {
- return Astro.redirect('/404');
-}
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/frontend/web-developer-portfolio.astro b/src/pages/frontend/web-developer-portfolio.astro
deleted file mode 100644
index 63fe99b9e..000000000
--- a/src/pages/frontend/web-developer-portfolio.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'frontend-web-developer-portfolio';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/full-stack/developer-skills.astro b/src/pages/full-stack/developer-skills.astro
deleted file mode 100644
index d48ecd76d..000000000
--- a/src/pages/full-stack/developer-skills.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'full-stack-developer-skills';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/full-stack/how-to-become.astro b/src/pages/full-stack/how-to-become.astro
deleted file mode 100644
index e23b2b38c..000000000
--- a/src/pages/full-stack/how-to-become.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'full-stack-how-to-become';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/full-stack/job-description.astro b/src/pages/full-stack/job-description.astro
deleted file mode 100644
index d963039fa..000000000
--- a/src/pages/full-stack/job-description.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'full-stack-job-description';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/full-stack/vs-backend.astro b/src/pages/full-stack/vs-backend.astro
deleted file mode 100644
index 617918749..000000000
--- a/src/pages/full-stack/vs-backend.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'full-stack-vs-backend';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/full-stack/vs-software-engineer.astro b/src/pages/full-stack/vs-software-engineer.astro
deleted file mode 100644
index 6d04fa25d..000000000
--- a/src/pages/full-stack/vs-software-engineer.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'full-stack-vs-software-engineer';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/golang/rest-api.astro b/src/pages/golang/rest-api.astro
deleted file mode 100644
index 90acda95e..000000000
--- a/src/pages/golang/rest-api.astro
+++ /dev/null
@@ -1,30 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-const guideId = 'golang-rest-api';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/golang/vs-java.astro b/src/pages/golang/vs-java.astro
deleted file mode 100644
index c8ced7e9d..000000000
--- a/src/pages/golang/vs-java.astro
+++ /dev/null
@@ -1,29 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'go-vs-java';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/guides/[guideId].astro b/src/pages/guides/[guideId].astro
deleted file mode 100644
index c6a7f28c7..000000000
--- a/src/pages/guides/[guideId].astro
+++ /dev/null
@@ -1,47 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getAllGuides, type GuideFileType } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-import { replaceVariables } from '../../lib/markdown';
-
-export const prerender = true;
-
-export interface Props {
- guide: GuideFileType;
-}
-
-export async function getStaticPaths() {
- const guides = (await getAllGuides()).filter(
- (guide) => !guide.frontmatter.excludedBySlug,
- );
-
- return guides.map((guide) => ({
- params: { guideId: guide.id },
- props: { guide },
- }));
-}
-
-const { guideId } = Astro.params;
-const { guide } = Astro.props;
-const { frontmatter: guideData, author } = guide;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
-
diff --git a/src/pages/guides/index.astro b/src/pages/guides/index.astro
deleted file mode 100644
index ac7eeb02e..000000000
--- a/src/pages/guides/index.astro
+++ /dev/null
@@ -1,40 +0,0 @@
----
-import { GuideListItem } from '../../components/FeaturedGuides/GuideListItem';
-import SimplePageHeader from '../../components/SimplePageHeader.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getAllGuides } from '../../lib/guide';
-import { getAllQuestionGroups } from '../../lib/question-group';
-
-const guides = await getAllGuides();
-const questionGuides = (await getAllQuestionGroups()).filter(
- (questionGroup) => questionGroup.frontmatter.authorId,
-);
-
-const allGuides = [...guides, ...questionGuides];
-const sortedGuides = allGuides.sort((a, b) => {
- const aDate = new Date(a.frontmatter.date as string);
- const bDate = new Date(b.frontmatter.date as string);
-
- return bDate.getTime() - aDate.getTime();
-});
----
-
-
-
-
-
-
-
- {sortedGuides.map((guide) => )}
-
-
-
-
-
diff --git a/src/pages/index.astro b/src/pages/index.astro
index 161aa2178..252ad59de 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -6,15 +6,13 @@ import { FeaturedVideoList } from '../components/FeaturedVideos/FeaturedVideoLis
import HeroSection from '../components/HeroSection/HeroSection.astro';
import BaseLayout from '../layouts/BaseLayout.astro';
import { getAllBestPractices } from '../lib/best-practice';
-import { getAllGuides } from '../lib/guide';
-import { getAllQuestionGroups } from '../lib/question-group';
import { getRoadmapsByTag } from '../lib/roadmap';
import { getAllVideos } from '../lib/video';
+import { listOfficialGuides } from '../queries/official-guide';
const roleRoadmaps = await getRoadmapsByTag('role-roadmap');
const skillRoadmaps = await getRoadmapsByTag('skill-roadmap');
const bestPractices = await getAllBestPractices();
-const questionGroups = await getAllQuestionGroups();
export const projectGroups = [
{
@@ -31,9 +29,9 @@ export const projectGroups = [
},
];
-const guides = await getAllGuides();
-const questionGuides = (await getAllQuestionGroups()).filter(
- (questionGroup) => questionGroup.frontmatter.authorId,
+const guides = await listOfficialGuides();
+const questionGuides = guides.filter(
+ (guide) => guide.roadmapId === 'questions' && !!guide?.authorId,
);
const videos = await getAllVideos();
---
@@ -97,16 +95,6 @@ const videos = await getAllVideos();
}))}
/>
- ({
- text: questionGroup.frontmatter.briefTitle,
- url: `/questions/${questionGroup.id}`,
- isNew: questionGroup.frontmatter.isNew,
- }))}
- />
-
-
-
-
diff --git a/src/pages/java/vs-javascript.astro b/src/pages/java/vs-javascript.astro
deleted file mode 100644
index 46343ae44..000000000
--- a/src/pages/java/vs-javascript.astro
+++ /dev/null
@@ -1,29 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'java-vs-javascript';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/java/vs-python.astro b/src/pages/java/vs-python.astro
deleted file mode 100644
index 7f8632aa5..000000000
--- a/src/pages/java/vs-python.astro
+++ /dev/null
@@ -1,29 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'java-vs-python';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/javascript/vs-typescript.astro b/src/pages/javascript/vs-typescript.astro
deleted file mode 100644
index 46351390a..000000000
--- a/src/pages/javascript/vs-typescript.astro
+++ /dev/null
@@ -1,29 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'javascript-vs-typescript';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
diff --git a/src/pages/og/guide/[slug].ts b/src/pages/og/guide/[slug].ts
index 947d023d1..ee35a7ba0 100644
--- a/src/pages/og/guide/[slug].ts
+++ b/src/pages/og/guide/[slug].ts
@@ -3,7 +3,7 @@ import {
getDefaultOpenGraphImageBuffer,
getResourceOpenGraph,
} from '../../../lib/open-graph';
-import {Transformer} from "@napi-rs/image";
+import { Transformer } from '@napi-rs/image';
export const prerender = false;
@@ -13,6 +13,7 @@ type Params = {
export const GET: APIRoute = async (context) => {
const { slug } = context.params;
+ const { searchParams } = context.url;
if (!slug) {
const buffer = await getDefaultOpenGraphImageBuffer();
@@ -23,9 +24,14 @@ export const GET: APIRoute = async (context) => {
});
}
- const svg = await getResourceOpenGraph('guide', slug);
+ const svg = await getResourceOpenGraph(
+ 'guide',
+ slug,
+ Object.fromEntries(searchParams.entries()),
+ );
const transformer = Transformer.fromSvg(svg).crop(0, 0, 1200, 630);
+ // @ts-expect-error - Buffer is not assignable to BodyInit
return new Response(await transformer.png(), {
headers: {
'Content-Type': 'image/png',
diff --git a/src/pages/sql/hard-to-learn.astro b/src/pages/sql/hard-to-learn.astro
deleted file mode 100644
index 75fdeab5d..000000000
--- a/src/pages/sql/hard-to-learn.astro
+++ /dev/null
@@ -1,29 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'sql-hard-to-learn';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
\ No newline at end of file
diff --git a/src/pages/sql/how-long-to-learn.astro b/src/pages/sql/how-long-to-learn.astro
deleted file mode 100644
index bcae6a815..000000000
--- a/src/pages/sql/how-long-to-learn.astro
+++ /dev/null
@@ -1,29 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'sql-how-long-to-learn';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
\ No newline at end of file
diff --git a/src/pages/sql/vs-mysql.astro b/src/pages/sql/vs-mysql.astro
deleted file mode 100644
index 8076683e8..000000000
--- a/src/pages/sql/vs-mysql.astro
+++ /dev/null
@@ -1,29 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'sql-vs-mysql';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
\ No newline at end of file
diff --git a/src/pages/sql/vs-python.astro b/src/pages/sql/vs-python.astro
deleted file mode 100644
index cec52ad78..000000000
--- a/src/pages/sql/vs-python.astro
+++ /dev/null
@@ -1,29 +0,0 @@
----
-import GuideContent from '../../components/Guide/GuideContent.astro';
-import BaseLayout from '../../layouts/BaseLayout.astro';
-import { getGuideById } from '../../lib/guide';
-import { getOpenGraphImageUrl } from '../../lib/open-graph';
-
-const guideId = 'sql-vs-python';
-const guide = await getGuideById(guideId);
-
-const { frontmatter: guideData } = guide!;
-
-const ogImageUrl =
- guideData.seo.ogImageUrl ||
- getOpenGraphImageUrl({
- group: 'guide',
- resourceId: guideId,
- });
----
-
-
-
-
-
\ No newline at end of file
diff --git a/src/queries/official-guide.ts b/src/queries/official-guide.ts
new file mode 100644
index 000000000..c8215845b
--- /dev/null
+++ b/src/queries/official-guide.ts
@@ -0,0 +1,113 @@
+import { FetchError, httpGet } from '../lib/query-http';
+
+export const allowedOfficialGuideStatus = ['draft', 'published'] as const;
+export type AllowedOfficialGuideStatus =
+ (typeof allowedOfficialGuideStatus)[number];
+
+export interface OfficialGuideDocument {
+ _id: string;
+ title: string;
+ slug: string;
+ description?: string;
+ content: any;
+ authorId: string;
+ roadmapId?: string;
+ featuredImage?: string;
+ status: AllowedOfficialGuideStatus;
+ publishedAt?: Date;
+ seo?: {
+ metaTitle?: string;
+ metaDescription?: string;
+ keywords?: string[];
+ };
+ tags?: string[];
+
+ questionCount?: number;
+ questionTopicCount?: number;
+
+ viewCount?: number;
+ createdAt: Date;
+ updatedAt: Date;
+}
+
+type ListOfficialGuidesQuery = {
+ authorSlug?: string;
+ roadmapId?: string;
+};
+
+export async function listOfficialGuides(query: ListOfficialGuidesQuery = {}) {
+ try {
+ const guides = await httpGet(
+ `/v1-list-official-guides`,
+ query,
+ );
+
+ return guides.sort((a, b) => {
+ const aDate = new Date(a.createdAt);
+ const bDate = new Date(b.createdAt);
+
+ return bDate.getTime() - aDate.getTime();
+ });
+ } catch (error) {
+ if (FetchError.isFetchError(error) && error.status === 404) {
+ return [];
+ }
+
+ throw error;
+ }
+}
+
+export interface OfficialAuthorDocument {
+ _id: string;
+ name: string;
+ slug: string;
+ bio?: string;
+ avatar?: string;
+ socialLinks?: {
+ twitter?: string;
+ linkedin?: string;
+ github?: string;
+ website?: string;
+ };
+ isActive: boolean;
+ createdAt: Date;
+ updatedAt: Date;
+}
+
+type GuideWithAuthor = OfficialGuideDocument & {
+ author?: Pick<
+ OfficialAuthorDocument,
+ 'name' | 'slug' | 'avatar' | 'bio' | 'socialLinks'
+ >;
+ relatedGuides?: Pick[];
+};
+
+export type OfficialGuideResponse = GuideWithAuthor;
+
+export async function getOfficialGuide(slug: string, roadmapId?: string) {
+ try {
+ const guide = await httpGet(
+ `/v1-official-guide/${slug}`,
+ {
+ ...(roadmapId ? { roadmapId } : {}),
+ },
+ );
+
+ return guide;
+ } catch (error) {
+ if (FetchError.isFetchError(error) && error.status === 404) {
+ return null;
+ }
+
+ throw error;
+ }
+}
+
+export function getOfficialGuideHref(slug: string, roadmapId?: string) {
+ const isExternal = roadmapId && roadmapId !== 'questions';
+ return isExternal
+ ? `${import.meta.env.PUBLIC_APP_URL}/${roadmapId}/${slug}`
+ : roadmapId
+ ? `/${roadmapId}/${slug}`
+ : `/guides/${slug}`;
+}