From 2333694e2c6e45a156ba2ed8f8e516b3c752cd7f Mon Sep 17 00:00:00 2001 From: Arik Chakma Date: Sat, 21 Sep 2024 04:26:30 +0600 Subject: [PATCH] feat: migrate projects --- .../CustomRoadmap/FlowRoadmapRenderer.tsx | 3 +- src/components/Guide/GuideContent.astro | 4 +- src/components/GuideHeader.astro | 14 ++-- .../Projects/ListProjectSolutions.tsx | 5 +- src/components/Projects/ProjectCard.tsx | 8 +-- src/components/Projects/ProjectsList.tsx | 29 +++++--- src/components/Projects/ProjectsPage.tsx | 16 ++--- src/components/Questions/QuestionGuide.astro | 6 +- src/components/VideoHeader.astro | 9 ++- src/content/config.ts | 2 + src/content/project.ts | 28 ++++++++ .../projects/accessible-form-ui.md | 0 src/{data => content}/projects/accordion.md | 0 .../projects/basic-dockerfile.md | 0 .../projects/basic-html-website.md | 0 .../projects/blogging-platform-api.md | 0 .../projects/broadcast-server.md | 0 .../projects/caching-server.md | 0 .../projects/changelog-component.md | 0 .../projects/cookie-consent.md | 0 .../projects/custom-dropdown.md | 0 .../projects/database-backup-utility.md | 0 .../projects/datepicker-ui.md | 0 .../projects/ecommerce-api.md | 0 .../projects/expense-tracker-api.md | 0 .../projects/expense-tracker.md | 0 .../projects/fitness-workout-tracker.md | 0 .../projects/github-random-repo.md | 0 .../projects/github-user-activity.md | 0 src/{data => content}/projects/image-grid.md | 0 .../projects/image-processing-service.md | 0 .../projects/log-archive-tool.md | 0 .../projects/markdown-note-taking-app.md | 0 .../projects/movie-reservation-system.md | 0 .../projects/number-guessing-game.md | 0 .../projects/personal-blog.md | 0 .../projects/portfolio-website.md | 0 .../projects/realtime-leaderboard-system.md | 0 .../projects/reddit-client.md | 0 .../projects/restricted-textarea.md | 0 .../projects/scalable-ecommerce-platform.md | 0 src/{data => content}/projects/simple-tabs.md | 0 .../projects/single-page-cv.md | 0 .../projects/task-tracker-js.md | 0 .../projects/task-tracker.md | 0 .../projects/temperature-converter.md | 10 +-- .../projects/testimonial-cards.md | 0 .../projects/todo-list-api.md | 0 src/{data => content}/projects/tooltip-ui.md | 0 .../projects/unit-converter.md | 0 .../projects/url-shortening-service.md | 0 .../projects/weather-api-wrapper-service.md | 0 src/lib/project.ts | 68 ++++--------------- src/lib/video.ts | 4 +- src/pages/[roadmapId]/projects.astro | 2 +- src/pages/authors/[authorId].astro | 2 +- src/pages/index.astro | 2 +- src/pages/pages.json.ts | 16 ++--- src/pages/projects/[projectId]/index.astro | 19 +++--- .../projects/[projectId]/solutions.astro | 10 +-- src/pages/projects/index.astro | 4 +- src/pages/questions/[questionGroupId].astro | 2 +- 62 files changed, 124 insertions(+), 139 deletions(-) create mode 100644 src/content/project.ts rename src/{data => content}/projects/accessible-form-ui.md (100%) rename src/{data => content}/projects/accordion.md (100%) rename src/{data => content}/projects/basic-dockerfile.md (100%) rename src/{data => content}/projects/basic-html-website.md (100%) rename src/{data => content}/projects/blogging-platform-api.md (100%) rename src/{data => content}/projects/broadcast-server.md (100%) rename src/{data => content}/projects/caching-server.md (100%) rename src/{data => content}/projects/changelog-component.md (100%) rename src/{data => content}/projects/cookie-consent.md (100%) rename src/{data => content}/projects/custom-dropdown.md (100%) rename src/{data => content}/projects/database-backup-utility.md (100%) rename src/{data => content}/projects/datepicker-ui.md (100%) rename src/{data => content}/projects/ecommerce-api.md (100%) rename src/{data => content}/projects/expense-tracker-api.md (100%) rename src/{data => content}/projects/expense-tracker.md (100%) rename src/{data => content}/projects/fitness-workout-tracker.md (100%) rename src/{data => content}/projects/github-random-repo.md (100%) rename src/{data => content}/projects/github-user-activity.md (100%) rename src/{data => content}/projects/image-grid.md (100%) rename src/{data => content}/projects/image-processing-service.md (100%) rename src/{data => content}/projects/log-archive-tool.md (100%) rename src/{data => content}/projects/markdown-note-taking-app.md (100%) rename src/{data => content}/projects/movie-reservation-system.md (100%) rename src/{data => content}/projects/number-guessing-game.md (100%) rename src/{data => content}/projects/personal-blog.md (100%) rename src/{data => content}/projects/portfolio-website.md (100%) rename src/{data => content}/projects/realtime-leaderboard-system.md (100%) rename src/{data => content}/projects/reddit-client.md (100%) rename src/{data => content}/projects/restricted-textarea.md (100%) rename src/{data => content}/projects/scalable-ecommerce-platform.md (100%) rename src/{data => content}/projects/simple-tabs.md (100%) rename src/{data => content}/projects/single-page-cv.md (100%) rename src/{data => content}/projects/task-tracker-js.md (100%) rename src/{data => content}/projects/task-tracker.md (100%) rename src/{data => content}/projects/temperature-converter.md (82%) rename src/{data => content}/projects/testimonial-cards.md (100%) rename src/{data => content}/projects/todo-list-api.md (100%) rename src/{data => content}/projects/tooltip-ui.md (100%) rename src/{data => content}/projects/unit-converter.md (100%) rename src/{data => content}/projects/url-shortening-service.md (100%) rename src/{data => content}/projects/weather-api-wrapper-service.md (100%) diff --git a/src/components/CustomRoadmap/FlowRoadmapRenderer.tsx b/src/components/CustomRoadmap/FlowRoadmapRenderer.tsx index f64bf7cad..ed8457816 100644 --- a/src/components/CustomRoadmap/FlowRoadmapRenderer.tsx +++ b/src/components/CustomRoadmap/FlowRoadmapRenderer.tsx @@ -159,7 +159,8 @@ export function FlowRoadmapRenderer(props: FlowRoadmapRendererProps) { {hideRenderer && ( )} diff --git a/src/components/Guide/GuideContent.astro b/src/components/Guide/GuideContent.astro index d07edd159..15d2ef57d 100644 --- a/src/components/Guide/GuideContent.astro +++ b/src/components/Guide/GuideContent.astro @@ -40,7 +40,7 @@ const { data: guideFrontmatter, author } = guide;

· {author.frontmatter.name} - {author.frontmatter.name} + {author.data.name} · @@ -39,7 +39,7 @@ return undefined; · Improve this Guide

diff --git a/src/components/Projects/ListProjectSolutions.tsx b/src/components/Projects/ListProjectSolutions.tsx index 2d29a4ae2..63bf481ed 100644 --- a/src/components/Projects/ListProjectSolutions.tsx +++ b/src/components/Projects/ListProjectSolutions.tsx @@ -14,8 +14,7 @@ import { showLoginPopup } from '../../lib/popup'; import { VoteButton } from './VoteButton.tsx'; import { GitHubIcon } from '../ReactIcons/GitHubIcon.tsx'; import { SelectLanguages } from './SelectLanguages.tsx'; -import type { ProjectFrontmatter } from '../../lib/project.ts'; -import { ProjectSolutionModal } from './ProjectSolutionModal.tsx'; +import type { ProjectFileType } from '../../lib/project.ts'; export interface ProjectStatusDocument { _id?: string; @@ -65,7 +64,7 @@ type PageState = { }; type ListProjectSolutionsProps = { - project: ProjectFrontmatter; + project: ProjectFileType['data']; projectId: string; }; diff --git a/src/components/Projects/ProjectCard.tsx b/src/components/Projects/ProjectCard.tsx index efa0ac210..5fe86ea38 100644 --- a/src/components/Projects/ProjectCard.tsx +++ b/src/components/Projects/ProjectCard.tsx @@ -1,10 +1,8 @@ import { Badge } from '../Badge.tsx'; -import type { - ProjectDifficultyType, - ProjectFileType, -} from '../../lib/project.ts'; +import type { ProjectFileType } from '../../lib/project.ts'; import { Users } from 'lucide-react'; import { formatCommaNumber } from '../../lib/number.ts'; +import type { ProjectDifficultyType } from '../../content/project.ts'; type ProjectCardProps = { project: ProjectFileType; @@ -20,7 +18,7 @@ const badgeVariants: Record = { export function ProjectCard(props: ProjectCardProps) { const { project, userCount = 0 } = props; - const { frontmatter, id } = project; + const { data: frontmatter, slug: id } = project; return ( (); for (const project of projects) { - const difficulty = project.frontmatter.difficulty; + const difficulty = project.data.difficulty; if (!result.has(difficulty)) { result.set(difficulty, []); @@ -78,6 +78,7 @@ export function ProjectsList(props: ProjectsListProps) {
{projectDifficulties.map((projectDifficulty) => ( { setDifficulty(projectDifficulty); setUrlParams({ difficulty: projectDifficulty }); @@ -119,18 +120,24 @@ export function ProjectsList(props: ProjectsListProps) { {matchingProjects .sort((project) => { - return project.frontmatter.difficulty === 'beginner' + return project.data.difficulty === 'beginner' ? -1 - : project.frontmatter.difficulty === 'intermediate' + : project.data.difficulty === 'intermediate' ? 0 : 1; }) .sort((a, b) => { - return a.frontmatter.sort - b.frontmatter.sort; + return a.data.sort - b.data.sort; }) .map((matchingProject) => { - const count = userCounts[matchingProject?.id] || 0; - return ; + const count = userCounts[matchingProject?.slug] || 0; + return ( + + ); })}
diff --git a/src/components/Projects/ProjectsPage.tsx b/src/components/Projects/ProjectsPage.tsx index f3d797763..a3ad71fce 100644 --- a/src/components/Projects/ProjectsPage.tsx +++ b/src/components/Projects/ProjectsPage.tsx @@ -7,11 +7,9 @@ import { setUrlParams, } from '../../lib/browser.ts'; import { CategoryFilterButton } from '../Roadmaps/CategoryFilterButton.tsx'; -import { - projectDifficulties, - type ProjectFileType, -} from '../../lib/project.ts'; +import { type ProjectFileType } from '../../lib/project.ts'; import { ProjectCard } from './ProjectCard.tsx'; +import { projectDifficulties } from '../../content/project.ts'; type ProjectGroup = { id: string; @@ -28,7 +26,7 @@ export function ProjectsPage(props: ProjectsPageProps) { const { roadmapsProjects, userCounts } = props; const allUniqueProjectIds = new Set( roadmapsProjects.flatMap((group) => - group.projects.map((project) => project.id), + group.projects.map((project) => project.slug), ), ); const allUniqueProjects = useMemo( @@ -37,7 +35,7 @@ export function ProjectsPage(props: ProjectsPageProps) { .map((id) => roadmapsProjects .flatMap((group) => group.projects) - .find((project) => project.id === id), + .find((project) => project.slug === id), ) .filter(Boolean) as ProjectFileType[], [allUniqueProjectIds], @@ -67,8 +65,8 @@ export function ProjectsPage(props: ProjectsPageProps) { const sortedVisibleProjects = useMemo( () => visibleProjects.sort((a, b) => { - const projectADifficulty = a?.frontmatter.difficulty || 'beginner'; - const projectBDifficulty = b?.frontmatter.difficulty || 'beginner'; + const projectADifficulty = a?.data.difficulty || 'beginner'; + const projectBDifficulty = b?.data.difficulty || 'beginner'; return ( projectDifficulties.indexOf(projectADifficulty) - projectDifficulties.indexOf(projectBDifficulty) @@ -189,7 +187,7 @@ export function ProjectsPage(props: ProjectsPageProps) { ))} diff --git a/src/components/Questions/QuestionGuide.astro b/src/components/Questions/QuestionGuide.astro index caefcde14..1b17ad72d 100644 --- a/src/components/Questions/QuestionGuide.astro +++ b/src/components/Questions/QuestionGuide.astro @@ -80,7 +80,7 @@ const { data: guideFrontmatter, author } = questionGroup; author && (

·

{author.frontmatter.name} - {author.frontmatter.name} + {author.data.name} · Illustrated Video diff --git a/src/content/config.ts b/src/content/config.ts index d5ba9159d..3f4e01b12 100644 --- a/src/content/config.ts +++ b/src/content/config.ts @@ -1,9 +1,11 @@ import { authorCollection } from './author'; import { guideCollection } from './guide'; +import { projectCollection } from './project'; import { questionGroupCollection } from './question-group'; export const collections = { authors: authorCollection, guides: guideCollection, 'question-groups': questionGroupCollection, + projects: projectCollection, }; diff --git a/src/content/project.ts b/src/content/project.ts new file mode 100644 index 000000000..08c368571 --- /dev/null +++ b/src/content/project.ts @@ -0,0 +1,28 @@ +import { defineCollection, z } from 'astro:content'; + +export const projectDifficulties = [ + 'beginner', + 'intermediate', + 'advanced', +] as const; +export type ProjectDifficultyType = (typeof projectDifficulties)[number]; + +export const projectCollection = defineCollection({ + type: 'content', + schema: z.object({ + title: z.string(), + description: z.string(), + isNew: z.boolean(), + sort: z.number(), + difficulty: z.enum(projectDifficulties), + nature: z.string(), + skills: z.array(z.string()), + seo: z.object({ + title: z.string(), + description: z.string(), + keywords: z.array(z.string()), + ogImageUrl: z.string().optional(), + }), + roadmapIds: z.array(z.string()), + }), +}); diff --git a/src/data/projects/accessible-form-ui.md b/src/content/projects/accessible-form-ui.md similarity index 100% rename from src/data/projects/accessible-form-ui.md rename to src/content/projects/accessible-form-ui.md diff --git a/src/data/projects/accordion.md b/src/content/projects/accordion.md similarity index 100% rename from src/data/projects/accordion.md rename to src/content/projects/accordion.md diff --git a/src/data/projects/basic-dockerfile.md b/src/content/projects/basic-dockerfile.md similarity index 100% rename from src/data/projects/basic-dockerfile.md rename to src/content/projects/basic-dockerfile.md diff --git a/src/data/projects/basic-html-website.md b/src/content/projects/basic-html-website.md similarity index 100% rename from src/data/projects/basic-html-website.md rename to src/content/projects/basic-html-website.md diff --git a/src/data/projects/blogging-platform-api.md b/src/content/projects/blogging-platform-api.md similarity index 100% rename from src/data/projects/blogging-platform-api.md rename to src/content/projects/blogging-platform-api.md diff --git a/src/data/projects/broadcast-server.md b/src/content/projects/broadcast-server.md similarity index 100% rename from src/data/projects/broadcast-server.md rename to src/content/projects/broadcast-server.md diff --git a/src/data/projects/caching-server.md b/src/content/projects/caching-server.md similarity index 100% rename from src/data/projects/caching-server.md rename to src/content/projects/caching-server.md diff --git a/src/data/projects/changelog-component.md b/src/content/projects/changelog-component.md similarity index 100% rename from src/data/projects/changelog-component.md rename to src/content/projects/changelog-component.md diff --git a/src/data/projects/cookie-consent.md b/src/content/projects/cookie-consent.md similarity index 100% rename from src/data/projects/cookie-consent.md rename to src/content/projects/cookie-consent.md diff --git a/src/data/projects/custom-dropdown.md b/src/content/projects/custom-dropdown.md similarity index 100% rename from src/data/projects/custom-dropdown.md rename to src/content/projects/custom-dropdown.md diff --git a/src/data/projects/database-backup-utility.md b/src/content/projects/database-backup-utility.md similarity index 100% rename from src/data/projects/database-backup-utility.md rename to src/content/projects/database-backup-utility.md diff --git a/src/data/projects/datepicker-ui.md b/src/content/projects/datepicker-ui.md similarity index 100% rename from src/data/projects/datepicker-ui.md rename to src/content/projects/datepicker-ui.md diff --git a/src/data/projects/ecommerce-api.md b/src/content/projects/ecommerce-api.md similarity index 100% rename from src/data/projects/ecommerce-api.md rename to src/content/projects/ecommerce-api.md diff --git a/src/data/projects/expense-tracker-api.md b/src/content/projects/expense-tracker-api.md similarity index 100% rename from src/data/projects/expense-tracker-api.md rename to src/content/projects/expense-tracker-api.md diff --git a/src/data/projects/expense-tracker.md b/src/content/projects/expense-tracker.md similarity index 100% rename from src/data/projects/expense-tracker.md rename to src/content/projects/expense-tracker.md diff --git a/src/data/projects/fitness-workout-tracker.md b/src/content/projects/fitness-workout-tracker.md similarity index 100% rename from src/data/projects/fitness-workout-tracker.md rename to src/content/projects/fitness-workout-tracker.md diff --git a/src/data/projects/github-random-repo.md b/src/content/projects/github-random-repo.md similarity index 100% rename from src/data/projects/github-random-repo.md rename to src/content/projects/github-random-repo.md diff --git a/src/data/projects/github-user-activity.md b/src/content/projects/github-user-activity.md similarity index 100% rename from src/data/projects/github-user-activity.md rename to src/content/projects/github-user-activity.md diff --git a/src/data/projects/image-grid.md b/src/content/projects/image-grid.md similarity index 100% rename from src/data/projects/image-grid.md rename to src/content/projects/image-grid.md diff --git a/src/data/projects/image-processing-service.md b/src/content/projects/image-processing-service.md similarity index 100% rename from src/data/projects/image-processing-service.md rename to src/content/projects/image-processing-service.md diff --git a/src/data/projects/log-archive-tool.md b/src/content/projects/log-archive-tool.md similarity index 100% rename from src/data/projects/log-archive-tool.md rename to src/content/projects/log-archive-tool.md diff --git a/src/data/projects/markdown-note-taking-app.md b/src/content/projects/markdown-note-taking-app.md similarity index 100% rename from src/data/projects/markdown-note-taking-app.md rename to src/content/projects/markdown-note-taking-app.md diff --git a/src/data/projects/movie-reservation-system.md b/src/content/projects/movie-reservation-system.md similarity index 100% rename from src/data/projects/movie-reservation-system.md rename to src/content/projects/movie-reservation-system.md diff --git a/src/data/projects/number-guessing-game.md b/src/content/projects/number-guessing-game.md similarity index 100% rename from src/data/projects/number-guessing-game.md rename to src/content/projects/number-guessing-game.md diff --git a/src/data/projects/personal-blog.md b/src/content/projects/personal-blog.md similarity index 100% rename from src/data/projects/personal-blog.md rename to src/content/projects/personal-blog.md diff --git a/src/data/projects/portfolio-website.md b/src/content/projects/portfolio-website.md similarity index 100% rename from src/data/projects/portfolio-website.md rename to src/content/projects/portfolio-website.md diff --git a/src/data/projects/realtime-leaderboard-system.md b/src/content/projects/realtime-leaderboard-system.md similarity index 100% rename from src/data/projects/realtime-leaderboard-system.md rename to src/content/projects/realtime-leaderboard-system.md diff --git a/src/data/projects/reddit-client.md b/src/content/projects/reddit-client.md similarity index 100% rename from src/data/projects/reddit-client.md rename to src/content/projects/reddit-client.md diff --git a/src/data/projects/restricted-textarea.md b/src/content/projects/restricted-textarea.md similarity index 100% rename from src/data/projects/restricted-textarea.md rename to src/content/projects/restricted-textarea.md diff --git a/src/data/projects/scalable-ecommerce-platform.md b/src/content/projects/scalable-ecommerce-platform.md similarity index 100% rename from src/data/projects/scalable-ecommerce-platform.md rename to src/content/projects/scalable-ecommerce-platform.md diff --git a/src/data/projects/simple-tabs.md b/src/content/projects/simple-tabs.md similarity index 100% rename from src/data/projects/simple-tabs.md rename to src/content/projects/simple-tabs.md diff --git a/src/data/projects/single-page-cv.md b/src/content/projects/single-page-cv.md similarity index 100% rename from src/data/projects/single-page-cv.md rename to src/content/projects/single-page-cv.md diff --git a/src/data/projects/task-tracker-js.md b/src/content/projects/task-tracker-js.md similarity index 100% rename from src/data/projects/task-tracker-js.md rename to src/content/projects/task-tracker-js.md diff --git a/src/data/projects/task-tracker.md b/src/content/projects/task-tracker.md similarity index 100% rename from src/data/projects/task-tracker.md rename to src/content/projects/task-tracker.md diff --git a/src/data/projects/temperature-converter.md b/src/content/projects/temperature-converter.md similarity index 82% rename from src/data/projects/temperature-converter.md rename to src/content/projects/temperature-converter.md index c142baac7..9a43312b4 100644 --- a/src/data/projects/temperature-converter.md +++ b/src/content/projects/temperature-converter.md @@ -11,14 +11,14 @@ skills: - JavaScript - DOM Manipulation seo: - - title: Build a Temperature Converter with JavaScript - - description: Learn how to create an interactive temperature converter that converts between Celsius, Fahrenheit, and Kelvin using JavaScript. - - keywords: + title: Build a Temperature Converter with JavaScript + description: Learn how to create an interactive temperature converter that converts between Celsius, Fahrenheit, and Kelvin using JavaScript. + keywords: - 'temperature converter' - 'javascript project' - 'unit conversion' - 'html and css' -roadmapIds: +roadmapIds: - 'frontend' --- @@ -30,4 +30,4 @@ Here is a mockup of what the temperature converter might look like: [![Temperature Converter](https://assets.roadmap.sh/guest/temperature-converter-8omel.png)](https://assets.roadmap.sh/guest/temperature-converter-8omel.png) -This project will help you gain experience with handling user input, conditionally enabling form elements, and performing simple calculations using JavaScript. \ No newline at end of file +This project will help you gain experience with handling user input, conditionally enabling form elements, and performing simple calculations using JavaScript. diff --git a/src/data/projects/testimonial-cards.md b/src/content/projects/testimonial-cards.md similarity index 100% rename from src/data/projects/testimonial-cards.md rename to src/content/projects/testimonial-cards.md diff --git a/src/data/projects/todo-list-api.md b/src/content/projects/todo-list-api.md similarity index 100% rename from src/data/projects/todo-list-api.md rename to src/content/projects/todo-list-api.md diff --git a/src/data/projects/tooltip-ui.md b/src/content/projects/tooltip-ui.md similarity index 100% rename from src/data/projects/tooltip-ui.md rename to src/content/projects/tooltip-ui.md diff --git a/src/data/projects/unit-converter.md b/src/content/projects/unit-converter.md similarity index 100% rename from src/data/projects/unit-converter.md rename to src/content/projects/unit-converter.md diff --git a/src/data/projects/url-shortening-service.md b/src/content/projects/url-shortening-service.md similarity index 100% rename from src/data/projects/url-shortening-service.md rename to src/content/projects/url-shortening-service.md diff --git a/src/data/projects/weather-api-wrapper-service.md b/src/content/projects/weather-api-wrapper-service.md similarity index 100% rename from src/data/projects/weather-api-wrapper-service.md rename to src/content/projects/weather-api-wrapper-service.md diff --git a/src/lib/project.ts b/src/lib/project.ts index 011f829f7..6a693f453 100644 --- a/src/lib/project.ts +++ b/src/lib/project.ts @@ -1,54 +1,17 @@ -import type { MarkdownFileType } from './file'; +import { getCollection, type CollectionEntry } from 'astro:content'; import { getRoadmapById, type RoadmapFileType } from './roadmap.ts'; -export const projectDifficulties = [ - 'beginner', - 'intermediate', - 'advanced', -] as const; -export type ProjectDifficultyType = (typeof projectDifficulties)[number]; - -export interface ProjectFrontmatter { - title: string; - description: string; - isNew: boolean; - sort: number; - difficulty: ProjectDifficultyType; - nature: string; - skills: string[]; - seo: { - title: string; - description: string; - keywords: string[]; - ogImageUrl: string; - }; - roadmapIds: string[]; -} - -export type ProjectFileType = MarkdownFileType & { - id: string; +export type ProjectFileType = CollectionEntry<'projects'> & { roadmaps: RoadmapFileType[]; }; -/** - * Generates id from the given project file - * @param filePath Markdown file path - * - * @returns unique project identifier - */ -function projectPathToId(filePath: string): string { - const fileName = filePath.split('/').pop() || ''; - - return fileName.replace('.md', ''); -} - export async function getProjectsByRoadmapId( roadmapId: string, ): Promise { const projects = await getAllProjects(); return projects.filter((project) => - project.frontmatter?.roadmapIds?.includes(roadmapId), + project.data?.roadmapIds?.includes(roadmapId), ); } @@ -63,26 +26,20 @@ export async function getAllProjects(): Promise { return tempProjects; } - const projects = import.meta.glob( - '/src/data/projects/*.md', - { - eager: true, - }, - ); - - tempProjects = Object.values(projects).map((projectFile) => ({ - ...projectFile, - id: projectPathToId(projectFile.file), - })); - + tempProjects = await getCollection('projects'); return tempProjects; } export async function getProjectById( groupId: string, ): Promise { - const project = await import(`../data/projects/${groupId}.md`); - const roadmapIds = project.frontmatter.roadmapIds || []; + const projects = await getAllProjects(); + const project = projects.find((project) => project.slug === groupId); + if (!project) { + throw new Error(`Project not found with id: ${groupId}`); + } + + const roadmapIds = project.data.roadmapIds || []; const roadmaps = await Promise.all( roadmapIds.map((roadmapId: string) => getRoadmapById(roadmapId)), ); @@ -90,7 +47,6 @@ export async function getProjectById( return { ...project, roadmaps: roadmaps, - id: projectPathToId(project.file), }; } @@ -101,7 +57,7 @@ export async function getRoadmapsProjects(): Promise< const roadmapsProjects: Record = {}; projects.forEach((project) => { - project.frontmatter.roadmapIds.forEach((roadmapId) => { + project.data.roadmapIds.forEach((roadmapId) => { if (!roadmapsProjects[roadmapId]) { roadmapsProjects[roadmapId] = []; } diff --git a/src/lib/video.ts b/src/lib/video.ts index d34e27ab4..e0bba39e1 100644 --- a/src/lib/video.ts +++ b/src/lib/video.ts @@ -44,7 +44,7 @@ export async function getVideosByAuthor( ): Promise { const allVideos = await getAllVideos(); - return allVideos.filter((video) => video.author?.id === authorId); + return allVideos.filter((video) => video.author?.slug === authorId); } /** @@ -63,7 +63,7 @@ export async function getAllVideos(): Promise { ...videoFile, id: videoPathToId(videoFile.file), author: allAuthors.find( - (author) => author.id === videoFile.frontmatter.authorId, + (author) => author.slug === videoFile.frontmatter.authorId, )!, })); diff --git a/src/pages/[roadmapId]/projects.astro b/src/pages/[roadmapId]/projects.astro index 78ed00e9b..061d4e85c 100644 --- a/src/pages/[roadmapId]/projects.astro +++ b/src/pages/[roadmapId]/projects.astro @@ -52,7 +52,7 @@ const nounTitle = const seoDescription = `Seeking ${nounTitle.toLowerCase()} projects to enhance your skills? Explore our top 20 project ideas, from simple apps to complex systems. Start building today!`; const projects = await getProjectsByRoadmapId(roadmapId); -const projectIds = projects.map((project) => project.id); +const projectIds = projects.map((project) => project.slug); const projectApiClient = projectApi(Astro); const { response: userCounts } = diff --git a/src/pages/authors/[authorId].astro b/src/pages/authors/[authorId].astro index 18947fc91..943e760c1 100644 --- a/src/pages/authors/[authorId].astro +++ b/src/pages/authors/[authorId].astro @@ -32,7 +32,7 @@ const videos = await getVideosByAuthor(authorId); --- ({ text: questionGroup.data.briefTitle, - url: `/questions/${questionGroup.id}`, + url: `/questions/${questionGroup.slug}`, isNew: questionGroup.data.isNew, }))} /> diff --git a/src/pages/pages.json.ts b/src/pages/pages.json.ts index 16703b170..2996e7ea3 100644 --- a/src/pages/pages.json.ts +++ b/src/pages/pages.json.ts @@ -34,16 +34,16 @@ export async function GET() { group: 'Best Practices', })), ...questionGroups.map((questionGroup) => ({ - id: questionGroup.id, - url: `/questions/${questionGroup.id}`, + id: questionGroup.slug, + url: `/questions/${questionGroup.slug}`, title: questionGroup.data.briefTitle, group: 'Questions', })), ...guides.map((guide) => ({ - id: guide.id, + id: guide.slug, url: guide.data.excludedBySlug ? guide.data.excludedBySlug - : `/guides/${guide.id}`, + : `/guides/${guide.slug}`, title: guide.data.title, description: guide.data.description, authorId: guide.data.authorId, @@ -56,10 +56,10 @@ export async function GET() { group: 'Videos', })), ...projects.map((project) => ({ - id: project.id, - url: `/projects/${project.id}`, - title: project.frontmatter.title, - description: project.frontmatter.description, + id: project.slug, + url: `/projects/${project.slug}`, + title: project.data.title, + description: project.data.description, group: 'Projects', })), ]), diff --git a/src/pages/projects/[projectId]/index.astro b/src/pages/projects/[projectId]/index.astro index 7a712a729..0c80b7eb5 100644 --- a/src/pages/projects/[projectId]/index.astro +++ b/src/pages/projects/[projectId]/index.astro @@ -1,11 +1,7 @@ --- import BaseLayout from '../../../layouts/BaseLayout.astro'; import { Badge } from '../../../components/Badge'; -import { - getAllProjects, - getProjectById, - type ProjectFrontmatter, -} from '../../../lib/project'; +import { getAllProjects, getProjectById } from '../../../lib/project'; import AstroIcon from '../../../components/AstroIcon.astro'; import { ProjectStepper } from '../../../components/Projects/StatusStepper/ProjectStepper'; import { ProjectTabs } from '../../../components/Projects/ProjectTabs'; @@ -14,7 +10,7 @@ export async function getStaticPaths() { const projects = await getAllProjects(); return projects - .map((project) => project.id) + .map((project) => project.slug) .map((projectId) => ({ params: { projectId }, })); @@ -27,7 +23,8 @@ interface Params extends Record { const { projectId } = Astro.params as Params; const project = await getProjectById(projectId); -const projectData = project.frontmatter as ProjectFrontmatter; +const projectData = project.data; +const { Content } = await project.render(); let jsonLdSchema: any[] = []; @@ -49,7 +46,11 @@ const parentRoadmapId = projectData?.roadmapIds?.[0] || ''; >
- +
- +
project.id) + .map((project) => project.slug) .map((projectId) => ({ params: { projectId }, })); @@ -26,7 +22,7 @@ interface Params extends Record { const { projectId } = Astro.params as Params; const project = await getProjectById(projectId); -const projectData = project.frontmatter as ProjectFrontmatter; +const projectData = project.data; let jsonLdSchema: any[] = []; diff --git a/src/pages/projects/index.astro b/src/pages/projects/index.astro index f0cfe6774..5732cd1f2 100644 --- a/src/pages/projects/index.astro +++ b/src/pages/projects/index.astro @@ -12,7 +12,7 @@ const allRoadmapIds = Object.keys(roadmapProjects); const allRoadmaps = await getRoadmapsByIds(allRoadmapIds); const enrichedRoadmaps = allRoadmaps.map((roadmap) => { const projects = (roadmapProjects[roadmap.id] || []).sort((a, b) => { - return a.frontmatter.sort - b.frontmatter.sort; + return a.data.sort - b.data.sort; }); return { @@ -25,7 +25,7 @@ const enrichedRoadmaps = allRoadmaps.map((roadmap) => { const projectIds = allRoadmapIds .map((id) => roadmapProjects[id]) .flat() - .map((project) => project.id); + .map((project) => project.slug); const projectApiClient = projectApi(Astro); const { response: userCounts } = await projectApiClient.listProjectsUserCount(projectIds); diff --git a/src/pages/questions/[questionGroupId].astro b/src/pages/questions/[questionGroupId].astro index 6ea62c146..0d53541ec 100644 --- a/src/pages/questions/[questionGroupId].astro +++ b/src/pages/questions/[questionGroupId].astro @@ -34,7 +34,7 @@ const { data: frontmatter } = questionGroup; briefTitle={frontmatter.briefTitle} description={frontmatter.seo.description} keywords={frontmatter.seo.keywords} - permalink={`/questions/${questionGroup.id}`} + permalink={`/questions/${questionGroup.slug}`} > { !frontmatter.authorId && (