Add video and guides on homepage

pull/1331/head
Kamran Ahmed 3 years ago
parent 0e90d53b8e
commit 74ef38cdb6
  1. 50
      content/guides.json
  2. 92
      content/videos.json
  3. 14
      lib/author.ts
  4. 26
      lib/guide.ts
  5. 44
      lib/video.ts
  6. 50
      pages/index.tsx

@ -5,7 +5,7 @@
"url": "/guides/ci-cd", "url": "/guides/ci-cd",
"fileName": "ci-cd", "fileName": "ci-cd",
"isPro": false, "isPro": false,
"author": "kamranahmedse", "authorUsername": "kamranahmedse",
"updatedAt": "2020-07-09T19:59:14.191Z", "updatedAt": "2020-07-09T19:59:14.191Z",
"createdAt": "2020-07-09T19:59:14.191Z" "createdAt": "2020-07-09T19:59:14.191Z"
}, },
@ -15,7 +15,7 @@
"url": "/guides/sso", "url": "/guides/sso",
"fileName": "sso", "fileName": "sso",
"isPro": false, "isPro": false,
"author": "kamranahmedse", "authorUsername": "kamranahmedse",
"updatedAt": "2020-07-01T19:59:14.191Z", "updatedAt": "2020-07-01T19:59:14.191Z",
"createdAt": "2020-07-01T19:59:14.191Z" "createdAt": "2020-07-01T19:59:14.191Z"
}, },
@ -25,7 +25,7 @@
"url": "/guides/oauth", "url": "/guides/oauth",
"fileName": "oauth", "fileName": "oauth",
"isPro": false, "isPro": false,
"author": "kamranahmedse", "authorUsername": "kamranahmedse",
"updatedAt": "2020-06-28T19:59:14.191Z", "updatedAt": "2020-06-28T19:59:14.191Z",
"createdAt": "2020-06-28T19:59:14.191Z" "createdAt": "2020-06-28T19:59:14.191Z"
}, },
@ -35,7 +35,7 @@
"url": "/guides/jwt-authentication", "url": "/guides/jwt-authentication",
"fileName": "jwt-authentication", "fileName": "jwt-authentication",
"isPro": false, "isPro": false,
"author": "kamranahmedse", "authorUsername": "kamranahmedse",
"updatedAt": "2020-06-20T19:59:14.191Z", "updatedAt": "2020-06-20T19:59:14.191Z",
"createdAt": "2020-06-20T19:59:14.191Z" "createdAt": "2020-06-20T19:59:14.191Z"
}, },
@ -45,7 +45,7 @@
"url": "/guides/token-authentication", "url": "/guides/token-authentication",
"fileName": "token-authentication", "fileName": "token-authentication",
"isPro": false, "isPro": false,
"author": "kamranahmedse", "authorUsername": "kamranahmedse",
"updatedAt": "2020-06-02T20:59:14.191Z", "updatedAt": "2020-06-02T20:59:14.191Z",
"createdAt": "2020-06-02T20:59:14.191Z" "createdAt": "2020-06-02T20:59:14.191Z"
}, },
@ -55,7 +55,7 @@
"url": "/guides/session-authentication", "url": "/guides/session-authentication",
"fileName": "session-authentication", "fileName": "session-authentication",
"isPro": false, "isPro": false,
"author": "kamranahmedse", "authorUsername": "kamranahmedse",
"updatedAt": "2020-05-26T20:59:14.191Z", "updatedAt": "2020-05-26T20:59:14.191Z",
"createdAt": "2020-05-26T20:59:14.191Z" "createdAt": "2020-05-26T20:59:14.191Z"
}, },
@ -65,7 +65,7 @@
"url": "/guides/basic-authentication", "url": "/guides/basic-authentication",
"fileName": "basic-authentication", "fileName": "basic-authentication",
"isPro": false, "isPro": false,
"author": "kamranahmedse", "authorUsername": "kamranahmedse",
"updatedAt": "2020-05-19T20:59:14.191Z", "updatedAt": "2020-05-19T20:59:14.191Z",
"createdAt": "2020-05-19T20:59:14.191Z" "createdAt": "2020-05-19T20:59:14.191Z"
}, },
@ -75,7 +75,7 @@
"url": "/guides/character-encodings", "url": "/guides/character-encodings",
"fileName": "character-encodings", "fileName": "character-encodings",
"isPro": false, "isPro": false,
"author": "kamranahmedse", "authorUsername": "kamranahmedse",
"updatedAt": "2020-05-14T20:59:14.191Z", "updatedAt": "2020-05-14T20:59:14.191Z",
"createdAt": "2020-05-14T20:59:14.191Z" "createdAt": "2020-05-14T20:59:14.191Z"
}, },
@ -85,7 +85,7 @@
"url": "/guides/unfamiliar-codebase", "url": "/guides/unfamiliar-codebase",
"fileName": "unfamiliar-codebase", "fileName": "unfamiliar-codebase",
"isPro": false, "isPro": false,
"author": "kamranahmedse", "authorUsername": "kamranahmedse",
"updatedAt": "2020-05-04T20:59:14.191Z", "updatedAt": "2020-05-04T20:59:14.191Z",
"createdAt": "2020-05-04T20:59:14.191Z" "createdAt": "2020-05-04T20:59:14.191Z"
}, },
@ -95,7 +95,7 @@
"url": "/guides/why-build-it-and-they-will-come-wont-work-anymore", "url": "/guides/why-build-it-and-they-will-come-wont-work-anymore",
"fileName": "why-build-it-and-they-will-come-wont-work-anymore", "fileName": "why-build-it-and-they-will-come-wont-work-anymore",
"isPro": false, "isPro": false,
"author": "spekulatius", "authorUsername": "spekulatius",
"updatedAt": "2020-05-04T12:59:14.191Z", "updatedAt": "2020-05-04T12:59:14.191Z",
"createdAt": "2020-05-04T12:59:14.191Z" "createdAt": "2020-05-04T12:59:14.191Z"
}, },
@ -105,7 +105,7 @@
"url": "/guides/dhcp-in-one-picture", "url": "/guides/dhcp-in-one-picture",
"fileName": "dhcp-in-one-picture", "fileName": "dhcp-in-one-picture",
"isPro": false, "isPro": false,
"author": "kamranahmedse", "authorUsername": "kamranahmedse",
"updatedAt": "2020-04-28T15:48:21.191Z", "updatedAt": "2020-04-28T15:48:21.191Z",
"createdAt": "2020-04-28T15:48:21.191Z" "createdAt": "2020-04-28T15:48:21.191Z"
}, },
@ -115,7 +115,7 @@
"url": "/guides/ssl-tls-https-ssh", "url": "/guides/ssl-tls-https-ssh",
"fileName": "ssl-tls-https-ssh", "fileName": "ssl-tls-https-ssh",
"isPro": false, "isPro": false,
"author": "kamranahmedse", "authorUsername": "kamranahmedse",
"updatedAt": "2020-04-22T15:48:21.191Z", "updatedAt": "2020-04-22T15:48:21.191Z",
"createdAt": "2020-04-22T15:48:21.191Z" "createdAt": "2020-04-22T15:48:21.191Z"
}, },
@ -125,7 +125,7 @@
"url": "/guides/asymptotic-notation", "url": "/guides/asymptotic-notation",
"fileName": "asymptotic-notation", "fileName": "asymptotic-notation",
"isPro": false, "isPro": false,
"author": "kamranahmedse", "authorUsername": "kamranahmedse",
"updatedAt": "2020-04-03T15:48:21.191Z", "updatedAt": "2020-04-03T15:48:21.191Z",
"createdAt": "2020-04-03T15:48:21.191Z" "createdAt": "2020-04-03T15:48:21.191Z"
}, },
@ -135,7 +135,7 @@
"url": "/guides/big-o-notation", "url": "/guides/big-o-notation",
"fileName": "big-o-notation", "fileName": "big-o-notation",
"isPro": false, "isPro": false,
"author": "kamranahmedse", "authorUsername": "kamranahmedse",
"updatedAt": "2020-03-15T15:48:21.191Z", "updatedAt": "2020-03-15T15:48:21.191Z",
"createdAt": "2020-03-15T15:48:21.191Z" "createdAt": "2020-03-15T15:48:21.191Z"
}, },
@ -145,7 +145,7 @@
"url": "/guides/random-numbers", "url": "/guides/random-numbers",
"fileName": "random-numbers", "fileName": "random-numbers",
"isPro": false, "isPro": false,
"author": "kamranahmedse", "authorUsername": "kamranahmedse",
"updatedAt": "2020-03-14T15:48:21.191Z", "updatedAt": "2020-03-14T15:48:21.191Z",
"createdAt": "2020-03-14T15:48:21.191Z" "createdAt": "2020-03-14T15:48:21.191Z"
}, },
@ -155,7 +155,7 @@
"url": "/guides/scaling-databases", "url": "/guides/scaling-databases",
"fileName": "scaling-databases", "fileName": "scaling-databases",
"isPro": false, "isPro": false,
"author": "kamranahmedse", "authorUsername": "kamranahmedse",
"updatedAt": "2020-02-18T15:48:21.191Z", "updatedAt": "2020-02-18T15:48:21.191Z",
"createdAt": "2020-02-18T15:48:21.191Z" "createdAt": "2020-02-18T15:48:21.191Z"
}, },
@ -165,7 +165,7 @@
"url": "/guides/what-is-internet", "url": "/guides/what-is-internet",
"fileName": "what-is-internet", "fileName": "what-is-internet",
"isPro": false, "isPro": false,
"author": "dmytrobol", "authorUsername": "dmytrobol",
"updatedAt": "2020-02-29T15:48:21.191Z", "updatedAt": "2020-02-29T15:48:21.191Z",
"createdAt": "2020-02-29T15:48:21.191Z" "createdAt": "2020-02-29T15:48:21.191Z"
}, },
@ -175,7 +175,7 @@
"url": "/guides/torrent-client", "url": "/guides/torrent-client",
"fileName": "torrent-client", "fileName": "torrent-client",
"isPro": false, "isPro": false,
"author": "jesse", "authorUsername": "jesse",
"updatedAt": "2020-01-17T15:48:21.191Z", "updatedAt": "2020-01-17T15:48:21.191Z",
"createdAt": "2020-01-17T15:48:21.191Z", "createdAt": "2020-01-17T15:48:21.191Z",
"canonical": "https://blog.jse.li/posts/torrent/" "canonical": "https://blog.jse.li/posts/torrent/"
@ -186,7 +186,7 @@
"url": "/guides/levels-of-seniority", "url": "/guides/levels-of-seniority",
"fileName": "levels-of-seniority", "fileName": "levels-of-seniority",
"isPro": false, "isPro": false,
"author": "kamranahmedse", "authorUsername": "kamranahmedse",
"updatedAt": "2019-12-03T12:13:00.860Z", "updatedAt": "2019-12-03T12:13:00.860Z",
"createdAt": "2019-12-03T12:13:00.860Z" "createdAt": "2019-12-03T12:13:00.860Z"
}, },
@ -196,7 +196,7 @@
"url": "/guides/design-patterns-for-humans", "url": "/guides/design-patterns-for-humans",
"fileName": "design-patterns-for-humans", "fileName": "design-patterns-for-humans",
"isPro": false, "isPro": false,
"author": "kamranahmedse", "authorUsername": "kamranahmedse",
"updatedAt": "2019-10-09T12:00:00.860Z", "updatedAt": "2019-10-09T12:00:00.860Z",
"createdAt": "2019-01-23T17:00:00.860Z" "createdAt": "2019-01-23T17:00:00.860Z"
}, },
@ -206,7 +206,7 @@
"url": "/guides/journey-to-http2", "url": "/guides/journey-to-http2",
"fileName": "journey-to-http2", "fileName": "journey-to-http2",
"isPro": false, "isPro": false,
"author": "kamranahmedse", "authorUsername": "kamranahmedse",
"createdAt": "2018-12-04T12:00:00.860Z", "createdAt": "2018-12-04T12:00:00.860Z",
"updatedAt": "2018-12-04T12:00:00.860Z", "updatedAt": "2018-12-04T12:00:00.860Z",
"isDraft": true "isDraft": true
@ -217,7 +217,7 @@
"url": "/guides/dns-in-one-picture", "url": "/guides/dns-in-one-picture",
"fileName": "dns-in-one-picture", "fileName": "dns-in-one-picture",
"isPro": false, "isPro": false,
"author": "kamranahmedse", "authorUsername": "kamranahmedse",
"updatedAt": "2018-12-04T12:00:00.860Z", "updatedAt": "2018-12-04T12:00:00.860Z",
"createdAt": "2018-12-04T17:00:00.860Z" "createdAt": "2018-12-04T17:00:00.860Z"
}, },
@ -227,7 +227,7 @@
"url": "/guides/http-caching", "url": "/guides/http-caching",
"fileName": "http-caching", "fileName": "http-caching",
"isPro": false, "isPro": false,
"author": "kamranahmedse", "authorUsername": "kamranahmedse",
"createdAt": "2018-11-29T17:00:00.860Z", "createdAt": "2018-11-29T17:00:00.860Z",
"updatedAt": "2018-11-29T17:00:00.860Z" "updatedAt": "2018-11-29T17:00:00.860Z"
}, },
@ -237,7 +237,7 @@
"url": "/guides/history-of-javascript", "url": "/guides/history-of-javascript",
"fileName": "history-of-javascript", "fileName": "history-of-javascript",
"isPro": false, "isPro": false,
"author": "kamranahmedse", "authorUsername": "kamranahmedse",
"createdAt": "2017-10-28T17:00:00.860Z", "createdAt": "2017-10-28T17:00:00.860Z",
"updatedAt": "2017-10-28T17:00:00.860Z" "updatedAt": "2017-10-28T17:00:00.860Z"
}, },
@ -247,7 +247,7 @@
"url": "/guides/proxy-servers", "url": "/guides/proxy-servers",
"fileName": "proxy-servers", "fileName": "proxy-servers",
"isPro": false, "isPro": false,
"author": "ebrahimbharmal007", "authorUsername": "ebrahimbharmal007",
"createdAt": "2020-07-24T12:40:18", "createdAt": "2020-07-24T12:40:18",
"updatedAt": "2020-07-24T12:40:18" "updatedAt": "2020-07-24T12:40:18"
} }

