Refactor roadmap page logic

pull/936/head
Kamran Ahmed 3 years ago
parent bf56db60bc
commit 098303b78b
  1. 50
      components/roadmap/new-alert-banner.tsx
  2. 48
      components/roadmap/roadmap-page-header.tsx
  3. 260
      content/roadmaps/100-frontend/content-paths.json
  4. 1
      lib/roadmap.ts
  5. 107
      pages/[roadmap]/index.tsx
  6. 55
      pages/[roadmap]/interactive.tsx
  7. 38
      pages/[roadmap]/resources.tsx
  8. 2
      public/sitemap.xml
  9. 9
      scripts/content-skeleton.ts

@ -0,0 +1,50 @@
import { Badge, Link, Text } from '@chakra-ui/react';
import siteConfig from '../../content/site.json';
import { event } from '../../lib/gtag';
import React from 'react';
export function NewAlertBanner() {
return (
<Text
_hover={{
textDecoration: 'none',
color: 'blue.700',
'& .new-badge': { bg: 'blue.700' },
}}
as={Link}
href={siteConfig.url.youtube}
d="block"
target="_blank"
color="red.700"
fontSize="sm"
mb="10px"
fontWeight={500}
onClick={() =>
event({
category: 'Subscription',
action: 'Clicked the YouTube banner',
label: 'YouTube Alert on Roadmap',
})
}
>
<Badge
transition={'all 300ms'}
className="new-badge"
mr="7px"
colorScheme="red"
variant="solid"
>
New
</Badge>
<Text textDecoration="underline" as="span" d={['none', 'inline']}>
Roadmap topics to be covered on our YouTube Channel
</Text>
<Text textDecoration="underline" as="span" d={['inline', 'none']}>
Topic videos being made on YouTube
</Text>
<Text as="span" ml="5px">
&raquo;
</Text>
</Text>
);
}

@ -0,0 +1,48 @@
import { RoadmapType } from '../../lib/roadmap';
import { NewAlertBanner } from './new-alert-banner';
import { Button, Link, Stack, Text } from '@chakra-ui/react';
import { AtSignIcon, DownloadIcon } from '@chakra-ui/icons';
import { PageHeader } from '../page-header';
import React from 'react';
type RoadmapPageHeaderType = {
roadmap: RoadmapType;
}
export function RoadmapPageHeader(props: RoadmapPageHeaderType) {
const { roadmap } = props;
return (
<PageHeader
beforeTitle={<NewAlertBanner />}
title={roadmap.title}
subtitle={roadmap.description}
>
<Stack mt='20px' isInline>
<Button d={['flex', 'flex']} as={Link} href={'/roadmaps'} size='xs' py='14px' px='10px'
colorScheme='teal' variant='solid' _hover={{ textDecoration: 'none' }}>
&larr; <Text as='span' d={['none', 'inline']} ml='5px'>All Roadmaps</Text>
</Button>
{roadmap.pdfUrl && (
<Button as={Link}
href={roadmap.pdfUrl}
target='_blank'
size='xs'
py='14px'
px='10px'
leftIcon={<DownloadIcon />}
colorScheme='yellow'
variant='solid'
_hover={{ textDecoration: 'none' }}>
Download
</Button>
)}
<Button as={Link} href={'/signup'} size='xs' py='14px' px='10px' leftIcon={<AtSignIcon />}
colorScheme='yellow' variant='solid' _hover={{ textDecoration: 'none' }}>
Subscribe
</Button>
</Stack>
</PageHeader>
);
}

