diff --git a/src/components/EditorRoadmap/EditorRoadmap.tsx b/src/components/EditorRoadmap/EditorRoadmap.tsx index dc5defaf0..997a78362 100644 --- a/src/components/EditorRoadmap/EditorRoadmap.tsx +++ b/src/components/EditorRoadmap/EditorRoadmap.tsx @@ -23,12 +23,7 @@ type EditorRoadmapProps = { }; export function EditorRoadmap(props: EditorRoadmapProps) { - const { - resourceId, - resourceType = 'roadmap', - dimensions, - hasChat = true, - } = props; + const { resourceId, resourceType = 'roadmap', dimensions, hasChat = true } = props; const [hasSwitchedRoadmap, setHasSwitchedRoadmap] = useState(false); const [isLoading, setIsLoading] = useState(true); diff --git a/src/components/GridItem.astro b/src/components/GridItem.astro index 7a327cf1c..2b80746b4 100644 --- a/src/components/GridItem.astro +++ b/src/components/GridItem.astro @@ -1,4 +1,6 @@ --- +import type { RoadmapFileType } from '../lib/roadmap'; + export interface Props { url: string; title: string; @@ -25,7 +27,7 @@ const { url, title, description, isNew } = Astro.props; { isNew && ( - + diff --git a/src/lib/project.ts b/src/lib/project.ts index 1a16aea66..41cef4841 100644 --- a/src/lib/project.ts +++ b/src/lib/project.ts @@ -1,8 +1,5 @@ -import { - officialRoadmapDetails, - type OfficialRoadmapDocument, -} from '../queries/official-roadmap'; import type { MarkdownFileType } from './file'; +import { getRoadmapById, type RoadmapFileType } from './roadmap'; export const projectDifficulties = [ 'beginner', @@ -31,7 +28,7 @@ export interface ProjectFrontmatter { export type ProjectFileType = MarkdownFileType & { id: string; - roadmaps: OfficialRoadmapDocument[]; + roadmaps: RoadmapFileType[]; }; /** @@ -88,7 +85,7 @@ export async function getProjectById( const project = await import(`../data/projects/${groupId}.md`); const roadmapIds = project.frontmatter.roadmapIds || []; const roadmaps = await Promise.all( - roadmapIds.map((roadmapId: string) => officialRoadmapDetails(roadmapId)), + roadmapIds.map((roadmapId: string) => getRoadmapById(roadmapId)), ); return { diff --git a/src/lib/roadmap.ts b/src/lib/roadmap.ts index 0beb7a18f..c83d9c41c 100644 --- a/src/lib/roadmap.ts +++ b/src/lib/roadmap.ts @@ -1,7 +1,19 @@ import type { PageType } from '../components/CommandMenu/CommandMenu'; +import type { MarkdownFileType } from './file'; import { httpGet } from './http'; import type { ResourceType } from './resource-progress'; +export function resourceTitleFromId(id: string): string { + if (id === 'devops') { + return 'DevOps'; + } + + return id + .split('-') + .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) + .join(' '); +} + export type AllowedRoadmapRenderer = 'balsamiq' | 'editor'; export interface RoadmapFrontmatter { @@ -64,6 +76,99 @@ export interface RoadmapFrontmatter { renderer?: AllowedRoadmapRenderer; } +export type RoadmapFileType = MarkdownFileType & { + id: string; +}; + +function roadmapPathToId(filePath: string): string { + const fileName = filePath.split('/').pop() || ''; + + return fileName.replace('.md', ''); +} + +/** + * Gets the IDs of all the roadmaps available on the website + * + * @returns string[] Array of roadmap IDs + */ +export async function getRoadmapIds() { + const roadmapFiles = import.meta.glob( + '/src/data/roadmaps/*/*.md', + { + eager: true, + }, + ); + + return Object.keys(roadmapFiles).map(roadmapPathToId); +} + +/** + * Gets the roadmap files which have the given tag assigned + * + * @param tag Tag assigned to roadmap + * @returns Promisified RoadmapFileType[] + */ +export async function getRoadmapsByTag( + tag: string, +): Promise { + const roadmapFilesMap = import.meta.glob( + '/src/data/roadmaps/*/*.md', + { + eager: true, + }, + ); + + const roadmapFiles: RoadmapFileType[] = Object.values(roadmapFilesMap); + const filteredRoadmaps = roadmapFiles + .filter((roadmapFile) => roadmapFile.frontmatter.tags?.includes(tag)) + .map((roadmapFile) => ({ + ...roadmapFile, + id: roadmapPathToId(roadmapFile.file), + })); + + return filteredRoadmaps.sort( + (a, b) => a.frontmatter.order - b.frontmatter.order, + ); +} + +export async function getRoadmapById(id: string): Promise { + const roadmapFilesMap: Record = + import.meta.glob('/src/data/roadmaps/*/*.md', { + eager: true, + }); + + const roadmapFile = Object.values(roadmapFilesMap).find((roadmapFile) => { + return roadmapPathToId(roadmapFile.file) === id; + }); + + if (!roadmapFile) { + throw new Error(`Roadmap with ID ${id} not found`); + } + + return { + ...roadmapFile, + id: roadmapPathToId(roadmapFile.file), + }; +} + +export async function getRoadmapsByIds( + ids: string[], +): Promise { + if (!ids?.length) { + return []; + } + + return Promise.all(ids.map((id) => getRoadmapById(id))); +} + +export async function getRoadmapFaqsById(roadmapId: string): Promise { + const { faqs } = await import( + `../data/roadmaps/${roadmapId}/faqs.astro` + ).catch(() => ({})); + + return faqs || []; +} + export async function getResourceMeta( resourceType: ResourceType, resourceId: string, diff --git a/src/pages/404.astro b/src/pages/404.astro index 553778cce..9e4261b86 100644 --- a/src/pages/404.astro +++ b/src/pages/404.astro @@ -1,13 +1,10 @@ --- import Icon from '../components/AstroIcon.astro'; import BaseLayout from '../layouts/BaseLayout.astro'; -import { listOfficialRoadmaps } from '../queries/official-roadmap'; +import { getRoadmapIds } from '../lib/roadmap'; -const roadmapIds = await listOfficialRoadmaps(); -const legacyRoadmapUrls = [ - ...roadmapIds.map((roadmap) => `/${roadmap.slug}/`), - '/roadmaps/', -]; +const roadmapIds = await getRoadmapIds(); +const legacyRoadmapUrls = [...roadmapIds.map((id) => `/${id}/`), '/roadmaps/']; --- @@ -21,26 +18,20 @@ const legacyRoadmapUrls = [
-
+
diff --git a/src/pages/[roadmapId]/courses.astro b/src/pages/[roadmapId]/courses.astro index 17b4514a4..001f62eb7 100644 --- a/src/pages/[roadmapId]/courses.astro +++ b/src/pages/[roadmapId]/courses.astro @@ -1,4 +1,4 @@ - + diff --git a/src/pages/[roadmapId]/projects.astro b/src/pages/[roadmapId]/projects.astro index 8c00615e6..bde9f23e2 100644 --- a/src/pages/[roadmapId]/projects.astro +++ b/src/pages/[roadmapId]/projects.astro @@ -5,19 +5,16 @@ import { ProjectsList } from '../../components/Projects/ProjectsList'; import BaseLayout from '../../layouts/BaseLayout.astro'; import { getProjectsByRoadmapId } from '../../lib/project'; import { getOpenGraphImageUrl } from '../../lib/open-graph'; +import { type RoadmapFrontmatter, getRoadmapIds } from '../../lib/roadmap'; import { projectApi } from '../../api/project'; -import { - listOfficialRoadmaps, - officialRoadmapDetails, -} from '../../queries/official-roadmap'; export const prerender = true; export async function getStaticPaths() { - const roadmapIds = await listOfficialRoadmaps(); + const roadmapIds = await getRoadmapIds(); - return roadmapIds.map((roadmap) => ({ - params: { roadmapId: roadmap.slug }, + return roadmapIds.map((roadmapId) => ({ + params: { roadmapId }, })); } @@ -26,14 +23,15 @@ interface Params extends Record { } const { roadmapId } = Astro.params as Params; -const roadmapData = await officialRoadmapDetails(roadmapId); -if (!roadmapData) { - return Astro.rewrite('/404'); -} +const roadmapFile = await import( + `../../data/roadmaps/${roadmapId}/${roadmapId}.md` +); + +const roadmapData = roadmapFile.frontmatter as RoadmapFrontmatter; // update og for projects const ogImageUrl = - roadmapData?.openGraph?.image || + roadmapData?.seo?.ogImageUrl || getOpenGraphImageUrl({ group: 'roadmap', resourceId: roadmapId, @@ -46,13 +44,13 @@ const descriptionNoun: Record = { 'Product Manager': 'Product Management', }; -const title = `${roadmapData.title.card} Projects`; -const description = `Project ideas to take you from beginner to advanced in ${descriptionNoun[roadmapData.title.card] || roadmapData.title.card}`; +const title = `${roadmapData.briefTitle} Projects`; +const description = `Project ideas to take you from beginner to advanced in ${descriptionNoun[roadmapData.briefTitle] || roadmapData.briefTitle}`; // `Seeking backend projects to enhance your skills? Explore our top 20 project ideas, from simple apps to complex systems. Start building today!` -const seoTitle = `${roadmapData.title.card} Projects`; +const seoTitle = `${roadmapData.briefTitle} Projects`; const nounTitle = - descriptionNoun[roadmapData?.title.card] || roadmapData.title.card; + descriptionNoun[roadmapData?.briefTitle] || roadmapData.briefTitle; 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); @@ -67,7 +65,7 @@ const { response: userCounts } = permalink={`/${roadmapId}/projects`} title={seoTitle} description={seoDescription} - briefTitle={roadmapData.title.card} + briefTitle={roadmapData.briefTitle} ogImageUrl={ogImageUrl} keywords={roadmapData.seo.keywords} noIndex={projects.length === 0} @@ -75,16 +73,15 @@ const { response: userCounts } = resourceType='roadmap' >
- diff --git a/src/pages/[roadmapId]/svg.astro b/src/pages/[roadmapId]/svg.astro index d353d723e..5b508c215 100644 --- a/src/pages/[roadmapId]/svg.astro +++ b/src/pages/[roadmapId]/svg.astro @@ -1,19 +1,17 @@ --- import { EditorRoadmap } from '../../components/EditorRoadmap/EditorRoadmap'; +import FrameRenderer from '../../components/FrameRenderer/FrameRenderer.astro'; import SkeletonLayout from '../../layouts/SkeletonLayout.astro'; import { getOpenGraphImageUrl } from '../../lib/open-graph'; -import { - listOfficialRoadmaps, - officialRoadmapDetails, -} from '../../queries/official-roadmap'; +import { type RoadmapFrontmatter, getRoadmapIds } from '../../lib/roadmap'; export const prerender = true; export async function getStaticPaths() { - const roadmapIds = await listOfficialRoadmaps(); + const roadmapIds = await getRoadmapIds(); - return roadmapIds.map((roadmap) => ({ - params: { roadmapId: roadmap.slug }, + return roadmapIds.map((roadmapId) => ({ + params: { roadmapId }, })); } @@ -22,13 +20,13 @@ interface Params extends Record { } const { roadmapId } = Astro.params as Params; -const roadmapData = await officialRoadmapDetails(roadmapId); -if (!roadmapData) { - return Astro.rewrite('/404'); -} +const roadmapFile = await import( + `../../data/roadmaps/${roadmapId}/${roadmapId}.md` +); +const roadmapData = roadmapFile.frontmatter as RoadmapFrontmatter; const ogImageUrl = - roadmapData?.openGraph?.image || + roadmapData?.seo?.ogImageUrl || getOpenGraphImageUrl({ group: 'roadmap', resourceId: roadmapId, @@ -37,8 +35,8 @@ const ogImageUrl = -
- +
+ { + roadmapData?.renderer === 'editor' ? ( + + ) : ( + + ) + }
diff --git a/src/pages/dashboard.astro b/src/pages/dashboard.astro index 88af1687a..08fdffa52 100644 --- a/src/pages/dashboard.astro +++ b/src/pages/dashboard.astro @@ -1,53 +1,56 @@ --- -import { DateTime } from 'luxon'; import { DashboardPage } from '../components/Dashboard/DashboardPage'; import BaseLayout from '../layouts/BaseLayout.astro'; import { getAllBestPractices } from '../lib/best-practice'; import { getAllQuestionGroups } from '../lib/question-group'; +import { getRoadmapsByTag } from '../lib/roadmap'; import { getAllVideos } from '../lib/video'; import { listOfficialGuides } from '../queries/official-guide'; -import { - isNewRoadmap, - listOfficialRoadmaps, -} from '../queries/official-roadmap'; -import type { BuiltInRoadmap } from '../components/Dashboard/PersonalDashboard'; -const roadmaps = await listOfficialRoadmaps(); -const roleRoadmaps = roadmaps.filter((roadmap) => roadmap.type === 'role'); -const skillRoadmaps = roadmaps.filter((roadmap) => roadmap.type === 'skill'); +const roleRoadmaps = await getRoadmapsByTag('role-roadmap'); +const skillRoadmaps = await getRoadmapsByTag('skill-roadmap'); const bestPractices = await getAllBestPractices(); const questionGroups = await getAllQuestionGroups(); const guides = await listOfficialGuides(); const videos = await getAllVideos(); -const enrichedRoleRoadmaps: BuiltInRoadmap[] = roleRoadmaps.map((roadmap) => { - return { - id: roadmap.slug, - url: `/${roadmap.slug}`, - title: roadmap.title.card, - description: roadmap.description, - relatedRoadmapIds: roadmap.relatedRoadmaps, - renderer: 'editor', - isNew: isNewRoadmap(roadmap.createdAt), - metadata: { - tags: ['role-roadmap'], - }, - }; -}); -const enrichedSkillRoadmaps: BuiltInRoadmap[] = skillRoadmaps.map((roadmap) => { - return { - id: roadmap.slug, - url: `/${roadmap.slug}`, - title: roadmap.title.card === 'Go' ? 'Go Roadmap' : roadmap.title.card, - description: roadmap.description, - relatedRoadmapIds: roadmap.relatedRoadmaps, - renderer: 'editor', - isNew: isNewRoadmap(roadmap.createdAt), - metadata: { - tags: ['skill-roadmap'], - }, - }; -}); +const enrichedRoleRoadmaps = roleRoadmaps + .filter((roadmapItem) => !roadmapItem.frontmatter.isHidden) + .map((roadmap) => { + const { frontmatter } = roadmap; + + return { + id: roadmap.id, + url: `/${roadmap.id}`, + title: frontmatter.briefTitle, + description: frontmatter.briefDescription, + relatedRoadmapIds: frontmatter.relatedRoadmaps, + renderer: frontmatter.renderer, + isNew: frontmatter.isNew, + metadata: { + tags: frontmatter.tags, + }, + }; + }); +const enrichedSkillRoadmaps = skillRoadmaps + .filter((roadmapItem) => !roadmapItem.frontmatter.isHidden) + .map((roadmap) => { + const { frontmatter } = roadmap; + + return { + id: roadmap.id, + url: `/${roadmap.id}`, + title: + frontmatter.briefTitle === 'Go' ? 'Go Roadmap' : frontmatter.briefTitle, + description: frontmatter.briefDescription, + relatedRoadmapIds: frontmatter.relatedRoadmaps, + renderer: frontmatter.renderer, + isNew: frontmatter.isNew, + metadata: { + tags: frontmatter.tags, + }, + }; + }); const enrichedBestPractices = bestPractices.map((bestPractice) => { const { frontmatter } = bestPractice; diff --git a/src/pages/index.astro b/src/pages/index.astro index 658bd2677..bbbd2aab8 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,5 +1,4 @@ --- -import { DateTime } from 'luxon'; import ChangelogBanner from '../components/ChangelogBanner.astro'; import { FeaturedGuideList } from '../components/FeaturedGuides/FeaturedGuideList'; import FeaturedItems from '../components/FeaturedItems/FeaturedItems.astro'; @@ -7,16 +6,12 @@ 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 { getRoadmapsByTag } from '../lib/roadmap'; import { getAllVideos } from '../lib/video'; import { listOfficialGuides } from '../queries/official-guide'; -import { - isNewRoadmap, - listOfficialRoadmaps, -} from '../queries/official-roadmap'; -const roadmaps = await listOfficialRoadmaps(); -const roleRoadmaps = roadmaps.filter((roadmap) => roadmap.type === 'role'); -const skillRoadmaps = roadmaps.filter((roadmap) => roadmap.type === 'skill'); +const roleRoadmaps = await getRoadmapsByTag('role-roadmap'); +const skillRoadmaps = await getRoadmapsByTag('skill-roadmap'); const bestPractices = await getAllBestPractices(); export const projectGroups = [ @@ -52,32 +47,33 @@ const videos = await getAllVideos(); { - const isNew = isNewRoadmap(roadmapItem.createdAt); - - return { - text: roadmapItem.title.card, - url: `/${roadmapItem.slug}`, - isNew, - }; - })} + featuredItems={roleRoadmaps + .filter((roadmapItem) => !roadmapItem.frontmatter.isHidden) + .map((roadmapItem) => ({ + text: roadmapItem.frontmatter.briefTitle, + url: `/${roadmapItem.id}`, + isNew: roadmapItem.frontmatter.isNew, + isUpcoming: roadmapItem.frontmatter.isUpcoming, + }))} showCreateRoadmap={true} /> { - const isNew = isNewRoadmap(roadmapItem.createdAt); - - return { + featuredItems={skillRoadmaps + .filter((roadmapItem) => !roadmapItem.frontmatter.isHidden) + .map((roadmapItem) => ({ text: - roadmapItem.title.card === 'Go' + roadmapItem.frontmatter.briefTitle === 'Go' ? 'Go Roadmap' - : roadmapItem.title.card.replace('Software Design', 'Design'), - url: `/${roadmapItem.slug}`, - isNew, - }; - })} + : roadmapItem.frontmatter.briefTitle.replace( + 'Software Design', + 'Design', + ), + url: `/${roadmapItem.id}`, + isNew: roadmapItem.frontmatter.isNew, + isUpcoming: roadmapItem.frontmatter.isUpcoming, + }))} showCreateRoadmap={true} /> diff --git a/src/pages/pages.json.ts b/src/pages/pages.json.ts index eec165088..1819f45b5 100644 --- a/src/pages/pages.json.ts +++ b/src/pages/pages.json.ts @@ -1,4 +1,5 @@ import { getAllBestPractices } from '../lib/best-practice'; +import { getRoadmapsByTag } from '../lib/roadmap'; import { getAllVideos } from '../lib/video'; import { getAllQuestionGroups } from '../lib/question-group'; import { getAllProjects } from '../lib/project'; @@ -6,7 +7,6 @@ import { listOfficialAuthors, listOfficialGuides, } from '../queries/official-guide'; -import { listOfficialRoadmaps } from '../queries/official-roadmap'; // Add utility to fetch beginner roadmap file IDs function getBeginnerRoadmapIds() { @@ -25,49 +25,40 @@ export async function GET() { const authors = await listOfficialAuthors(); const videos = await getAllVideos(); const questionGroups = await getAllQuestionGroups(); - const roadmaps = await listOfficialRoadmaps(); - + const roadmaps = await getRoadmapsByTag('roadmap'); const bestPractices = await getAllBestPractices(); const projects = await getAllProjects(); // Transform main roadmaps into page objects first so that we can reuse their meta for beginner variants - const roadmapPages = roadmaps - .map((roadmap) => { - const isBeginner = roadmap.slug.endsWith('-beginner'); - if (!isBeginner) { - return { - id: roadmap.slug, - url: `/${roadmap.slug}`, - title: roadmap.title.card, - shortTitle: roadmap.title.card, - description: roadmap.description, - group: 'Roadmaps', - metadata: { - tags: - roadmap.type === 'role' ? ['role-roadmap'] : ['skill-roadmap'], - }, - renderer: 'editor', - }; - } + const roadmapPages = roadmaps.map((roadmap) => ({ + id: roadmap.id, + url: `/${roadmap.id}`, + title: roadmap.frontmatter.briefTitle, + shortTitle: roadmap.frontmatter.title, + description: roadmap.frontmatter.briefDescription, + group: 'Roadmaps', + metadata: { + tags: roadmap.frontmatter.tags, + }, + renderer: roadmap?.frontmatter?.renderer || 'balsamiq', + })); - const parentSlug = roadmap.slug.replace('-beginner', ''); - const parentMeta = roadmaps.find((r) => r.slug === parentSlug); + // Generate beginner roadmap page objects + const beginnerRoadmapPages = getBeginnerRoadmapIds() + .map((beginnerId) => { + const parentId = beginnerId.replace('-beginner', ''); + const parentMeta = roadmapPages.find((page) => page.id === parentId); if (!parentMeta) { return null; } return { - id: roadmap.slug, - url: `/${parentSlug}?r=${roadmap.slug}`, - title: `${parentMeta.title.page} Beginner`, - shortTitle: `${parentMeta.title.page} Beginner`, - description: parentMeta.description, - group: 'Roadmaps', - metadata: { - tags: ['beginner-roadmap'], - }, - renderer: 'editor', + ...parentMeta, + id: beginnerId, + url: `/${parentId}?r=${beginnerId}`, + title: `${parentMeta.title} Beginner`, + shortTitle: `${parentMeta.shortTitle} Beginner`, }; }) .filter(Boolean); @@ -75,6 +66,7 @@ export async function GET() { return new Response( JSON.stringify([ ...roadmapPages, + ...beginnerRoadmapPages, ...bestPractices.map((bestPractice) => ({ id: bestPractice.id, url: `/best-practices/${bestPractice.id}`, diff --git a/src/pages/projects/index.astro b/src/pages/projects/index.astro index 68f08a2a4..83dc0042f 100644 --- a/src/pages/projects/index.astro +++ b/src/pages/projects/index.astro @@ -1,27 +1,23 @@ --- import BaseLayout from '../../layouts/BaseLayout.astro'; import { getRoadmapsProjects } from '../../lib/project'; +import { getRoadmapsByIds } from '../../lib/roadmap'; import { ProjectsPageHeader } from '../../components/Projects/ProjectsPageHeader'; import { ProjectsPage } from '../../components/Projects/ProjectsPage'; import { projectApi } from '../../api/project'; -import { listOfficialRoadmaps } from '../../queries/official-roadmap'; const roadmapProjects = await getRoadmapsProjects(); const allRoadmapIds = Object.keys(roadmapProjects); -const roadmaps = await listOfficialRoadmaps(); -const allRoadmaps = roadmaps.filter((roadmap) => - allRoadmapIds.includes(roadmap.slug), -); - +const allRoadmaps = await getRoadmapsByIds(allRoadmapIds); const enrichedRoadmaps = allRoadmaps.map((roadmap) => { - const projects = (roadmapProjects[roadmap.slug] || []).sort((a, b) => { + const projects = (roadmapProjects[roadmap.id] || []).sort((a, b) => { return a.frontmatter.sort - b.frontmatter.sort; }); return { - id: roadmap.slug, - title: roadmap.title.card, + id: roadmap.id, + title: roadmap.frontmatter.briefTitle, projects, }; }); @@ -46,5 +42,5 @@ const { response: userCounts } = userCounts={userCounts || {}} client:load /> -
+
diff --git a/src/pages/roadmaps.astro b/src/pages/roadmaps.astro index a5b202f95..c0f4db6be 100644 --- a/src/pages/roadmaps.astro +++ b/src/pages/roadmaps.astro @@ -1,7 +1,10 @@ --- import { RoadmapsPage } from '../components/Roadmaps/RoadmapsPage'; import { RoadmapsPageHeader } from '../components/Roadmaps/RoadmapsPageHeader'; +import GridItem from '../components/GridItem.astro'; +import SimplePageHeader from '../components/SimplePageHeader.astro'; import BaseLayout from '../layouts/BaseLayout.astro'; +import { getRoadmapsByTag } from '../lib/roadmap'; import ChangelogBanner from '../components/ChangelogBanner.astro'; --- diff --git a/src/queries/official-roadmap.ts b/src/queries/official-roadmap.ts index 89a2138c1..cbdc4f193 100644 --- a/src/queries/official-roadmap.ts +++ b/src/queries/official-roadmap.ts @@ -1,7 +1,6 @@ import { queryOptions } from '@tanstack/react-query'; import { FetchError, httpGet } from '../lib/query-http'; import type { Node, Edge } from '@roadmapsh/editor'; -import { DateTime } from 'luxon'; export const allowedOfficialRoadmapType = ['skill', 'role'] as const; export type AllowedOfficialRoadmapType = @@ -104,11 +103,3 @@ export async function listOfficialRoadmaps() { throw error; } } - -export function isNewRoadmap(createdAt: Date) { - return ( - createdAt && - DateTime.now().diff(DateTime.fromJSDate(new Date(createdAt)), 'days').days < - 45 - ); -}