Add roadmaps page

pull/5424/head
Kamran Ahmed 8 months ago
parent 3479201e20
commit 40c8bfc312
  1. 16
      src/components/FrameRenderer/renderer.ts
  2. 432
      src/components/Roadmaps/RoadmapsPage.tsx
  3. 2
      src/data/roadmaps/aspnet-core/aspnet-core.md
  4. 2
      src/data/roadmaps/cpp/cpp.md
  5. 2
      src/data/roadmaps/datastructures-and-algorithms/datastructures-and-algorithms.md
  6. 11
      src/lib/browser.ts
  7. 391
      src/pages/roadmaps.astro

@ -14,6 +14,7 @@ import type {
import { pageProgressMessage } from '../../stores/page';
import { showLoginPopup } from '../../lib/popup';
import { replaceChildren } from '../../lib/dom.ts';
import {setUrlParams} from "../../lib/browser.ts";
export class Renderer {
resourceId: string;
@ -141,19 +142,8 @@ export class Renderer {
const newJsonFileSlug = newJsonUrl.split('/').pop()?.replace('.json', '');
// Update the URL and attach the new roadmap type
if (window?.history?.pushState) {
const url = new URL(window.location.href);
const type = this.resourceType[0]; // r for roadmap, b for best-practices
url.searchParams.delete(type);
if (newJsonFileSlug !== this.resourceId) {
url.searchParams.set(type, newJsonFileSlug!);
}
window.history.pushState(null, '', url.toString());
}
const type = this.resourceType[0]; // r for roadmap, b for best-practices
setUrlParams({ [type]: newJsonFileSlug! })
this.jsonToSvg(newJsonUrl)?.then(() => {});
}

@ -0,0 +1,432 @@
import { useEffect, useState } from 'react';
import { cn } from '../../lib/classname.ts';
const groupNames = [
'Absolute Beginners',
'Web Development',
'Languages / Platforms',
'Frameworks',
'Mobile Development',
'Databases',
'Computer Science',
'Machine Learning',
'Game Development',
'Design',
'DevOps',
'Blockchain',
'Cyber Security',
];
type AllowGroupNames = (typeof groupNames)[number];
type GroupType = {
group: AllowGroupNames;
roadmaps: {
title: string;
link: string;
type: 'role' | 'skill';
}[];
};
const groups: GroupType[] = [
{
group: 'Absolute Beginners',
roadmaps: [
{
title: 'Frontend Beginner',
link: '/frontend?r=frontend-beginner',
type: 'role',
},
{
title: 'Backend Beginner',
link: '/backend?r=backend-beginner',
type: 'role',
},
{
title: 'DevOps Beginner',
link: '/devops?r=devops-beginner',
type: 'role',
},
{
title: 'Full-Stack Developer',
link: '/fullstack',
type: 'role',
},
],
},
{
group: 'Web Development',
roadmaps: [
{
title: 'Frontend',
link: '/frontend',
type: 'role',
},
{
title: 'Backend',
link: '/backend',
type: 'role',
},
{
title: 'DevOps',
link: '/devops',
type: 'role',
},
{
title: 'Full Stack',
link: '/full-stack',
type: 'role',
},
{
title: 'QA',
link: '/qa',
type: 'role',
},
{
title: 'GraphQL',
link: '/graphql',
type: 'skill',
},
],
},
{
group: 'DevOps',
roadmaps: [
{
title: 'DevOps',
link: '/devops',
type: 'role',
},
{
title: 'Docker',
link: '/docker',
type: 'skill',
},
{
title: 'Kubernetes',
link: '/kubernetes',
type: 'skill',
},
{
title: 'AWS',
link: '/aws',
type: 'skill',
},
],
},
{
group: 'Languages / Platforms',
roadmaps: [
{
title: 'JavaScript',
link: '/javascript',
type: 'skill',
},
{
title: 'TypeScript',
link: '/typescript',
type: 'skill',
},
{
title: 'Node.js',
link: '/nodejs',
type: 'skill',
},
{
title: 'C++',
link: '/cpp',
type: 'skill',
},
{
title: 'Go',
link: '/golang',
type: 'skill',
},
{
title: 'Rust',
link: '/rust',
type: 'skill',
},
{
title: 'Python',
link: '/python',
type: 'skill',
},
{
title: 'Java',
link: '/java',
type: 'skill',
},
{
title: 'SQL',
link: '/sql',
type: 'skill',
},
],
},
{
group: 'Frameworks',
roadmaps: [
{
title: 'React',
link: '/react',
type: 'skill',
},
{
title: 'Vue',
link: '/vue',
type: 'skill',
},
{
title: 'Angular',
link: '/angular',
type: 'skill',
},
{
title: 'Spring Boot',
link: '/spring-boot',
type: 'skill',
},
{
title: 'ASP.NET Core',
link: '/aspnet-core',
type: 'skill',
},
],
},
{
group: 'Mobile Development',
roadmaps: [
{
title: 'React Native',
link: '/react-native',
type: 'role',
},
{
title: 'Flutter',
link: '/flutter',
type: 'role',
},
{
title: 'Android',
link: '/android',
type: 'role',
},
],
},
{
group: 'Databases',
roadmaps: [
{
title: 'PostgreSQL',
link: '/postgresql-dba',
type: 'role',
},
{
title: 'MongoDB',
link: '/mongodb',
type: 'skill',
},
],
},
{
group: 'Computer Science',
roadmaps: [
{
title: 'Computer Science',
link: '/computer-science',
type: 'skill',
},
{
title: 'Data Structures',
link: '/data-structures-and-algorithms',
type: 'skill',
},
{
title: 'System Design',
link: '/system-design',
type: 'skill',
},
{
title: 'Design and Architecture',
link: '/software-design-architecture',
type: 'skill',
},
{
title: 'Software Architect',
link: '/software-architect',
type: 'role',
},
{
title: 'Code Review',
link: '/code-review',
type: 'skill',
},
{
title: 'Technical Writer',
link: '/technical-writer',
type: 'role',
},
],
},
{
group: 'Machine Learning',
roadmaps: [
{
title: 'AI and Data Scientist',
link: '/ai-data-scientist',
type: 'role',
},
{
title: 'MLOps',
link: '/mlops',
type: 'role',
},
{
title: 'Prompt Engineering',
link: '/prompt-engineering',
type: 'skill',
},
],
},
{
group: 'Game Development',
roadmaps: [
{
title: 'Client Side Game Dev.',
link: '/game-developer',
type: 'role',
},
{
title: 'Server Side Game Dev.',
link: '/server-side-game-developer',
type: 'role',
},
],
},
{
group: 'Design',
roadmaps: [
{
title: 'UX Design',
link: '/ux-design',
type: 'role',
},
{
title: 'Design System',
link: '/design-system',
type: 'skill',
},
],
},
{
group: 'Blockchain',
roadmaps: [
{
title: 'Blockchain',
link: '/blockchain',
type: 'role',
},
],
},
{
group: 'Cyber Security',
roadmaps: [
{
title: 'Cyber Security',
link: '/cyber-security',
type: 'role',
},
],
},
];
export function RoadmapsPage() {
const [activeGroup, setActiveGroup] = useState<AllowGroupNames>('');
const [visibleGroups, setVisibleGroups] = useState<GroupType[]>([]);
useEffect(() => {
if (!activeGroup) {
const roleRoadmaps = groups.flatMap((group) =>
group.roadmaps.filter((roadmap) => roadmap.type === 'role'),
);
const skillRoadmaps = groups.flatMap((group) =>
group.roadmaps.filter((roadmap) => roadmap.type === 'skill'),
);
setVisibleGroups([
{
group: 'Role Based Roadmaps',
roadmaps: roleRoadmaps,
},
{
group: 'Skill Based Roadmaps',
roadmaps: skillRoadmaps,
},
]);
} else {
const group = groups.find((group) => group.group === activeGroup);
if (group) {
setVisibleGroups([group]);
}
}
}, [activeGroup]);
return (
<div className="border-t bg-gray-100">
<div className="container flex flex-row gap-4">
<div className="w-[180px] border-r bg-gradient-to-l from-gray-100 pt-6">
<div className="sticky top-10 pb-20">
<div className="grid grid-cols-1">
<button
onClick={() => setActiveGroup('')}
className={cn('border-b py-1.5 pr-3 text-right text-sm', {
'font-bold text-gray-900': activeGroup === '',
})}
>
{' '}
All Roadmaps
</button>
{groups.map((group) => (
<button
className={cn(
'border-b bg-gradient-to-l py-1.5 pr-3 text-right text-sm text-gray-500 hover:from-white hover:text-gray-900',
{
'from-white font-semibold text-gray-900':
activeGroup === group.group,
},
)}
type="button"
onClick={() => setActiveGroup(group.group)}
>
{group.group}
</button>
))}
</div>
</div>
</div>
<div className="flex flex-grow flex-col gap-6 pb-20 pt-8">
{visibleGroups.map((group) => (
<div>
<h2 className="mb-2 text-xs uppercase tracking-wide text-gray-400">
{group.group}
</h2>
<div className="grid grid-cols-3 gap-1.5">
{group.roadmaps.map((roadmap) => (
<a
className="rounded-md border bg-white px-3 py-2 text-left text-sm shadow-sm transition-all hover:border-gray-300 hover:bg-gray-50"
href={roadmap.link}
>
{roadmap.title}
</a>
))}
</div>
</div>
))}
</div>
</div>
</div>
);
}

@ -57,5 +57,5 @@ sitemap:
tags:
- 'roadmap'
- 'main-sitemap'
- 'role-roadmap'
- 'skill-roadmap'
---

@ -52,5 +52,5 @@ sitemap:
tags:
- 'roadmap'
- 'main-sitemap'
- 'role-roadmap'
- 'skill-roadmap'
---

@ -35,5 +35,5 @@ sitemap:
tags:
- 'roadmap'
- 'main-sitemap'
- 'role-roadmap'
- 'skill-roadmap'
---

@ -32,11 +32,20 @@ export function setUrlParams(params: Record<string, string>) {
}
const url = new URL(window.location.href);
let hasUpdatedUrl = false;
for (const [key, value] of Object.entries(params)) {
if (url.searchParams.get(key) === String(value)) {
continue;
}
url.searchParams.delete(key);
url.searchParams.set(key, value);
hasUpdatedUrl = true;
}
window.history.pushState(null, '', url.toString());
if (hasUpdatedUrl) {
window.history.pushState(null, '', url.toString());
}
}

@ -1,340 +1,9 @@
---
import { RoadmapsPage } from '../components/Roadmaps/RoadmapsPage';
import GridItem from '../components/GridItem.astro';
import SimplePageHeader from '../components/SimplePageHeader.astro';
import BaseLayout from '../layouts/BaseLayout.astro';
import { getRoadmapsByTag } from '../lib/roadmap';
const groups = [
{
group: 'Absolute Beginners',
roadmaps: [
{
title: 'Frontend Beginner',
link: '/frontend?r=frontend-beginner',
},
{
title: 'Backend Beginner',
link: '/backend?r=backend-beginner',
},
{
title: 'DevOps Beginner',
link: '/devops?r=devops-beginner',
},
{
title: 'Full-Stack Developer',
link: '/fullstack',
},
],
},
{
group: 'Web Development',
roadmaps: [
{
title: 'Frontend',
link: '/frontend',
type: 'role',
},
{
title: 'Backend',
link: '/backend',
type: 'role',
},
{
title: 'DevOps',
link: '/devops',
type: 'role',
},
{
title: 'Full Stack',
link: '/full-stack',
type: 'role',
},
{
title: 'QA',
link: '/qa',
type: 'role',
},
{
title: 'GraphQL',
link: '/graphql',
type: 'role',
},
],
},
{
group: 'Languages / Platforms',
roadmaps: [
{
title: 'JavaScript',
link: '/javascript',
type: 'skill',
},
{
title: 'TypeScript',
link: '/typescript',
type: 'skill',
},
{
title: 'Node.js',
link: '/nodejs',
type: 'role',
},
{
title: 'C++',
link: '/cpp',
type: 'skill',
},
{
title: 'Go',
link: '/golang',
type: 'skill',
},
{
title: 'Rust',
link: '/rust',
type: 'skill',
},
{
title: 'Python',
link: '/python',
type: 'skill',
},
{
title: 'Java',
link: '/java',
type: 'skill',
},
{
title: 'SQL',
link: '/sql',
type: 'skill',
},
],
},
{
group: 'Frameworks',
roadmaps: [
{
title: 'React',
link: '/react',
type: 'skill',
},
{
title: 'Vue',
link: '/vue',
type: 'skill',
},
{
title: 'Angular',
link: '/angular',
type: 'skill',
},
{
title: 'Spring Boot',
link: '/spring-boot',
type: 'skill',
},
{
title: 'ASP.NET Core',
link: '/aspnet-core',
type: 'skill',
},
],
},
{
group: 'Mobile Development',
roadmaps: [
{
title: 'React Native',
link: '/react-native',
type: 'skill',
},
{
title: 'Flutter',
link: '/flutter',
type: 'skill',
},
{
title: 'Android',
link: '/android',
type: 'skill',
},
],
},
{
group: 'Databases',
roadmaps: [
{
title: 'PostgreSQL',
link: '/postgresql-dba',
type: 'role',
},
{
title: 'MongoDB',
link: '/mongodb',
type: 'skill',
},
],
},
{
group: 'Computer Science',
roadmaps: [
{
title: 'Computer Science',
link: '/computer-science',
type: 'skill',
},
{
title: 'Data Structures',
link: '/data-structures-and-algorithms',
type: 'skill',
},
{
title: 'System Design',
link: '/system-design',
type: 'skill',
},
{
title: 'Design and Architecture',
link: '/software-design-architecture',
type: 'skill',
},
{
title: 'Software Architect',
link: '/software-architect',
type: 'role',
},
{
title: 'Code Review',
link: '/code-review',
type: 'skill',
},
{
title: 'Technical Writer',
link: '/technical-writer',
type: 'skill',
},
],
},
{
group: 'Machine Learning',
roadmaps: [
{
title: 'AI and Data Scientist',
link: '/ai-data-scientist',
type: 'skill',
},
{
title: 'MLOps',
link: '/mlops',
type: 'skill',
},
{
title: 'Prompt Engineering',
link: '/prompt-engineering',
type: 'skill',
},
],
},
{
group: 'Game Development',
roadmaps: [
{
title: 'Client Side Development',
link: '/game-developer',
type: 'skill',
},
{
title: 'Server Side Development',
link: '/server-side-game-developer',
type: 'skill',
},
],
},
{
group: 'Design',
roadmaps: [
{
title: 'UX Design',
link: '/ux-design',
},
{
title: 'Design System',
link: '/design-system',
},
],
},
{
group: 'DevOps',
roadmaps: [
{
title: 'DevOps',
link: '/devops',
},
{
title: 'Docker',
link: '/docker',
},
{
title: 'Kubernetes',
link: '/kubernetes',
},
{
title: 'AWS',
link: '/aws',
},
],
},
{
group: 'Blockchain',
roadmaps: [
{
title: 'Blockchain',
link: '/blockchain',
},
],
},
{
group: 'Cyber Security',
roadmaps: [
{
title: 'Cyber Security',
link: '/cyber-security',
},
],
},
];
const shownTitles = groups
.map((group) => group.roadmaps.map((roadmap) => roadmap.title))
.flat()
.concat([
'Frontend Beginner',
'Backend Beginner',
'DevOps Beginner',
'Full-Stack Developer',
'Data Structures & Algorithms',
'Server Side Game Developer',
'Game Developer',
]);
const roleRoadmaps = (await getRoadmapsByTag('role-roadmap')).filter(
(roadmap) => !shownTitles.includes(roadmap.frontmatter.briefTitle),
);
const skillRoadmaps = (await getRoadmapsByTag('skill-roadmap')).filter(
(roadmap) => !shownTitles.includes(roadmap.frontmatter.briefTitle),
);
const otherRoadmaps = roleRoadmaps.concat(skillRoadmaps);
if (otherRoadmaps.length > 0) {
groups.push({
group: 'Uncategorized',
roadmaps: otherRoadmaps.map((roadmap) => ({
title: roadmap.frontmatter.briefTitle,
link: roadmap.url,
})),
});
}
---
<BaseLayout
@ -347,14 +16,20 @@ if (otherRoadmaps.length > 0) {
<div class='container'>
<div class='flex flex-col items-center bg-white'>
<h1 class='text-5xl font-bold'>Developer Roadmaps</h1>
<p class='text-lg my-3'>
<p class='my-3 text-lg'>
Browse ever-growing list of up-to-date, community driven roadmaps
</p>
<p class="flex flex-row gap-3">
<a class="inline-block bg-black py-1.5 text-base px-3.5 rounded-md text-white" href="#">
<p class='flex flex-row gap-3'>
<a
class='inline-block rounded-md bg-black px-3.5 py-1.5 text-base text-white'
href='#'
>
Draw your own roadmap
</a>
<a class="inline-block bg-gray-300 py-1.5 text-base px-3.5 rounded-md text-black" href="#">
<a
class='inline-block rounded-md bg-gray-300 px-3.5 py-1.5 text-base text-black'
href='#'
>
Generate Roadmap with AI
</a>
</p>
@ -362,48 +37,6 @@ if (otherRoadmaps.length > 0) {
</div>
</div>
<div class='bg-gray-100 border-t'>
<div class='container flex flex-row gap-4'>
<div class='w-[180px] border-r pt-8 bg-gradient-to-l from-gray-100'>
<div class='sticky top-10 pb-20'>
<div class='grid grid-cols-1 gap-1'>
<a class='text-right pr-3 text-sm border-b pb-1 font-bold'> All Roadmaps</a>
{
groups.map((group) => (
<a
class='text-right pr-3 text-sm border-b py-1 text-gray-500 hover:text-gray-900 transition-all'
href={`#${group.group.toLowerCase().replace(' ', '-')}`}
>
{group.group}
</a>
))
}
</div>
</div>
</div>
<div class='flex flex-grow flex-col gap-6 pt-8 pb-20'>
{
groups.map((group) => (
<div>
<h2 class='mb-2 text-xs uppercase tracking-wide text-gray-400'>
{group.group}
</h2>
<div class='grid grid-cols-3 gap-1.5'>
{group.roadmaps.map((roadmap) => (
<a
class='rounded-md border bg-white px-3 py-2 text-left text-sm shadow-sm transition-all hover:border-gray-300 hover:bg-gray-50'
href={roadmap.link}
>
{roadmap.title}
</a>
))}
</div>
</div>
))
}
</div>
</div>
</div>
<RoadmapsPage client:load />
</div>
</BaseLayout>

Loading…
Cancel
Save