@ -0,0 +1,92 @@
[
{
"title": "Transport Protocols: TCP vs UDP",
"description": "Learn the basics of CI/CD and how to implement that with GitHub Actions.",
"url": "/watch/transport-protocols-tcp-vs-udp",
"fileName": "tcp-udp",
"isPro": false,
"duration": "10 minutes",
"updatedAt": "2020-07-09T19:59:14.191Z",
"createdAt": "2020-07-09T19:59:14.191Z"
},
{
"title": "OSI Model Explained",
"description": "Learn the basics of CI/CD and how to implement that with GitHub Actions.",
"url": "/watch/transport-protocols-tcp-vs-udp",
"fileName": "tcp-udp",
"isPro": false,
"duration": "10 minutes",
"updatedAt": "2020-07-09T19:59:14.191Z",
"createdAt": "2020-07-09T19:59:14.191Z"
},
{
"title": "Creating a React App",
"description": "Learn the basics of CI/CD and how to implement that with GitHub Actions.",
"url": "/watch/transport-protocols-tcp-vs-udp",
"fileName": "tcp-udp",
"isPro": false,
"duration": "10 minutes",
"updatedAt": "2020-07-09T19:59:14.191Z",
"createdAt": "2020-07-09T19:59:14.191Z"
},
{
"title": "DOM vs Shadow DOM vs Virtual DOM",
"description": "Learn the basics of CI/CD and how to implement that with GitHub Actions.",
"url": "/watch/transport-protocols-tcp-vs-udp",
"fileName": "tcp-udp",
"isPro": false,
"duration": "10 minutes",
"updatedAt": "2020-07-09T19:59:14.191Z",
"createdAt": "2020-07-09T19:59:14.191Z"
},
{
"title": "Everything you need to know about HTTP Caching",
"description": "Learn the basics of CI/CD and how to implement that with GitHub Actions.",
"url": "/watch/transport-protocols-tcp-vs-udp",
"fileName": "tcp-udp",
"isPro": false,
"duration": "10 minutes",
"updatedAt": "2020-07-09T19:59:14.191Z",
"createdAt": "2020-07-09T19:59:14.191Z"
},
{
"title": "Content Delivery Networks",
"description": "Learn the basics of CI/CD and how to implement that with GitHub Actions.",
"url": "/watch/transport-protocols-tcp-vs-udp",
"fileName": "tcp-udp",
"isPro": false,
"duration": "10 minutes",
"updatedAt": "2020-07-09T19:59:14.191Z",
"createdAt": "2020-07-09T19:59:14.191Z"
},
{
"title": "Load Balancers in Depth",
"description": "Learn the basics of CI/CD and how to implement that with GitHub Actions.",
"url": "/watch/transport-protocols-tcp-vs-udp",
"fileName": "tcp-udp",
"isPro": false,
"duration": "10 minutes",
"updatedAt": "2020-07-09T19:59:14.191Z",
"createdAt": "2020-07-09T19:59:14.191Z"
},
{
"title": "DNS and How does it Work?",
"description": "Learn the basics of CI/CD and how to implement that with GitHub Actions.",
"url": "/watch/transport-protocols-tcp-vs-udp",
"fileName": "tcp-udp",
"isPro": false,
"duration": "10 minutes",
"updatedAt": "2020-07-09T19:59:14.191Z",
"createdAt": "2020-07-09T19:59:14.191Z"
},
{
"title": "JavaScript Fetch API",
"description": "Learn the basics of CI/CD and how to implement that with GitHub Actions.",
"url": "/watch/transport-protocols-tcp-vs-udp",
"fileName": "tcp-udp",
"isPro": false,
"duration": "10 minutes",
"updatedAt": "2020-07-09T19:59:14.191Z",
"createdAt": "2020-07-09T19:59:14.191Z"
}
]

