Main Post Content Page
This page is statically generated, BUT regenerated after new requests come in at an interval of 5000ms. If a prerendered page does not exist, will fallback to regular SSR.
pages/username/slug.js
import styles from '../../styles/Post.module.css';
import PostContent from '../../components/PostContent';
import { firestore, getUserWithUsername, postToJSON } from '../../lib/firebase';
import { useDocumentData } from 'react-firebase-hooks/firestore';
export async function getStaticProps({ params }) {
const { username, slug } = params;
const userDoc = await getUserWithUsername(username);
let post;
let path;
if (userDoc) {
const postRef = userDoc.ref.collection('posts').doc(slug);
post = postToJSON(await postRef.get());
path = postRef.path;
}
return {
props: { post, path },
revalidate: 5000,
};
}
export async function getStaticPaths() {
// Improve my using Admin SDK to select empty docs
const snapshot = await firestore.collectionGroup('posts').get();
const paths = snapshot.docs.map((doc) => {
const { slug, username } = doc.data();
return {
params: { username, slug },
};
});
return {
// must be in this format:
// paths: [
// { params: { username, slug }}
// ],
paths,
fallback: 'blocking',
};
}
export default function Post(props) {
return (
<main className={styles.container}>
</main>
);
}
Post Content with Markdown
command line
npm i react-markdown
Learn more about React Markdown
components/PostContent.js
import Link from 'next/link';
import ReactMarkdown from 'react-markdown';
// UI component for main post content
export default function PostContent({ post }) {
const createdAt = typeof post?.createdAt === 'number' ? new Date(post.createdAt) : post.createdAt.toDate();
return (
<div className="card">
<h1>{post?.title}</h1>
<span className="text-sm">
Written by{' '}
<Link href={`/${post.username}/`}>
<a className="text-info">@{post.username}</a>
</Link>{' '}
on {createdAt.toISOString()}
</span>
<ReactMarkdown>{post?.content}</ReactMarkdown>
</div>
);
}