@ -1,132 +1,132 @@
{ {
"home": "/100-frontend/content/readme.md", "home": "/roadmaps/100-frontend/content/readme.md",
"internet": "/100-frontend/content/100-internet/readme.md", "internet": "/roadmaps/100-frontend/content/100-internet/readme.md",
"internet:how-does-the-internet-work": "/100-frontend/content/100-internet/100-how-does-the-internet-work.md", "internet:how-does-the-internet-work": "/roadmaps/100-frontend/content/100-internet/100-how-does-the-internet-work.md",
"internet:what-is-http": "/100-frontend/content/100-internet/101-what-is-http.md", "internet:what-is-http": "/roadmaps/100-frontend/content/100-internet/101-what-is-http.md",
"internet:browsers-and-how-they-work": "/100-frontend/content/100-internet/102-browsers-and-how-they-work.md", "internet:browsers-and-how-they-work": "/roadmaps/100-frontend/content/100-internet/102-browsers-and-how-they-work.md",
"internet:dns-and-how-it-works": "/100-frontend/content/100-internet/103-dns-and-how-it-works.md", "internet:dns-and-how-it-works": "/roadmaps/100-frontend/content/100-internet/103-dns-and-how-it-works.md",
"internet:what-is-domain-name": "/100-frontend/content/100-internet/104-what-is-domain-name.md", "internet:what-is-domain-name": "/roadmaps/100-frontend/content/100-internet/104-what-is-domain-name.md",
"internet:what-is-hosting": "/100-frontend/content/100-internet/105-what-is-hosting.md", "internet:what-is-hosting": "/roadmaps/100-frontend/content/100-internet/105-what-is-hosting.md",
"html": "/100-frontend/content/101-html/readme.md", "html": "/roadmaps/100-frontend/content/101-html/readme.md",
"html:learn-the-basics": "/100-frontend/content/101-html/100-learn-the-basics.md", "html:learn-the-basics": "/roadmaps/100-frontend/content/101-html/100-learn-the-basics.md",
"html:writing-semantic-html": "/100-frontend/content/101-html/101-writing-semantic-html.md", "html:writing-semantic-html": "/roadmaps/100-frontend/content/101-html/101-writing-semantic-html.md",
"html:forms-and-validations": "/100-frontend/content/101-html/102-forms-and-validations.md", "html:forms-and-validations": "/roadmaps/100-frontend/content/101-html/102-forms-and-validations.md",
"html:conventions-and-best-practices": "/100-frontend/content/101-html/103-conventions-and-best-practices.md", "html:conventions-and-best-practices": "/roadmaps/100-frontend/content/101-html/103-conventions-and-best-practices.md",
"html:accessibility": "/100-frontend/content/101-html/104-accessibility.md", "html:accessibility": "/roadmaps/100-frontend/content/101-html/104-accessibility.md",
"html:seo-basics": "/100-frontend/content/101-html/105-seo-basics.md", "html:seo-basics": "/roadmaps/100-frontend/content/101-html/105-seo-basics.md",
"css": "/100-frontend/content/102-css/readme.md", "css": "/roadmaps/100-frontend/content/102-css/readme.md",
"css:learn-the-basics": "/100-frontend/content/102-css/100-learn-the-basics.md", "css:learn-the-basics": "/roadmaps/100-frontend/content/102-css/100-learn-the-basics.md",
"css:making-layouts": "/100-frontend/content/102-css/101-making-layouts.md", "css:making-layouts": "/roadmaps/100-frontend/content/102-css/101-making-layouts.md",
"css:responsive-design-and-media-queries": "/100-frontend/content/102-css/102-responsive-design-and-media-queries.md", "css:responsive-design-and-media-queries": "/roadmaps/100-frontend/content/102-css/102-responsive-design-and-media-queries.md",
"javascript": "/100-frontend/content/103-javascript/readme.md", "javascript": "/roadmaps/100-frontend/content/103-javascript/readme.md",
"javascript:syntax-and-basic-constructs": "/100-frontend/content/103-javascript/100-syntax-and-basic-constructs.md", "javascript:syntax-and-basic-constructs": "/roadmaps/100-frontend/content/103-javascript/100-syntax-and-basic-constructs.md",
"javascript:learn-dom-manipulation": "/100-frontend/content/103-javascript/101-learn-dom-manipulation.md", "javascript:learn-dom-manipulation": "/roadmaps/100-frontend/content/103-javascript/101-learn-dom-manipulation.md",
"javascript:learn-fetch-api-ajax-xhr": "/100-frontend/content/103-javascript/102-learn-fetch-api-ajax-xhr.md", "javascript:learn-fetch-api-ajax-xhr": "/roadmaps/100-frontend/content/103-javascript/102-learn-fetch-api-ajax-xhr.md",
"javascript:es6-and-modular-javascript": "/100-frontend/content/103-javascript/103-es6-and-modular-javascript.md", "javascript:es6-and-modular-javascript": "/roadmaps/100-frontend/content/103-javascript/103-es6-and-modular-javascript.md",
"javascript:concepts": "/100-frontend/content/103-javascript/104-concepts.md", "javascript:concepts": "/roadmaps/100-frontend/content/103-javascript/104-concepts.md",
"version-control-systems": "/100-frontend/content/104-version-control-systems/readme.md", "version-control-systems": "/roadmaps/100-frontend/content/104-version-control-systems/readme.md",
"version-control-systems:basic-usage-of-git": "/100-frontend/content/104-version-control-systems/100-basic-usage-of-git.md", "version-control-systems:basic-usage-of-git": "/roadmaps/100-frontend/content/104-version-control-systems/100-basic-usage-of-git.md",
"repo-hosting-services": "/100-frontend/content/105-repo-hosting-services/readme.md", "repo-hosting-services": "/roadmaps/100-frontend/content/105-repo-hosting-services/readme.md",
"repo-hosting-services:github": "/100-frontend/content/105-repo-hosting-services/100-github.md", "repo-hosting-services:github": "/roadmaps/100-frontend/content/105-repo-hosting-services/100-github.md",
"repo-hosting-services:gitlab": "/100-frontend/content/105-repo-hosting-services/101-gitlab.md", "repo-hosting-services:gitlab": "/roadmaps/100-frontend/content/105-repo-hosting-services/101-gitlab.md",
"repo-hosting-services:bitbucket": "/100-frontend/content/105-repo-hosting-services/102-bitbucket.md", "repo-hosting-services:bitbucket": "/roadmaps/100-frontend/content/105-repo-hosting-services/102-bitbucket.md",
"web-security-knowledge": "/100-frontend/content/106-web-security-knowledge/readme.md", "web-security-knowledge": "/roadmaps/100-frontend/content/106-web-security-knowledge/readme.md",
"web-security-knowledge:cors": "/100-frontend/content/106-web-security-knowledge/102-cors.md", "web-security-knowledge:cors": "/roadmaps/100-frontend/content/106-web-security-knowledge/102-cors.md",
"web-security-knowledge:https": "/100-frontend/content/106-web-security-knowledge/100-https.md", "web-security-knowledge:https": "/roadmaps/100-frontend/content/106-web-security-knowledge/100-https.md",
"web-security-knowledge:content-security-policy": "/100-frontend/content/106-web-security-knowledge/101-content-security-policy.md", "web-security-knowledge:content-security-policy": "/roadmaps/100-frontend/content/106-web-security-knowledge/101-content-security-policy.md",
"web-security-knowledge:owasp-security-risks": "/100-frontend/content/106-web-security-knowledge/103-owasp-security-risks.md", "web-security-knowledge:owasp-security-risks": "/roadmaps/100-frontend/content/106-web-security-knowledge/103-owasp-security-risks.md",
"package-managers": "/100-frontend/content/107-package-managers/readme.md", "package-managers": "/roadmaps/100-frontend/content/107-package-managers/readme.md",
"package-managers:npm": "/100-frontend/content/107-package-managers/100-npm.md", "package-managers:npm": "/roadmaps/100-frontend/content/107-package-managers/100-npm.md",
"package-managers:yarn": "/100-frontend/content/107-package-managers/101-yarn.md", "package-managers:yarn": "/roadmaps/100-frontend/content/107-package-managers/101-yarn.md",
"css-architecture": "/100-frontend/content/108-css-architecture/readme.md", "css-architecture": "/roadmaps/100-frontend/content/108-css-architecture/readme.md",
"css-architecture:bem": "/100-frontend/content/108-css-architecture/100-bem.md", "css-architecture:bem": "/roadmaps/100-frontend/content/108-css-architecture/100-bem.md",
"css-architecture:oocss": "/100-frontend/content/108-css-architecture/101-oocss.md", "css-architecture:oocss": "/roadmaps/100-frontend/content/108-css-architecture/101-oocss.md",
"css-architecture:smacss": "/100-frontend/content/108-css-architecture/102-smacss.md", "css-architecture:smacss": "/roadmaps/100-frontend/content/108-css-architecture/102-smacss.md",
"css-preprocessors": "/100-frontend/content/109-css-preprocessors/readme.md", "css-preprocessors": "/roadmaps/100-frontend/content/109-css-preprocessors/readme.md",
"css-preprocessors:sass": "/100-frontend/content/109-css-preprocessors/100-sass.md", "css-preprocessors:sass": "/roadmaps/100-frontend/content/109-css-preprocessors/100-sass.md",
"css-preprocessors:postcss": "/100-frontend/content/109-css-preprocessors/101-postcss.md", "css-preprocessors:postcss": "/roadmaps/100-frontend/content/109-css-preprocessors/101-postcss.md",
"css-preprocessors:less": "/100-frontend/content/109-css-preprocessors/102-less.md", "css-preprocessors:less": "/roadmaps/100-frontend/content/109-css-preprocessors/102-less.md",
"build-tools": "/100-frontend/content/110-build-tools/readme.md", "build-tools": "/roadmaps/100-frontend/content/110-build-tools/readme.md",
"build-tools:task-runners": "/100-frontend/content/110-build-tools/100-task-runners/readme.md", "build-tools:task-runners": "/roadmaps/100-frontend/content/110-build-tools/100-task-runners/readme.md",
"build-tools:100-task-runners/npm-scripts": "/100-frontend/content/110-build-tools/100-task-runners/npm-scripts.md", "build-tools:100-task-runners/npm-scripts": "/roadmaps/100-frontend/content/110-build-tools/100-task-runners/npm-scripts.md",
"build-tools:linters-formatters": "/100-frontend/content/110-build-tools/102-linters-formatters/readme.md", "build-tools:linters-formatters": "/roadmaps/100-frontend/content/110-build-tools/102-linters-formatters/readme.md",
"build-tools:102-linters-formatters/prettier": "/100-frontend/content/110-build-tools/102-linters-formatters/prettier.md", "build-tools:102-linters-formatters/prettier": "/roadmaps/100-frontend/content/110-build-tools/102-linters-formatters/prettier.md",
"build-tools:102-linters-formatters/eslint": "/100-frontend/content/110-build-tools/102-linters-formatters/eslint.md", "build-tools:102-linters-formatters/eslint": "/roadmaps/100-frontend/content/110-build-tools/102-linters-formatters/eslint.md",
"build-tools:102-linters-formatters/standardjs": "/100-frontend/content/110-build-tools/102-linters-formatters/standardjs.md", "build-tools:102-linters-formatters/standardjs": "/roadmaps/100-frontend/content/110-build-tools/102-linters-formatters/standardjs.md",
"build-tools:module-bundlers": "/100-frontend/content/110-build-tools/101-module-bundlers/readme.md", "build-tools:module-bundlers": "/roadmaps/100-frontend/content/110-build-tools/101-module-bundlers/readme.md",
"build-tools:101-module-bundlers/webpack": "/100-frontend/content/110-build-tools/101-module-bundlers/webpack.md", "build-tools:101-module-bundlers/webpack": "/roadmaps/100-frontend/content/110-build-tools/101-module-bundlers/webpack.md",
"build-tools:101-module-bundlers/esbuild": "/100-frontend/content/110-build-tools/101-module-bundlers/esbuild.md", "build-tools:101-module-bundlers/esbuild": "/roadmaps/100-frontend/content/110-build-tools/101-module-bundlers/esbuild.md",
"build-tools:101-module-bundlers/rollup": "/100-frontend/content/110-build-tools/101-module-bundlers/rollup.md", "build-tools:101-module-bundlers/rollup": "/roadmaps/100-frontend/content/110-build-tools/101-module-bundlers/rollup.md",
"build-tools:101-module-bundlers/parcel": "/100-frontend/content/110-build-tools/101-module-bundlers/parcel.md", "build-tools:101-module-bundlers/parcel": "/roadmaps/100-frontend/content/110-build-tools/101-module-bundlers/parcel.md",
"build-tools:101-module-bundlers/vite": "/100-frontend/content/110-build-tools/101-module-bundlers/vite.md", "build-tools:101-module-bundlers/vite": "/roadmaps/100-frontend/content/110-build-tools/101-module-bundlers/vite.md",
"pick-a-framework": "/100-frontend/content/111-pick-a-framework/readme.md", "pick-a-framework": "/roadmaps/100-frontend/content/111-pick-a-framework/readme.md",
"pick-a-framework:react-js": "/100-frontend/content/111-pick-a-framework/100-react-js/readme.md", "pick-a-framework:react-js": "/roadmaps/100-frontend/content/111-pick-a-framework/100-react-js/readme.md",
"pick-a-framework:100-react-js/recoil": "/100-frontend/content/111-pick-a-framework/100-react-js/recoil.md", "pick-a-framework:100-react-js/recoil": "/roadmaps/100-frontend/content/111-pick-a-framework/100-react-js/recoil.md",
"pick-a-framework:100-react-js/redux": "/100-frontend/content/111-pick-a-framework/100-react-js/redux.md", "pick-a-framework:100-react-js/redux": "/roadmaps/100-frontend/content/111-pick-a-framework/100-react-js/redux.md",
"pick-a-framework:100-react-js/mobx": "/100-frontend/content/111-pick-a-framework/100-react-js/mobx.md", "pick-a-framework:100-react-js/mobx": "/roadmaps/100-frontend/content/111-pick-a-framework/100-react-js/mobx.md",
"pick-a-framework:angular": "/100-frontend/content/111-pick-a-framework/101-angular/readme.md", "pick-a-framework:angular": "/roadmaps/100-frontend/content/111-pick-a-framework/101-angular/readme.md",
"pick-a-framework:101-angular/rxjs": "/100-frontend/content/111-pick-a-framework/101-angular/rxjs.md", "pick-a-framework:101-angular/rxjs": "/roadmaps/100-frontend/content/111-pick-a-framework/101-angular/rxjs.md",
"pick-a-framework:101-angular/ngrx": "/100-frontend/content/111-pick-a-framework/101-angular/ngrx.md", "pick-a-framework:101-angular/ngrx": "/roadmaps/100-frontend/content/111-pick-a-framework/101-angular/ngrx.md",
"pick-a-framework:vue-js": "/100-frontend/content/111-pick-a-framework/102-vue-js/readme.md", "pick-a-framework:vue-js": "/roadmaps/100-frontend/content/111-pick-a-framework/102-vue-js/readme.md",
"pick-a-framework:102-vue-js/vuex": "/100-frontend/content/111-pick-a-framework/102-vue-js/vuex.md", "pick-a-framework:102-vue-js/vuex": "/roadmaps/100-frontend/content/111-pick-a-framework/102-vue-js/vuex.md",
"modern-css": "/100-frontend/content/112-modern-css/readme.md", "modern-css": "/roadmaps/100-frontend/content/112-modern-css/readme.md",
"modern-css:styled-components": "/100-frontend/content/112-modern-css/100-styled-components.md", "modern-css:styled-components": "/roadmaps/100-frontend/content/112-modern-css/100-styled-components.md",
"modern-css:css-modules": "/100-frontend/content/112-modern-css/101-css-modules.md", "modern-css:css-modules": "/roadmaps/100-frontend/content/112-modern-css/101-css-modules.md",
"modern-css:styled-jsx": "/100-frontend/content/112-modern-css/102-styled-jsx.md", "modern-css:styled-jsx": "/roadmaps/100-frontend/content/112-modern-css/102-styled-jsx.md",
"modern-css:emotion": "/100-frontend/content/112-modern-css/103-emotion.md", "modern-css:emotion": "/roadmaps/100-frontend/content/112-modern-css/103-emotion.md",
"web-components": "/100-frontend/content/113-web-components/readme.md", "web-components": "/roadmaps/100-frontend/content/113-web-components/readme.md",
"web-components:html-templates": "/100-frontend/content/113-web-components/100-html-templates.md", "web-components:html-templates": "/roadmaps/100-frontend/content/113-web-components/100-html-templates.md",
"web-components:custom-elements": "/100-frontend/content/113-web-components/101-custom-elements.md", "web-components:custom-elements": "/roadmaps/100-frontend/content/113-web-components/101-custom-elements.md",
"web-components:shadow-dom": "/100-frontend/content/113-web-components/102-shadow-dom.md", "web-components:shadow-dom": "/roadmaps/100-frontend/content/113-web-components/102-shadow-dom.md",
"css-frameworks": "/100-frontend/content/114-css-frameworks/readme.md", "css-frameworks": "/roadmaps/100-frontend/content/114-css-frameworks/readme.md",
"css-frameworks:js-first": "/100-frontend/content/114-css-frameworks/114-js-first/readme.md", "css-frameworks:js-first": "/roadmaps/100-frontend/content/114-css-frameworks/114-js-first/readme.md",
"css-frameworks:114-js-first/chakra-ui": "/100-frontend/content/114-css-frameworks/114-js-first/chakra-ui.md", "css-frameworks:114-js-first/chakra-ui": "/roadmaps/100-frontend/content/114-css-frameworks/114-js-first/chakra-ui.md",
"css-frameworks:114-js-first/material-ui": "/100-frontend/content/114-css-frameworks/114-js-first/material-ui.md", "css-frameworks:114-js-first/material-ui": "/roadmaps/100-frontend/content/114-css-frameworks/114-js-first/material-ui.md",
"css-frameworks:114-js-first/radix-ui": "/100-frontend/content/114-css-frameworks/114-js-first/radix-ui.md", "css-frameworks:114-js-first/radix-ui": "/roadmaps/100-frontend/content/114-css-frameworks/114-js-first/radix-ui.md",
"css-frameworks:114-js-first/tailwind-css": "/100-frontend/content/114-css-frameworks/114-js-first/tailwind-css.md", "css-frameworks:114-js-first/tailwind-css": "/roadmaps/100-frontend/content/114-css-frameworks/114-js-first/tailwind-css.md",
"css-frameworks:css-first": "/100-frontend/content/114-css-frameworks/114-css-first/readme.md", "css-frameworks:css-first": "/roadmaps/100-frontend/content/114-css-frameworks/114-css-first/readme.md",
"css-frameworks:114-css-first/bootstrap": "/100-frontend/content/114-css-frameworks/114-css-first/bootstrap.md", "css-frameworks:114-css-first/bootstrap": "/roadmaps/100-frontend/content/114-css-frameworks/114-css-first/bootstrap.md",
"css-frameworks:114-css-first/bulma": "/100-frontend/content/114-css-frameworks/114-css-first/bulma.md", "css-frameworks:114-css-first/bulma": "/roadmaps/100-frontend/content/114-css-frameworks/114-css-first/bulma.md",
"testing-your-apps": "/100-frontend/content/115-testing-your-apps/readme.md", "testing-your-apps": "/roadmaps/100-frontend/content/115-testing-your-apps/readme.md",
"testing-your-apps:jest": "/100-frontend/content/115-testing-your-apps/100-jest.md", "testing-your-apps:jest": "/roadmaps/100-frontend/content/115-testing-your-apps/100-jest.md",
"testing-your-apps:react-testing-library": "/100-frontend/content/115-testing-your-apps/101-react-testing-library.md", "testing-your-apps:react-testing-library": "/roadmaps/100-frontend/content/115-testing-your-apps/101-react-testing-library.md",
"testing-your-apps:cypress": "/100-frontend/content/115-testing-your-apps/102-cypress.md", "testing-your-apps:cypress": "/roadmaps/100-frontend/content/115-testing-your-apps/102-cypress.md",
"testing-your-apps:enzyme": "/100-frontend/content/115-testing-your-apps/103-enzyme.md", "testing-your-apps:enzyme": "/roadmaps/100-frontend/content/115-testing-your-apps/103-enzyme.md",
"testing-your-apps:other-options": "/100-frontend/content/115-testing-your-apps/104-other-options.md", "testing-your-apps:other-options": "/roadmaps/100-frontend/content/115-testing-your-apps/104-other-options.md",
"type-checkers": "/100-frontend/content/116-type-checkers/readme.md", "type-checkers": "/roadmaps/100-frontend/content/116-type-checkers/readme.md",
"type-checkers:typescript": "/100-frontend/content/116-type-checkers/100-typescript.md", "type-checkers:typescript": "/roadmaps/100-frontend/content/116-type-checkers/100-typescript.md",
"type-checkers:flow": "/100-frontend/content/116-type-checkers/101-flow.md", "type-checkers:flow": "/roadmaps/100-frontend/content/116-type-checkers/101-flow.md",
"progressive-web-apps": "/100-frontend/content/117-progressive-web-apps/readme.md", "progressive-web-apps": "/roadmaps/100-frontend/content/117-progressive-web-apps/readme.md",
"progressive-web-apps:performance": "/100-frontend/content/117-progressive-web-apps/101-performance.md", "progressive-web-apps:performance": "/roadmaps/100-frontend/content/117-progressive-web-apps/101-performance.md",
"progressive-web-apps:apis": "/100-frontend/content/117-progressive-web-apps/100-apis.md", "progressive-web-apps:apis": "/roadmaps/100-frontend/content/117-progressive-web-apps/100-apis.md",
"server-side-rendering": "/100-frontend/content/118-server-side-rendering/readme.md", "server-side-rendering": "/roadmaps/100-frontend/content/118-server-side-rendering/readme.md",
"server-side-rendering:react-js": "/100-frontend/content/118-server-side-rendering/100-react-js/readme.md", "server-side-rendering:react-js": "/roadmaps/100-frontend/content/118-server-side-rendering/100-react-js/readme.md",
"server-side-rendering:100-react-js/next-js": "/100-frontend/content/118-server-side-rendering/100-react-js/next-js.md", "server-side-rendering:100-react-js/next-js": "/roadmaps/100-frontend/content/118-server-side-rendering/100-react-js/next-js.md",
"server-side-rendering:100-react-js/after-js": "/100-frontend/content/118-server-side-rendering/100-react-js/after-js.md", "server-side-rendering:100-react-js/after-js": "/roadmaps/100-frontend/content/118-server-side-rendering/100-react-js/after-js.md",
"server-side-rendering:angular": "/100-frontend/content/118-server-side-rendering/101-angular/readme.md", "server-side-rendering:angular": "/roadmaps/100-frontend/content/118-server-side-rendering/101-angular/readme.md",
"server-side-rendering:101-angular/universal": "/100-frontend/content/118-server-side-rendering/101-angular/universal.md", "server-side-rendering:101-angular/universal": "/roadmaps/100-frontend/content/118-server-side-rendering/101-angular/universal.md",
"server-side-rendering:vue-js": "/100-frontend/content/118-server-side-rendering/102-vue-js/readme.md", "server-side-rendering:vue-js": "/roadmaps/100-frontend/content/118-server-side-rendering/102-vue-js/readme.md",
"server-side-rendering:102-vue-js/nuxt-js": "/100-frontend/content/118-server-side-rendering/102-vue-js/nuxt-js.md", "server-side-rendering:102-vue-js/nuxt-js": "/roadmaps/100-frontend/content/118-server-side-rendering/102-vue-js/nuxt-js.md",
"graphql": "/100-frontend/content/119-graphql/readme.md", "graphql": "/roadmaps/100-frontend/content/119-graphql/readme.md",
"graphql:apollo": "/100-frontend/content/119-graphql/100-apollo.md", "graphql:apollo": "/roadmaps/100-frontend/content/119-graphql/100-apollo.md",
"graphql:relay-modern": "/100-frontend/content/119-graphql/101-relay-modern.md", "graphql:relay-modern": "/roadmaps/100-frontend/content/119-graphql/101-relay-modern.md",
"static-site-generators": "/100-frontend/content/120-static-site-generators/readme.md", "static-site-generators": "/roadmaps/100-frontend/content/120-static-site-generators/readme.md",
"static-site-generators:next-js": "/100-frontend/content/120-static-site-generators/100-next-js.md", "static-site-generators:next-js": "/roadmaps/100-frontend/content/120-static-site-generators/100-next-js.md",
"static-site-generators:gatsbyjs": "/100-frontend/content/120-static-site-generators/101-gatsbyjs.md", "static-site-generators:gatsbyjs": "/roadmaps/100-frontend/content/120-static-site-generators/101-gatsbyjs.md",
"static-site-generators:nuxt-js": "/100-frontend/content/120-static-site-generators/102-nuxt-js.md", "static-site-generators:nuxt-js": "/roadmaps/100-frontend/content/120-static-site-generators/102-nuxt-js.md",
"static-site-generators:vuepress": "/100-frontend/content/120-static-site-generators/103-vuepress.md", "static-site-generators:vuepress": "/roadmaps/100-frontend/content/120-static-site-generators/103-vuepress.md",
"static-site-generators:jekyll": "/100-frontend/content/120-static-site-generators/104-jekyll.md", "static-site-generators:jekyll": "/roadmaps/100-frontend/content/120-static-site-generators/104-jekyll.md",
"static-site-generators:hugo": "/100-frontend/content/120-static-site-generators/105-hugo.md", "static-site-generators:hugo": "/roadmaps/100-frontend/content/120-static-site-generators/105-hugo.md",
"static-site-generators:gridsome": "/100-frontend/content/120-static-site-generators/106-gridsome.md", "static-site-generators:gridsome": "/roadmaps/100-frontend/content/120-static-site-generators/106-gridsome.md",
"static-site-generators:eleventy": "/100-frontend/content/120-static-site-generators/107-eleventy.md", "static-site-generators:eleventy": "/roadmaps/100-frontend/content/120-static-site-generators/107-eleventy.md",
"mobile-applications": "/100-frontend/content/121-mobile-applications/readme.md", "mobile-applications": "/roadmaps/100-frontend/content/121-mobile-applications/readme.md",
"mobile-applications:react-native": "/100-frontend/content/121-mobile-applications/100-react-native.md", "mobile-applications:react-native": "/roadmaps/100-frontend/content/121-mobile-applications/100-react-native.md",
"mobile-applications:nativescript": "/100-frontend/content/121-mobile-applications/101-nativescript.md", "mobile-applications:nativescript": "/roadmaps/100-frontend/content/121-mobile-applications/101-nativescript.md",
"mobile-applications:flutter": "/100-frontend/content/121-mobile-applications/102-flutter.md", "mobile-applications:flutter": "/roadmaps/100-frontend/content/121-mobile-applications/102-flutter.md",
"mobile-applications:ionic": "/100-frontend/content/121-mobile-applications/103-ionic.md", "mobile-applications:ionic": "/roadmaps/100-frontend/content/121-mobile-applications/103-ionic.md",
"desktop-applications": "/100-frontend/content/122-desktop-applications/readme.md", "desktop-applications": "/roadmaps/100-frontend/content/122-desktop-applications/readme.md",
"desktop-applications:electron": "/100-frontend/content/122-desktop-applications/100-electron.md", "desktop-applications:electron": "/roadmaps/100-frontend/content/122-desktop-applications/100-electron.md",
"desktop-applications:carlo": "/100-frontend/content/122-desktop-applications/101-carlo.md", "desktop-applications:carlo": "/roadmaps/100-frontend/content/122-desktop-applications/101-carlo.md",
"desktop-applications:proton-native": "/100-frontend/content/122-desktop-applications/102-proton-native.md", "desktop-applications:proton-native": "/roadmaps/100-frontend/content/122-desktop-applications/102-proton-native.md",
"web-assembly": "/100-frontend/content/123-web-assembly.md" "web-assembly": "/roadmaps/100-frontend/content/123-web-assembly.md"
} }

