Handle SSR for static pages

feat/roadmap-slug
Kamran Ahmed 11 months ago
parent 33af126728
commit bd01586e8e
  1. 13
      src/lib/guide.ts
  2. 13
      src/lib/link-group.ts
  3. 6
      src/lib/question-group.ts
  4. 13
      src/lib/video.ts
  5. 3
      src/pages/[roadmapId]/[...topicId].astro
  6. 27
      src/pages/g/[linkGroupId]/[linkId].astro
  7. 21
      src/pages/guides/[guideId].astro
  8. 27
      src/pages/questions/[questionGroupId].astro
  9. 21
      src/pages/videos/[videoId].astro

@ -48,7 +48,7 @@ export async function getAllGuides(): Promise<GuideFileType[]> {
'/src/data/guides/*.md', '/src/data/guides/*.md',
{ {
eager: true, eager: true,
} },
); );
const guideFiles = Object.values(guides); const guideFiles = Object.values(guides);
@ -60,6 +60,15 @@ export async function getAllGuides(): Promise<GuideFileType[]> {
return enrichedGuides.sort( return enrichedGuides.sort(
(a, b) => (a, b) =>
new Date(b.frontmatter.date).valueOf() - new Date(b.frontmatter.date).valueOf() -
new Date(a.frontmatter.date).valueOf() new Date(a.frontmatter.date).valueOf(),
); );
} }
export async function getGuideById(id: string): Promise<GuideFileType> {
const guide = await import(`/src/data/guides/${id}.md`);
return {
...guide,
id: guidePathToId(guide.file),
};
}

@ -29,7 +29,7 @@ export async function getAllLinkGroups(): Promise<LinkGroupFileType[]> {
'/src/data/link-groups/*.md', '/src/data/link-groups/*.md',
{ {
eager: true, eager: true,
} },
); );
return Object.values(linkGroups).map((linkGroupFile) => ({ return Object.values(linkGroups).map((linkGroupFile) => ({
@ -37,3 +37,14 @@ export async function getAllLinkGroups(): Promise<LinkGroupFileType[]> {
id: linkGroupPathToId(linkGroupFile.file), id: linkGroupPathToId(linkGroupFile.file),
})); }));
} }
export async function getLinkGroupById(
groupId: string,
): Promise<LinkGroupFileType> {
const linkGroup = await import(`/src/data/link-groups/${groupId}.md`);
return {
...linkGroup,
id: linkGroupPathToId(linkGroup.file),
};
}

@ -117,6 +117,12 @@ export async function getAllQuestionGroups(): Promise<QuestionGroupType[]> {
.sort((a, b) => a.frontmatter.order - b.frontmatter.order); .sort((a, b) => a.frontmatter.order - b.frontmatter.order);
} }
export async function getQuestionGroupById(id: string) {
const questionGroups = await getAllQuestionGroups();
return questionGroups.find((group) => group.id === id);
}
export async function getQuestionGroupsByIds( export async function getQuestionGroupsByIds(
ids: string[], ids: string[],
): Promise<{ id: string; title: string; description: string }[]> { ): Promise<{ id: string; title: string; description: string }[]> {

@ -47,7 +47,7 @@ export async function getAllVideos(): Promise<VideoFileType[]> {
'/src/data/videos/*.md', '/src/data/videos/*.md',
{ {
eager: true, eager: true,
} },
); );
const videoFiles = Object.values(videos); const videoFiles = Object.values(videos);
@ -59,6 +59,15 @@ export async function getAllVideos(): Promise<VideoFileType[]> {
return enrichedVideos.sort( return enrichedVideos.sort(
(a, b) => (a, b) =>
new Date(b.frontmatter.date).valueOf() - new Date(b.frontmatter.date).valueOf() -
new Date(a.frontmatter.date).valueOf() new Date(a.frontmatter.date).valueOf(),
); );
} }
export async function getVideoById(id: string): Promise<VideoFileType> {
const video = await import(`/src/data/videos/${id}.md`);
return {
...video,
id: videoPathToId(video.file),
};
}

@ -12,6 +12,9 @@ const topicSlug = `/${roadmapId}/${topicId}`;
const topicPathMapping = await getRoadmapTopicFiles(); const topicPathMapping = await getRoadmapTopicFiles();
const topicDetails = topicPathMapping[topicSlug]; const topicDetails = topicPathMapping[topicSlug];
if (!topicDetails) {
return Astro.redirect('/404');
}
const { file } = topicDetails; const { file } = topicDetails;

@ -1,30 +1,13 @@
--- ---
import BaseLayout from '../../../layouts/BaseLayout.astro'; import BaseLayout from '../../../layouts/BaseLayout.astro';
import SkeletonLayout from '../../../layouts/SkeletonLayout.astro'; import SkeletonLayout from '../../../layouts/SkeletonLayout.astro';
import { getAllLinkGroups } from '../../../lib/link-group'; import { getLinkGroupById } from '../../../lib/link-group';
export async function getStaticPaths() {
const linkGroups = await getAllLinkGroups();
return linkGroups.flatMap((linkGroup) => {
const linkGroupLinks = linkGroup.frontmatter;
return Object.keys(linkGroupLinks).map((slug) => {
return {
params: {
linkGroupId: linkGroup.id,
linkId: slug,
},
props: {
linkGroup,
},
};
});
});
}
const { linkId } = Astro.params; const { linkId } = Astro.params;
const { linkGroup } = Astro.props; const linkGroup = await getLinkGroupById(linkId!).catch(() => null);
if (!linkGroup) {
return Astro.redirect('/404');
}
const fullUrl = linkGroup.frontmatter[linkId!]; const fullUrl = linkGroup.frontmatter[linkId!];
--- ---