@ -0,0 +1,14 @@
import authors from '../content/authors.json';
export type AuthorType = {
username: string;
name: string;
twitter: string;
picture: string;
bio: string;
}
export function findAuthorByUsername(username: string): AuthorType | undefined {
return (authors as AuthorType[]).find(author => author.username === username);
}

@ -1,6 +1,7 @@
import guides from '../content/guides.json'; import guides from '../content/guides.json';
import authors from '../content/authors.json';
import formatDate from 'date-fns/format'; import formatDate from 'date-fns/format';
import { NextApiRequest } from 'next';
import { AuthorType, findAuthorByUsername } from './author';
export type GuideType = { export type GuideType = {
title: string; title: string;
@ -8,12 +9,13 @@ export type GuideType = {
url: string; url: string;
fileName: string; fileName: string;
isPro: boolean; isPro: boolean;
author: string;
isDraft: boolean; isDraft: boolean;
createdAt: string; createdAt: string;
updatedAt: string; updatedAt: string;
formattedCreatedAt: string; formattedCreatedAt: string;
formattedUpdatedAt: string; formattedUpdatedAt: string;
authorUsername: string;
author?: AuthorType;
}; };
export function getAllGuides(limit: number = 0): GuideType[] { export function getAllGuides(limit: number = 0): GuideType[] {
@ -27,3 +29,23 @@ export function getAllGuides(limit: number = 0): GuideType[] {
})) }))
.slice(0, limit ? limit : guides.length); .slice(0, limit ? limit : guides.length);
} }
export function getRequestedGuide(req: NextApiRequest): GuideType | undefined {
const allGuides = getAllGuides();
const guide = allGuides.find(guide => guide.url === req.url);
if (!guide) {
return undefined;
}
try {
return {
...guide,
author: findAuthorByUsername(guide.authorUsername)
};
} catch (e) {
console.log(e);
}
return undefined;
}