@ -18,6 +18,7 @@ export type RoadmapType = {
imagePath?: string, imagePath?: string,
landingPath?: string; landingPath?: string;
resourcesPath: string; resourcesPath: string;
contentPathsFilePath?: string;
metaPath: string; metaPath: string;
isCommunity: boolean; isCommunity: boolean;
isUpcoming: boolean; isUpcoming: boolean;

@ -1,5 +1,18 @@
import { Box, Button, Text, Container, Link, Stack, Badge } from '@chakra-ui/react'; import {
import { ArrowBackIcon, AtSignIcon, DownloadIcon, ViewIcon } from '@chakra-ui/icons'; Box,
Button,
Text,
Container,
Link,
Stack,
Badge,
} from '@chakra-ui/react';
import {
ArrowBackIcon,
AtSignIcon,
DownloadIcon,
ViewIcon,
} from '@chakra-ui/icons';
import { GlobalHeader } from '../../components/global-header'; import { GlobalHeader } from '../../components/global-header';
import { OpensourceBanner } from '../../components/opensource-banner'; import { OpensourceBanner } from '../../components/opensource-banner';
import { UpdatesBanner } from '../../components/updates-banner'; import { UpdatesBanner } from '../../components/updates-banner';
@ -11,6 +24,8 @@ import Helmet from '../../components/helmet';
import siteConfig from '../../content/site.json'; import siteConfig from '../../content/site.json';
import React from 'react'; import React from 'react';
import { event } from '../../lib/gtag'; import { event } from '../../lib/gtag';
import { NewAlertBanner } from '../../components/roadmap/new-alert-banner';
import { RoadmapPageHeader } from '../../components/roadmap/roadmap-page-header';
type RoadmapProps = { type RoadmapProps = {
roadmap: RoadmapType; roadmap: RoadmapType;
@ -23,9 +38,9 @@ function ImageRoadmap(props: RoadmapProps) {
} }
return ( return (
<Container maxW={'900px'} position='relative'> <Container maxW={'900px'} position="relative">
<Box mb='30px'> <Box mb="30px">
<img alt='Frontend Roadmap' src={roadmap.imagePath} /> <img alt="Frontend Roadmap" src={roadmap.imagePath} />
</Box> </Box>
</Container> </Container>
); );
@ -42,7 +57,7 @@ function TextualRoadmap(props: RoadmapProps) {
const LandingContent = require(`../../content/${normalizedPath}`).default; const LandingContent = require(`../../content/${normalizedPath}`).default;
return ( return (
<Container maxW={'container.md'} position='relative'> <Container maxW={'container.md'} position="relative">
<MdRenderer> <MdRenderer>
<LandingContent /> <LandingContent />
</MdRenderer> </MdRenderer>
@ -50,75 +65,19 @@ function TextualRoadmap(props: RoadmapProps) {
); );
} }
export function NewBanner() {
return (
<Text _hover={{ textDecoration: 'none', color: 'blue.700', '& .new-badge': { bg: 'blue.700' } }}
as={Link}
href={siteConfig.url.youtube}
d='block'
target='_blank'
color='red.700'
fontSize='sm'
mb='10px'
fontWeight={500}
onClick={() => event({
category: 'Subscription',
action: 'Clicked the YouTube banner',
label: 'YouTube Alert on Roadmap'
})}>
<Badge transition={'all 300ms'} className='new-badge' mr='7px' colorScheme='red' variant='solid'>New</Badge>
<Text textDecoration='underline' as='span' d={['none', 'inline']}>Roadmap topics to be covered on our YouTube
Channel</Text>
<Text textDecoration='underline' as='span' d={['inline', 'none']}>Topic videos being made on YouTube</Text>
<Text as='span' ml='5px'>&raquo;</Text>
</Text>
);
}
export default function Roadmap(props: RoadmapProps) { export default function Roadmap(props: RoadmapProps) {
const { roadmap } = props; const { roadmap } = props;
return ( return (
<Box bg='white' minH='100vh'> <Box bg="white" minH="100vh">
<GlobalHeader /> <GlobalHeader />
<Helmet <Helmet
title={roadmap?.seo?.title || roadmap.title} title={roadmap?.seo?.title || roadmap.title}
description={roadmap?.seo?.description || roadmap.description} description={roadmap?.seo?.description || roadmap.description}
keywords={roadmap?.seo.keywords || []} keywords={roadmap?.seo.keywords || []}
/> />
<Box mb='60px'> <Box mb="60px">
<PageHeader <RoadmapPageHeader roadmap={roadmap} />
beforeTitle={<NewBanner />}
title={roadmap.title}
subtitle={roadmap.description}
>
<Stack mt='20px' isInline>
<Button d={['flex', 'flex']} as={Link} href={'/roadmaps'} size='xs' py='14px' px='10px'
colorScheme='teal' variant='solid' _hover={{ textDecoration: 'none' }}>
&larr; <Text as='span' d={['none', 'inline']} ml='5px'>All Roadmaps</Text>
</Button>
{roadmap.pdfUrl && (
<Button as={Link}
href={roadmap.pdfUrl}
target='_blank'
size='xs'
py='14px'
px='10px'
leftIcon={<DownloadIcon />}
colorScheme='yellow'
variant='solid'
_hover={{ textDecoration: 'none' }}>
Download
</Button>
)}
<Button as={Link} href={'/signup'} size='xs' py='14px' px='10px' leftIcon={<AtSignIcon />}
colorScheme='yellow' variant='solid' _hover={{ textDecoration: 'none' }}>
Subscribe
</Button>
</Stack>
</PageHeader>
<ImageRoadmap roadmap={roadmap} /> <ImageRoadmap roadmap={roadmap} />
<TextualRoadmap roadmap={roadmap} /> <TextualRoadmap roadmap={roadmap} />
</Box> </Box>
@ -132,26 +91,26 @@ export default function Roadmap(props: RoadmapProps) {
type StaticPathItem = { type StaticPathItem = {
params: { params: {
roadmap: string roadmap: string;
} };
}; };
export async function getStaticPaths() { export async function getStaticPaths() {
const roadmaps = getAllRoadmaps(); const roadmaps = getAllRoadmaps();
const paramsList: StaticPathItem[] = roadmaps.map(roadmap => ({ const paramsList: StaticPathItem[] = roadmaps.map((roadmap) => ({
params: { 'roadmap': roadmap.id } params: { roadmap: roadmap.id },
})); }));
return { return {
paths: paramsList, paths: paramsList,
fallback: false fallback: false,
}; };
} }
type ContextType = { type ContextType = {
params: { params: {
roadmap: string roadmap: string;
} };
}; };
export async function getStaticProps(context: ContextType) { export async function getStaticProps(context: ContextType) {
@ -159,7 +118,7 @@ export async function getStaticProps(context: ContextType) {
return { return {
props: { props: {
roadmap: getRoadmapById(roadmapId) roadmap: getRoadmapById(roadmapId),
} },
}; };
} }

@ -1,14 +1,13 @@
import { Box, Button, Container, Link, Stack } from '@chakra-ui/react'; import { Box, Container } from '@chakra-ui/react';
import { ArrowBackIcon, AtSignIcon, DownloadIcon } from '@chakra-ui/icons';
import { GlobalHeader } from '../../components/global-header'; import { GlobalHeader } from '../../components/global-header';
import { OpensourceBanner } from '../../components/opensource-banner'; import { OpensourceBanner } from '../../components/opensource-banner';
import { UpdatesBanner } from '../../components/updates-banner'; import { UpdatesBanner } from '../../components/updates-banner';
import { Footer } from '../../components/footer'; import { Footer } from '../../components/footer';
import { PageHeader } from '../../components/page-header';
import { getAllRoadmaps, getRoadmapById, RoadmapType } from '../../lib/roadmap'; import { getAllRoadmaps, getRoadmapById, RoadmapType } from '../../lib/roadmap';
import Helmet from '../../components/helmet'; import Helmet from '../../components/helmet';
import { useEffect, useRef, useState } from 'react'; import { useEffect, useRef, useState } from 'react';
import { wireframeJSONToSVG } from '../../lib/renderer'; import { wireframeJSONToSVG } from '../../lib/renderer';
import { RoadmapPageHeader } from '../../components/roadmap/roadmap-page-header';
type RoadmapProps = { type RoadmapProps = {
roadmap: RoadmapType; roadmap: RoadmapType;
@ -71,55 +70,7 @@ export default function InteractiveRoadmap(props: RoadmapProps) {
keywords={roadmap?.seo.keywords || []} keywords={roadmap?.seo.keywords || []}
/> />
<Box mb="60px"> <Box mb="60px">
<PageHeader title={roadmap.title} subtitle={roadmap.description}> <RoadmapPageHeader roadmap={roadmap} />
<Stack mt="20px" isInline>
<Button
d={['none', 'flex']}
as={Link}
href={'/roadmaps'}
size="xs"
py="14px"
px="10px"
leftIcon={<ArrowBackIcon />}
colorScheme="teal"
variant="solid"
_hover={{ textDecoration: 'none' }}
>
All Roadmaps
</Button>
{roadmap.pdfUrl && (
<Button
as={Link}
href={roadmap.pdfUrl}
target="_blank"
size="xs"
py="14px"
px="10px"
leftIcon={<DownloadIcon />}
colorScheme="yellow"
variant="solid"
_hover={{ textDecoration: 'none' }}
>
Download PDF
</Button>
)}
<Button
as={Link}
href={'/signup'}
size="xs"
py="14px"
px="10px"
leftIcon={<AtSignIcon />}
colorScheme="yellow"
variant="solid"
_hover={{ textDecoration: 'none' }}
>
Subscribe
</Button>
</Stack>
</PageHeader>
<RoadmapRenderer json={json} roadmap={roadmap} /> <RoadmapRenderer json={json} roadmap={roadmap} />
</Box> </Box>

@ -1,13 +1,12 @@
import { Box, Button, Container, Link, Stack } from '@chakra-ui/react'; import { Box, Container } from '@chakra-ui/react';
import { ArrowBackIcon, AtSignIcon, DownloadIcon } from '@chakra-ui/icons';
import { GlobalHeader } from '../../components/global-header'; import { GlobalHeader } from '../../components/global-header';
import { OpensourceBanner } from '../../components/opensource-banner'; import { OpensourceBanner } from '../../components/opensource-banner';
import { UpdatesBanner } from '../../components/updates-banner'; import { UpdatesBanner } from '../../components/updates-banner';
import { Footer } from '../../components/footer'; import { Footer } from '../../components/footer';
import { PageHeader } from '../../components/page-header';
import { getAllRoadmaps, getRoadmapById, RoadmapType } from '../../lib/roadmap'; import { getAllRoadmaps, getRoadmapById, RoadmapType } from '../../lib/roadmap';
import MdRenderer from '../../components/md-renderer'; import MdRenderer from '../../components/md-renderer';
import Helmet from '../../components/helmet'; import Helmet from '../../components/helmet';
import { RoadmapPageHeader } from '../../components/roadmap/roadmap-page-header';
type RoadmapProps = { type RoadmapProps = {
roadmap: RoadmapType; roadmap: RoadmapType;
@ -44,38 +43,7 @@ export default function Roadmap(props: RoadmapProps) {
keywords={roadmap?.seo.keywords || []} keywords={roadmap?.seo.keywords || []}
/> />
<Box mb='60px'> <Box mb='60px'>
<PageHeader <RoadmapPageHeader roadmap={roadmap} />
title={roadmap.title}
subtitle={roadmap.description}
>
<Stack mt='20px' isInline>
<Button d={['none', 'flex']} as={Link} href={'/roadmaps'} size='xs' py='14px' px='10px'
leftIcon={<ArrowBackIcon />}
colorScheme='teal' variant='solid' _hover={{ textDecoration: 'none' }}>
All Roadmaps
</Button>
{roadmap.pdfUrl && (
<Button as={Link}
href={roadmap.pdfUrl}
target='_blank'
size='xs'
py='14px'
px='10px'
leftIcon={<DownloadIcon />}
colorScheme='yellow'
variant='solid'
_hover={{ textDecoration: 'none' }}>
Download PDF
</Button>
)}
<Button as={Link} href={'/signup'} size='xs' py='14px' px='10px' leftIcon={<AtSignIcon />}
colorScheme='yellow' variant='solid' _hover={{ textDecoration: 'none' }}>
Subscribe
</Button>
</Stack>
</PageHeader>
<RoadmapResources roadmap={roadmap} /> <RoadmapResources roadmap={roadmap} />
</Box> </Box>

@ -3,7 +3,7 @@
<url> <url>
<loc>https://roadmap.sh/frontend</loc> <loc>https://roadmap.sh/frontend</loc>
<changefreq>monthly</changefreq> <changefreq>monthly</changefreq>
<lastmod>2021-12-03T14:00:37.506Z</lastmod> <lastmod>2021-12-03T18:57:23.101Z</lastmod>
<priority>1.0</priority> <priority>1.0</priority>
</url> </url>
<url> <url>

@ -1,8 +1,9 @@
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
const CONTENT_DIR = path.join(__dirname, '../content');
// Directory containing the roadmaps // Directory containing the roadmaps
const CONTENT_DIR = path.join(__dirname, '../content/roadmaps'); const ROADMAP_CONTENT_DIR = path.join(__dirname, '../content/roadmaps');
const roadmapKey = process.argv[2]; const roadmapKey = process.argv[2];
type ControlType = { type ControlType = {
@ -53,7 +54,7 @@ if (!roadmapKey || !roadmaps[roadmapKey]) {
// Directory holding the roadmap content files // Directory holding the roadmap content files
const roadmapDirName = fs const roadmapDirName = fs
.readdirSync(CONTENT_DIR) .readdirSync(ROADMAP_CONTENT_DIR)
.find((dirName: string) => dirName.replace(/\d+-/, '') === roadmapKey); .find((dirName: string) => dirName.replace(/\d+-/, '') === roadmapKey);
if (!roadmapDirName) { if (!roadmapDirName) {
@ -61,8 +62,8 @@ if (!roadmapDirName) {
process.exit(1); process.exit(1);
} }
const roadmapDirPath = path.join(CONTENT_DIR, roadmapDirName); const roadmapDirPath = path.join(ROADMAP_CONTENT_DIR, roadmapDirName);
const roadmapContentDirPath = path.join(CONTENT_DIR, roadmapDirName, 'content'); const roadmapContentDirPath = path.join(ROADMAP_CONTENT_DIR, roadmapDirName, 'content');
// If roadmap content already exists do not proceed as it would override the files // If roadmap content already exists do not proceed as it would override the files
if (fs.existsSync(roadmapContentDirPath)) { if (fs.existsSync(roadmapContentDirPath)) {

Loading…
Cancel
Save