Load mdx files, make navbar good

This commit is contained in:
2025-07-15 00:54:33 +01:00
parent 813603282e
commit eb0907fdfd
13 changed files with 104 additions and 98 deletions

View File

@@ -20,6 +20,10 @@ const config = {
protocol: "https",
hostname: "fly.storage.tigris.dev",
},
{
protocol: "https",
hostname: "img.daisyui.com",
},
],
},
};

View File

@@ -9,7 +9,7 @@ export default function CvPage(): React.JSX.Element {
Download
</button>
</div>
<div className="divider divider-primary"></div>
<div className="divider divider-primary"></div>
<Cv />
</div>
);

View File

@@ -9,7 +9,7 @@ export default function RootLayout({
return (
<>
<NavBar />
<main className="bg-base-200 sm:border-x-2 dark:border-0 border-accent mx-auto w-full flex-1 px-6 py-4 align-middle lg:max-w-5xl">
<main className="mx-auto w-full flex-1 px-6 py-8 align-middle lg:max-w-5xl">
{children}
</main>
<Footer />

View File

@@ -1,10 +1,14 @@
import { glob } from "glob";
import dynamic, { type LoaderComponent } from "next/dynamic";
import dynamic from "next/dynamic";
import type React from "react";
export const dynamicParams = false;
export async function generateStaticParams(): Promise<{ slug: string[] }[]> {
export async function generateStaticParams(): Promise<
{
slug: string[];
}[]
> {
const posts = await glob(
`${process.cwd()}/src/markdown/posts/[[]...slug[]]/**/*.mdx`,
{
@@ -12,21 +16,25 @@ export async function generateStaticParams(): Promise<{ slug: string[] }[]> {
},
);
const slugs = posts.map((post) => ({
slug: [post.split("/").at(-1)?.slice(0, -4)],
const postData = posts.map((post) => ({
slug: [post.split("/").at(-1)?.slice(0, -4) ?? ""],
}));
return slugs;
return await Promise.all(postData);
}
export default async function Post({
params,
}: {
params: Promise<{ slug: string[] }>;
params: {
slug: string[];
};
}): Promise<React.JSX.Element> {
const mdxFile = (await import(
`../../../../markdown/posts/[...slug]/${(await params).slug.join("/")}.mdx`
)) as LoaderComponent<unknown>;
const Post = dynamic(() => mdxFile);
const Post = dynamic(
async () =>
import(
`../../../../markdown/posts/[...slug]/${(await params).slug.join("/")}.mdx`
),
);
return <Post />;
}

View File

@@ -1,16 +1,13 @@
import { glob } from "glob";
import { unstable_cache } from "next/cache";
import Link from "next/link";
import { getBaseUrl } from "@/lib/base-url";
type postDetails = {
link: string;
metadata: {
title: string;
date: string;
coverImage: string;
blurb: string;
shortBlurb: string;
tags: string[];
};
};
@@ -29,13 +26,16 @@ async function loadPostDetails(): Promise<postDetails[]> {
`../../../../src/markdown/posts/[...slug]/${slug.join("/")}.mdx`
)) as postDetails;
return {
link: `${getBaseUrl()}/posts/${slug.join("/")}`,
link: `/posts/${slug.join("/")}`,
metadata: mdxFile.metadata,
};
});
const postData = await Promise.all(loadPostData);
return postData;
return postData.sort(
(postA, postB) =>
Date.parse(postB.metadata.date) - Date.parse(postA.metadata.date),
);
}
const getPosts = unstable_cache(loadPostDetails, ["posts"], {
@@ -45,26 +45,30 @@ const getPosts = unstable_cache(loadPostDetails, ["posts"], {
export default async function Posts(): Promise<React.JSX.Element> {
const postDetails = await getPosts();
return (
<div className="flex flex-col gap-6">
<div className="flex flex-wrap sm:grid-cols-2">
{postDetails.map((post) => {
return (
<div key={post.link}>
<div className="card md:card-side">
<h2>
<Link href={post.link}>{post.metadata.title}</Link>
</h2>
<div className="flex flex-row">
{post.metadata.tags.map((tag) => {
return (
<div key={`${post.link}_${tag}`}>
<span className="me-2 select-none rounded border border-dracula-pink px-2.5 py-1 text-sm dark:bg-dracula-bg-darker dark:text-dracula-pink">
{tag}
</span>
</div>
);
})}
<div key={post.link} className="sm:max-w-1/2 grow">
<div className="card card-border m-2 bg-base-200 shadow-sm">
<div className="card-body">
<h1 className="card-title">{post.metadata.title}</h1>
<time dateTime={post.metadata.date}>{post.metadata.date}</time>
<div className="flex flex-row gap-2">
{post.metadata.tags.map((tag) => {
return (
<div key={`${post.link}_${tag}`}>
<div className="badge badge-soft badge-info">{tag}</div>
</div>
);
})}
</div>
<p>{post.metadata.blurb}</p>
<div className="card-actions justify-end pt-2">
<Link className="btn btn-primary" href={post.link}>
Read
</Link>
</div>
</div>
<p>{post.metadata.blurb}</p>
</div>
</div>
);

View File

@@ -25,9 +25,7 @@ export default async function LogIn(): Promise<React.JSX.Element | undefined> {
>
<UserIcon
className={`h-8 w-auto transition-colors ${
session?.user
? "stroke-warning"
: ""
session?.user ? "stroke-warning" : ""
}`}
/>
<span className="sr-only">{session?.user ? "Log out" : "Log in"}</span>

View File

@@ -152,15 +152,9 @@ export default function Cv(): React.JSX.Element {
</h1>
<div className="flex flex-col gap-2 p-2">
<div className="grid grid-cols-3 border-b-2 pb-2">
<span className="border-r text-left">
joemonk.co.uk
</span>
<span className="border-x text-center">
07757 017587
</span>
<span className="border-l text-right">
joemonk@hotmail.co.uk
</span>
<span className="border-r text-left">joemonk.co.uk</span>
<span className="border-x text-center">07757 017587</span>
<span className="border-l text-right">joemonk@hotmail.co.uk</span>
</div>
<p className="text-justify">
As a highly motivated and adaptive developer, my enthusiasm for

View File

@@ -43,7 +43,7 @@ export default function NavBarClient({
}, [pathname, navigation]);
return (
<nav className="border-accent border-b-2 bg-base-300">
<nav className="border-accent border-b-2 shadow-md dark:shadow-none dark:bg-base-300">
<LazyMotion features={domAnimation}>
<div className="mx-auto max-w-5xl px-4">
<div className="relative flex h-16 items-center justify-between">
@@ -64,7 +64,7 @@ export default function NavBarClient({
className="btn hidden items-center rounded border-2 border-primary/75 p-1 transition-colors hover:bg-primary/25 sm:flex"
href="/"
>
<HomeModernIcon className="h-8 w-auto rounded-sm" />
<HomeModernIcon className="h-8 w-auto rounded-sm" />
</Link>
<div className="ml-12 hidden gap-4 sm:flex">
{activeNavigation.map((item) => (

View File

@@ -18,13 +18,13 @@ export default function PostHeader({
return (
<>
<h1>{metadata.title}</h1>
<div className="mb-2">{metadata.date}</div>
<div className="mb-6">
<time dateTime={metadata.date}>{metadata.date}</time>
<div className="mb-6 flex gap-2">
{metadata.tags.map((tag) => {
return (
<span className="me-2 select-none rounded border border-dracula-pink px-2.5 py-1 text-sm dark:bg-dracula-bg-darker dark:text-dracula-pink">
{tag}
</span>
<div key={`${metadata.title}_tag_${tag}`}>
<div className="badge badge-soft badge-info">{tag}</div>
</div>
);
})}
</div>

View File

@@ -3,7 +3,6 @@ import PostHeader from '@/app/_components/post-header';
export const metadata = {
title: "Being a Developer",
date: "2020-05-12",
coverImage: "../images/being-a-developer/being-a-developer.jpg",
blurb: "My thoughts on being a \"developer\", being a \"programmer\" and the differences between them.",
shortBlurb: "My thoughts on being a developer vs being a programmer.",
tags: ["Blog", "Development"]

View File

@@ -4,7 +4,6 @@ export const metadata = {
title: "Learning Kubernetes",
date: "2020-12-31",
path: "/posts/learning-Kubernetes",
coverImage: "../images/learning-kubernetes/k8s.png",
blurb: "Learning how to use Kubenetes in an environment between \"Local testing\" and \"Full server deployments\".",
shortBlurb: "Finally getting around to \"learning\" Kubernetes.",
tags: ["Blog", "Development"],

View File

@@ -3,7 +3,6 @@ import PostHeader from '@/app/_components/post-header';
export const metadata = {
title: "Managing a Team Remotely",
date: "2020-10-05",
coverImage: "../images/managing-a-team-remotely/managing-a-team-remotely.jpg",
blurb: "With working remotely being a necessity at the moment, my thoughts on managing a team of developers with no physicality.",
shortBlurb: "My thoughts managing a team of developers with no physicality.",
tags: ["Blog", "Development"]

View File

@@ -1,58 +1,59 @@
/** biome-ignore-all lint/correctness/noUnknownProperty: Biome doesn't understand DaisyUI properties */
@import "tailwindcss";
@plugin "@tailwindcss/typography";
@plugin "daisyui" {
themes: nord --default;
};
themes: nord --default;
}
@plugin "daisyui/theme" {
/* Nicked from the vscode soft theme https://github.com/dracula/visual-studio-code/blob/master/src/dracula.yml */
name: "dracula-soft";
default: false;
prefersdark: false;
color-scheme: "dark";
/* Nicked from the vscode soft theme https://github.com/dracula/visual-studio-code/blob/master/src/dracula.yml */
name: "dracula-soft";
default: false;
prefersdark: false;
color-scheme: "dark";
/* --color-base-50: oklch(34.02% 0.027 276.05); */
--color-base-100: oklch(28.82% 0.022 277.51);
--color-base-200: oklch(25.54% 0.019 280.49);
--color-base-300: oklch(21.99% 0.014 278.80);
--color-base-content: oklch(91% 0.020 278);
/* --color-base-50: oklch(34.02% 0.027 276.05); */
--color-base-100: oklch(28.82% 0.022 277.51);
--color-base-200: oklch(25.54% 0.019 280.49);
--color-base-300: oklch(21.99% 0.014 278.8);
--color-base-content: oklch(91% 0.02 278);
--color-primary: oklch(88.263% 0.093 212.846);
--color-primary-content: oklch(17.652% 0.018 212.846);
--color-secondary: oklch(83.392% 0.124 66.558);
--color-secondary-content: oklch(16.678% 0.024 66.558);
--color-accent: oklch(74.202% 0.148 301.883);
--color-accent-content: oklch(14.84% 0.029 301.883);
--color-neutral: oklch(38.94% 0.020 277.93);
--color-neutral-content: oklch(87.889% 0.006 275.524);
--color-info: oklch(75.461% 0.183 346.812);
--color-info-content: oklch(15.092% 0.036 346.812);
--color-success: oklch(87.099% 0.219 148.024);
--color-success-content: oklch(17.419% 0.043 148.024);
--color-warning: oklch(95.533% 0.134 112.757);
--color-warning-content: oklch(15.106% 0.026 112.757);
--color-error: oklch(68.22% 0.206 24.43);
--color-error-content: oklch(13.644% 0.041 24.43);
--color-primary: oklch(88.263% 0.093 212.846);
--color-primary-content: oklch(88.263% 0.093 212.846);
/* --color-primary-content: oklch(17.652% 0.018 212.846); */
--color-secondary: oklch(83.392% 0.124 66.558);
--color-secondary-content: oklch(16.678% 0.024 66.558);
--color-accent: oklch(74.202% 0.148 301.883);
--color-accent-content: oklch(14.84% 0.029 301.883);
--color-neutral: oklch(38.94% 0.02 277.93);
--color-neutral-content: oklch(87.889% 0.006 275.524);
--radius-selector: 0.5rem;
--radius-field: 0.5rem;
--radius-box: 0.5rem;
--color-info: oklch(75.461% 0.183 346.812);
--color-info-content: oklch(15.092% 0.036 346.812);
--color-success: oklch(87.099% 0.219 148.024);
--color-success-content: oklch(17.419% 0.043 148.024);
--color-warning: oklch(95.533% 0.134 112.757);
--color-warning-content: oklch(15.106% 0.026 112.757);
--color-error: oklch(68.22% 0.206 24.43);
--color-error-content: oklch(13.644% 0.041 24.43);
--size-selector: 0.25rem;
--size-field: 0.25rem;
--border: 1px;
--radius-selector: 0.5rem;
--radius-field: 0.5rem;
--radius-box: 0.5rem;
--depth: 0;
--noise: 0;
--size-selector: 0.25rem;
--size-field: 0.25rem;
--border: 1px;
--depth: 0;
--noise: 0;
}
@theme {
--font-sans:
var(--font-inter), ui-sans-serif, system-ui, sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
var(--font-inter), ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji",
"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
}
@custom-variant dark (&:where([data-theme=dracula-soft], [data-theme=dracula-soft] *));
@@ -62,5 +63,5 @@
}
:root .prose {
--tw-prose-body: color-mix(in oklab, var(--color-base-content) 92%, #0000) !important;
}
--tw-prose-body: color-mix(in oklab, var(--color-base-content) 92%, #0000) !important;
}