@ -2,23 +2,14 @@
import GuideHeader from '../../components/GuideHeader.astro'; import GuideHeader from '../../components/GuideHeader.astro';
import MarkdownFile from '../../components/MarkdownFile.astro'; import MarkdownFile from '../../components/MarkdownFile.astro';
import BaseLayout from '../../layouts/BaseLayout.astro'; import BaseLayout from '../../layouts/BaseLayout.astro';
import { getAllGuides,GuideFileType } from '../../lib/guide'; import { getGuideById } from '../../lib/guide';
export interface Props { const { guideId } = Astro.params;
guide: GuideFileType; const guide = await getGuideById(guideId).catch(() => null);
} if (!guide) {
return Astro.redirect('/404');
export async function getStaticPaths() {
const guides = await getAllGuides();
return guides.map((guide) => ({
params: { guideId: guide.id },
props: { guide },
}));
} }
const { guideId } = Astro.params;
const { guide } = Astro.props;
const { frontmatter: guideData } = guide; const { frontmatter: guideData } = guide;
--- ---
@ -30,7 +21,7 @@ const { frontmatter: guideData } = guide;
> >
<GuideHeader guide={guide} /> <GuideHeader guide={guide} />
<div class='py-5 sm:py-10 max-w-[700px] mx-auto'> <div class='mx-auto max-w-[700px] py-5 sm:py-10'>
<MarkdownFile> <MarkdownFile>
<guide.Content /> <guide.Content />
</MarkdownFile> </MarkdownFile>

@ -8,24 +8,15 @@ import { QuestionsList } from '../../components/Questions/QuestionsList';
import { import {
getAllQuestionGroups, getAllQuestionGroups,
type QuestionGroupType, getQuestionGroupById,
} from '../../lib/question-group'; } from '../../lib/question-group';
export interface Props { const { questionGroupId } = Astro.params;
questionGroup: QuestionGroupType; const questionGroup = await getQuestionGroupById(questionGroupId);
if (!questionGroup) {
return Astro.redirect('/404');
} }
export async function getStaticPaths() {
const questionGroups = await getAllQuestionGroups();
return questionGroups.map((questionGroup) => {
return {
params: { questionGroupId: questionGroup.id },
props: { questionGroup },
};
});
}
const { questionGroup } = Astro.props;
const { frontmatter } = questionGroup; const { frontmatter } = questionGroup;
--- ---
@ -38,24 +29,24 @@ const { frontmatter } = questionGroup;
> >
<div class='flex bg-gray-50 pb-14 pt-4 sm:pb-16 sm:pt-8'> <div class='flex bg-gray-50 pb-14 pt-4 sm:pb-16 sm:pt-8'>
<div class='container !max-w-[740px]'> <div class='container !max-w-[740px]'>
<div class='mb-3 sm:mb-5 mt-2 text-left sm:text-center sm:mt-8'> <div class='mb-3 mt-2 text-left sm:mb-5 sm:mt-8 sm:text-center'>
<div class='mb-2 md:mb-6'> <div class='mb-2 md:mb-6'>
<a <a
href='/questions' href='/questions'
class='group rounded-md text-sm font-medium text-gray-400 hover:text-gray-800 transition-colors duration-200' class='group rounded-md text-sm font-medium text-gray-400 transition-colors duration-200 hover:text-gray-800'
> >
<span <span
class='inline-block transform transition-transform group-hover:translate-x-[-2px]' class='inline-block transform transition-transform group-hover:translate-x-[-2px]'
> >
&larr; &larr;
</span> </span>
Back to all Questions Back to all Questions
</a> </a>
</div> </div>
<h1 class='mb-1 text-2xl font-bold sm:mb-5 sm:text-5xl'> <h1 class='mb-1 text-2xl font-bold sm:mb-5 sm:text-5xl'>
{frontmatter.title} {frontmatter.title}
</h1> </h1>
<p class='hidden sm:block text-xl text-gray-500'> <p class='hidden text-xl text-gray-500 sm:block'>
{frontmatter.description} {frontmatter.description}
</p> </p>
</div> </div>

@ -1,23 +1,14 @@
--- ---
import VideoHeader from '../../components/VideoHeader.astro'; import VideoHeader from '../../components/VideoHeader.astro';
import BaseLayout from '../../layouts/BaseLayout.astro'; import BaseLayout from '../../layouts/BaseLayout.astro';
import { getAllVideos,VideoFileType } from '../../lib/video'; import { getVideoById } from '../../lib/video';
export interface Props { const { videoId } = Astro.params;
video: VideoFileType;
}
export async function getStaticPaths() {
const videos = await getAllVideos();
return videos.map((video) => ({ const video = await getVideoById(videoId).catch(() => null);
params: { videoId: video.id }, if (!video) {
props: { video }, return Astro.redirect('/404');
}));
} }
const { videoId } = Astro.params;
const { video } = Astro.props;
--- ---
<BaseLayout <BaseLayout
@ -29,7 +20,7 @@ const { video } = Astro.props;
<div class='bg-gray-50 py-5 sm:py-10'> <div class='bg-gray-50 py-5 sm:py-10'>
<div <div
class='container prose prose-code:bg-transparent prose-h2:text-3xl prose-h2:mt-4 prose-h2:mb-2 prose-h3:mt-2 prose-img:mt-1' class='container prose prose-h2:mb-2 prose-h2:mt-4 prose-h2:text-3xl prose-h3:mt-2 prose-code:bg-transparent prose-img:mt-1'
> >
<video.Content /> <video.Content />
</div> </div>

Loading…
Cancel
Save