diff --git a/components/blog/BlogPostLayout.tsx b/components/blog/BlogPostLayout.tsx index 539bfb6..b931c11 100644 --- a/components/blog/BlogPostLayout.tsx +++ b/components/blog/BlogPostLayout.tsx @@ -8,7 +8,8 @@ import { Image } from "./Image"; import { Footer } from "@/components/Footer"; import { Navigation } from "@/components/Navigation"; import { Separator } from "@/components/ui/separator"; -import { cn } from "@/lib/utils"; +import { BlogLinkType } from "@/lib/types"; +import { cn, filter } from "@/lib/utils"; export const SEO_TAGS_COLORS = { development: "bg-[#d946ef] text-black", @@ -35,6 +36,7 @@ export const BlogPostLayout = ({ includedImage, backLink = "/blog", hideComments, + relatedPostsPool, children, }: { title?: string; @@ -42,6 +44,7 @@ export const BlogPostLayout = ({ includedImage?: boolean; backLink?: string; hideComments?: boolean; + relatedPostsPool?: BlogLinkType[]; children: React.ReactNode; }) => { return ( diff --git a/lib/serverUtils.ts b/lib/serverUtils.ts new file mode 100644 index 0000000..aefd8d3 --- /dev/null +++ b/lib/serverUtils.ts @@ -0,0 +1,22 @@ +import { GetStaticProps } from "next"; + +import { getAllBlogPages } from "./pages"; +import { BlogLinkType, blogDateToIsoString } from "./types"; +import { sort } from "./utils"; +import { BlogSEOType } from "@/components/blog/BlogPostLayout"; + +export const postStaticProps = (async () => { + return { + props: { + posts: (await getAllBlogPages()) + .filter( + (seo: BlogSEOType & { href: string }) => + process.env.NODE_ENV !== "development" || !seo.draft, + ) + .sort(sort.byDate) + .map(blogDateToIsoString), + }, + }; +}) satisfies GetStaticProps<{ + posts: BlogLinkType[]; +}>; diff --git a/lib/types.ts b/lib/types.ts new file mode 100644 index 0000000..a08577d --- /dev/null +++ b/lib/types.ts @@ -0,0 +1,13 @@ +import { BlogSEOType } from "@/components/blog/BlogPostLayout"; + +export type BlogLinkType = Omit & { + date: string; + lastmod: string; + href: string; +}; + +export const blogDateToIsoString = (seo: BlogSEOType & { href: string }) => ({ + ...seo, + date: seo.date.toISOString(), + lastmod: seo.lastmod.toISOString(), +}); diff --git a/lib/utils.ts b/lib/utils.ts index 365058c..d2bec0a 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -1,6 +1,16 @@ import { type ClassValue, clsx } from "clsx"; import { twMerge } from "tailwind-merge"; -export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)); -} +export const cn = (...inputs: ClassValue[]) => twMerge(clsx(inputs)); + +export const sort = { + byDate: (a: { date: Date }, b: { date: Date }) => + b.date.getTime() - a.date.getTime(), +}; + +export const filter = { + arrayMatch: + (arr1: T[]) => + (item: T) => + arr1.includes(item), +}; diff --git a/pages/blog/index.tsx b/pages/blog/index.tsx index f79db95..8f51a74 100644 --- a/pages/blog/index.tsx +++ b/pages/blog/index.tsx @@ -4,31 +4,23 @@ import { NextSeo } from "next-seo"; import { ArticleCard } from "@/components/blog/ArticleCard"; import { BlogPostLayout, BlogSEOType } from "@/components/blog/BlogPostLayout"; import { getAllBlogPages } from "@/lib/pages"; +import { BlogLinkType, blogDateToIsoString } from "@/lib/types"; +import { sort } from "@/lib/utils"; export const getStaticProps = (async () => { return { props: { links: (await getAllBlogPages()) - .filter((seo: BlogSEOType & { href: string }) => - process.env.NODE_ENV !== "development" ? !seo.draft : true, + .filter( + (seo: BlogSEOType & { href: string }) => + process.env.NODE_ENV !== "development" || !seo.draft, ) - .sort( - (a: { date: Date }, b: { date: Date }) => - b.date.getTime() - a.date.getTime(), - ) - .map((seo: BlogSEOType & { href: string }) => ({ - ...seo, - date: seo.date.toISOString(), - lastmod: seo.lastmod.toISOString(), - })), + .sort(sort.byDate) + .map(blogDateToIsoString), }, }; }) satisfies GetStaticProps<{ - links: (Omit & { - date: string; - lastmod: string; - href: string; - })[]; + links: BlogLinkType[]; }>; export default function BlogIndexPage({ diff --git a/pages/blog/tag/[tag].tsx b/pages/blog/tag/[tag].tsx index 2f4572b..e04fcdc 100644 --- a/pages/blog/tag/[tag].tsx +++ b/pages/blog/tag/[tag].tsx @@ -8,17 +8,18 @@ import { SEO_TAGS_COLORS, } from "@/components/blog/BlogPostLayout"; import { getAllBlogPages } from "@/lib/pages"; +import { BlogLinkType, blogDateToIsoString } from "@/lib/types"; +import { sort } from "@/lib/utils"; export const getStaticPaths = (async () => { const tags = (await getAllBlogPages()) - .filter((seo: BlogSEOType & { href: string }) => - process.env.NODE_ENV !== "development" ? !seo.draft : true, + .filter( + (seo: BlogSEOType & { href: string }) => + process.env.NODE_ENV !== "development" || !seo.draft, ) .map((seo: BlogSEOType & { href: string }) => seo.tags) .flat() - .filter((tag, i, arr) => { - return arr.indexOf(tag) === i; - }); + .filter((tag, i, arr) => arr.indexOf(tag) === i); return { paths: tags.map(tag => ({ params: { tag } })), @@ -36,25 +37,14 @@ export const getStaticProps = (async context => { (process.env.NODE_ENV !== "development" ? !seo.draft : true) && seo.tags.includes(context.params!.tag), ) - .sort( - (a: { date: Date }, b: { date: Date }) => - b.date.getTime() - a.date.getTime(), - ) - .map((seo: BlogSEOType & { href: string }) => ({ - ...seo, - date: seo.date.toISOString(), - lastmod: seo.lastmod.toISOString(), - })), + .sort(sort.byDate) + .map(blogDateToIsoString), }, }; }) satisfies GetStaticProps< { tag: keyof typeof SEO_TAGS_COLORS; - links: (Omit & { - date: string; - lastmod: string; - href: string; - })[]; + links: BlogLinkType[]; }, { tag: keyof typeof SEO_TAGS_COLORS } >; diff --git a/pages/blog/thoughts-nodejs-backend.tsx b/pages/blog/thoughts-nodejs-backend.tsx index c4c5224..7dbe483 100644 --- a/pages/blog/thoughts-nodejs-backend.tsx +++ b/pages/blog/thoughts-nodejs-backend.tsx @@ -1,6 +1,8 @@ import { CodeTag } from "@/components/CodeTag"; import { BlogPostLayout, BlogSEOType } from "@/components/blog/BlogPostLayout"; import { H3 } from "@/components/blog/H3"; +import { postStaticProps } from "@/lib/serverUtils"; +import { BlogLinkType } from "@/lib/types"; export const seo: BlogSEOType = { title: "My thoughts on Node.js backend frameworks", @@ -10,12 +12,14 @@ export const seo: BlogSEOType = { lastmod: new Date("2024-11-02"), image: "/thoughts-nodejs-backend.svg", imageExtraClasses: "object-center object-scale-down bg-white w-full", - tags: ["development", "comparison", "opinion"], + tags: ["comparison"], }; -export default function BlogPostPage() { +export const getStaticProps = postStaticProps; + +export default function BlogPostPage({ posts }: { posts: BlogLinkType[] }) { return ( - +

For the longest time the only way to write backend code (after the dark times of pure PHP) was to use JavaScript on the frontend and something diff --git a/pages/blog/whats-up-with-deno.tsx b/pages/blog/whats-up-with-deno.tsx index eafdb4e..d351fcb 100644 --- a/pages/blog/whats-up-with-deno.tsx +++ b/pages/blog/whats-up-with-deno.tsx @@ -4,6 +4,8 @@ import { CodeTag } from "@/components/CodeTag"; import { BlogPostLayout, BlogSEOType } from "@/components/blog/BlogPostLayout"; import { H3 } from "@/components/blog/H3"; import { H4 } from "@/components/blog/H4"; +import { postStaticProps } from "@/lib/serverUtils"; +import { BlogLinkType } from "@/lib/types"; export const seo: BlogSEOType = { title: "What's up with Deno?", @@ -15,9 +17,11 @@ export const seo: BlogSEOType = { tags: ["development", "opinion"], }; -export default function BlogPostPage() { +export const getStaticProps = postStaticProps; + +export default function BlogPostPage({ posts }: { posts: BlogLinkType[] }) { return ( - +

Deno 2 was released a couple of weeks ago and most of us have seen the fun teasers and have heard of the new features. But why should it diff --git a/pages/blog/why-you-should-benchmark-your-code.tsx b/pages/blog/why-you-should-benchmark-your-code.tsx index 9d42af0..b170ff5 100644 --- a/pages/blog/why-you-should-benchmark-your-code.tsx +++ b/pages/blog/why-you-should-benchmark-your-code.tsx @@ -3,6 +3,8 @@ import { BlogPostLayout, BlogSEOType } from "@/components/blog/BlogPostLayout"; import { H3 } from "@/components/blog/H3"; import { H4 } from "@/components/blog/H4"; import { Link } from "@/components/blog/Link"; +import { postStaticProps } from "@/lib/serverUtils"; +import { BlogLinkType } from "@/lib/types"; export const seo: BlogSEOType = { draft: false, @@ -15,9 +17,11 @@ export const seo: BlogSEOType = { tags: ["development", "opinion", "testing", "benchmarking"], }; -export default function BlogPostPage() { +export const getStaticProps = postStaticProps; + +export default function BlogPostPage({ posts }: { posts: BlogLinkType[] }) { return ( - +

I started programming at a young age without any guidance, which meant for the longest time I had no idea what everyone meant by big O