@ -0,0 +1,44 @@
import videos from '../content/videos.json';
import formatDate from 'date-fns/format';
import { NextApiRequest } from 'next';
export type VideoType = {
title: string;
description: string;
url: string;
fileName: string;
isPro: boolean;
duration: string;
createdAt: string;
updatedAt: string;
formattedCreatedAt: string;
formattedUpdatedAt: string;
};
export function getAllVideos(limit: number = 0): VideoType[] {
return (videos as VideoType[])
.sort((a, b) => (new Date(b.updatedAt) as any) - (new Date(a.updatedAt) as any))
.map(video => ({
...video,
formattedCreatedAt: formatDate(new Date(video.createdAt), 'MMMM d, yyyy'),
formattedUpdatedAt: formatDate(new Date(video.updatedAt), 'MMMM d, yyyy')
}))
.slice(0, limit ? limit : videos.length);
}
export function getRequestedGuide(req: NextApiRequest): VideoType | undefined {
const allVideos = getAllVideos();
const video = allVideos.find(video => video.url === req.url);
if (!video) {
return undefined;
}
try {
return video;
} catch (e) {
console.log(e);
}
return undefined;
}

@ -10,14 +10,16 @@ import { LinksList } from '../components/links-list';
import { HomeRoadmapItem } from './roadmaps/components/home-roadmap-item'; import { HomeRoadmapItem } from './roadmaps/components/home-roadmap-item';
import { getFeaturedRoadmaps, RoadmapType } from '../lib/roadmap'; import { getFeaturedRoadmaps, RoadmapType } from '../lib/roadmap';
import { getAllGuides, GuideType } from '../lib/guide'; import { getAllGuides, GuideType } from '../lib/guide';
import { getAllVideos, VideoType } from '../lib/video';
type HomeProps = { type HomeProps = {
roadmaps: RoadmapType[]; roadmaps: RoadmapType[];
guides: GuideType[]; guides: GuideType[];
videos: VideoType[];
} }
export default function Home(props: HomeProps) { export default function Home(props: HomeProps) {
const { roadmaps, guides } = props; const { roadmaps, guides, videos } = props;
return ( return (
<Box bg='white' minH='100vh'> <Box bg='white' minH='100vh'>
@ -77,31 +79,24 @@ export default function Home(props: HomeProps) {
</Box> </Box>
<LinksList> <LinksList>
<LinksListItem hideSubtitleOnMobile title='Transport Protocols: TCP vs UDP' subtitle='15 minutes' {videos.map(video => (
icon={<VideoIcon <LinksListItem
style={{ marginRight: '7px', width: '18px', height: '18px', color: '#9c9c9c' }} />} /> key={video.url}
<LinksListItem hideSubtitleOnMobile title='OSI Model Explained' subtitle='10 minutes' icon={<VideoIcon hideSubtitleOnMobile
style={{ marginRight: '7px', width: '18px', height: '18px', color: '#9c9c9c' }} />} /> title={video.title}
<LinksListItem hideSubtitleOnMobile title='Creating a React App' badgeText='pro' subtitle='15 minutes' subtitle={video.duration}
icon={<VideoIcon icon={
style={{ marginRight: '7px', width: '18px', height: '18px', color: '#9c9c9c' }} />} /> <VideoIcon
<LinksListItem hideSubtitleOnMobile title='DOM vs Shadow DOM vs Virtual DOM' badgeText='pro' style={{
subtitle='15 minutes' marginRight: '7px',
icon={<VideoIcon width: '18px',
style={{ marginRight: '7px', width: '18px', height: '18px', color: '#9c9c9c' }} />} /> height: '18px',
<LinksListItem hideSubtitleOnMobile title='Everything you need to know about HTTP caching' badgeText='pro' color: '#9c9c9c'
subtitle='10 minutes' }}
icon={<VideoIcon />
style={{ marginRight: '7px', width: '18px', height: '18px', color: '#9c9c9c' }} />} /> }
<LinksListItem hideSubtitleOnMobile title='Content Delivery Networks' subtitle='5 minutes' icon={<VideoIcon />
style={{ marginRight: '7px', width: '18px', height: '18px', color: '#9c9c9c' }} />} /> ))}
<LinksListItem hideSubtitleOnMobile title='Load Balancers in Depth' subtitle='15 minutes' icon={<VideoIcon
style={{ marginRight: '7px', width: '18px', height: '18px', color: '#9c9c9c' }} />} />
<LinksListItem hideSubtitleOnMobile title='DNS and how does it work?' subtitle='2 minutes' icon={<VideoIcon
style={{ marginRight: '7px', width: '18px', height: '18px', color: '#9c9c9c' }} />} />
<LinksListItem hideSubtitleOnMobile title='JavaScript Fetch API' subtitle='22 minutes' icon={<VideoIcon
style={{ marginRight: '7px', width: '18px', height: '18px', color: '#9c9c9c' }} />} />
<DimmedMore text={'View all Videos'} /> <DimmedMore text={'View all Videos'} />
</LinksList> </LinksList>
</Container> </Container>
@ -118,7 +113,8 @@ export async function getStaticProps() {
return { return {
props: { props: {
roadmaps: getFeaturedRoadmaps(), roadmaps: getFeaturedRoadmaps(),
guides: getAllGuides(10) guides: getAllGuides(10),
videos: getAllVideos(10)
} }
}; };
} }

Loading…
Cancel
Save