Load mdx files, make navbar good
This commit is contained in:
@@ -20,6 +20,10 @@ const config = {
|
|||||||
protocol: "https",
|
protocol: "https",
|
||||||
hostname: "fly.storage.tigris.dev",
|
hostname: "fly.storage.tigris.dev",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
protocol: "https",
|
||||||
|
hostname: "img.daisyui.com",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export default function CvPage(): React.JSX.Element {
|
|||||||
Download
|
Download
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="divider divider-primary"></div>
|
<div className="divider divider-primary"></div>
|
||||||
<Cv />
|
<Cv />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export default function RootLayout({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<NavBar />
|
<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}
|
{children}
|
||||||
</main>
|
</main>
|
||||||
<Footer />
|
<Footer />
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
import { glob } from "glob";
|
import { glob } from "glob";
|
||||||
import dynamic, { type LoaderComponent } from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import type React from "react";
|
import type React from "react";
|
||||||
|
|
||||||
export const dynamicParams = false;
|
export const dynamicParams = false;
|
||||||
|
|
||||||
export async function generateStaticParams(): Promise<{ slug: string[] }[]> {
|
export async function generateStaticParams(): Promise<
|
||||||
|
{
|
||||||
|
slug: string[];
|
||||||
|
}[]
|
||||||
|
> {
|
||||||
const posts = await glob(
|
const posts = await glob(
|
||||||
`${process.cwd()}/src/markdown/posts/[[]...slug[]]/**/*.mdx`,
|
`${process.cwd()}/src/markdown/posts/[[]...slug[]]/**/*.mdx`,
|
||||||
{
|
{
|
||||||
@@ -12,21 +16,25 @@ export async function generateStaticParams(): Promise<{ slug: string[] }[]> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const slugs = posts.map((post) => ({
|
const postData = posts.map((post) => ({
|
||||||
slug: [post.split("/").at(-1)?.slice(0, -4)],
|
slug: [post.split("/").at(-1)?.slice(0, -4) ?? ""],
|
||||||
}));
|
}));
|
||||||
|
|
||||||
return slugs;
|
return await Promise.all(postData);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function Post({
|
export default async function Post({
|
||||||
params,
|
params,
|
||||||
}: {
|
}: {
|
||||||
params: Promise<{ slug: string[] }>;
|
params: {
|
||||||
|
slug: string[];
|
||||||
|
};
|
||||||
}): Promise<React.JSX.Element> {
|
}): Promise<React.JSX.Element> {
|
||||||
const mdxFile = (await import(
|
const Post = dynamic(
|
||||||
`../../../../markdown/posts/[...slug]/${(await params).slug.join("/")}.mdx`
|
async () =>
|
||||||
)) as LoaderComponent<unknown>;
|
import(
|
||||||
const Post = dynamic(() => mdxFile);
|
`../../../../markdown/posts/[...slug]/${(await params).slug.join("/")}.mdx`
|
||||||
|
),
|
||||||
|
);
|
||||||
return <Post />;
|
return <Post />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
import { glob } from "glob";
|
import { glob } from "glob";
|
||||||
import { unstable_cache } from "next/cache";
|
import { unstable_cache } from "next/cache";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { getBaseUrl } from "@/lib/base-url";
|
|
||||||
|
|
||||||
type postDetails = {
|
type postDetails = {
|
||||||
link: string;
|
link: string;
|
||||||
metadata: {
|
metadata: {
|
||||||
title: string;
|
title: string;
|
||||||
date: string;
|
date: string;
|
||||||
coverImage: string;
|
|
||||||
blurb: string;
|
blurb: string;
|
||||||
shortBlurb: string;
|
|
||||||
tags: string[];
|
tags: string[];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -29,13 +26,16 @@ async function loadPostDetails(): Promise<postDetails[]> {
|
|||||||
`../../../../src/markdown/posts/[...slug]/${slug.join("/")}.mdx`
|
`../../../../src/markdown/posts/[...slug]/${slug.join("/")}.mdx`
|
||||||
)) as postDetails;
|
)) as postDetails;
|
||||||
return {
|
return {
|
||||||
link: `${getBaseUrl()}/posts/${slug.join("/")}`,
|
link: `/posts/${slug.join("/")}`,
|
||||||
metadata: mdxFile.metadata,
|
metadata: mdxFile.metadata,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const postData = await Promise.all(loadPostData);
|
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"], {
|
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> {
|
export default async function Posts(): Promise<React.JSX.Element> {
|
||||||
const postDetails = await getPosts();
|
const postDetails = await getPosts();
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-6">
|
<div className="flex flex-wrap sm:grid-cols-2">
|
||||||
{postDetails.map((post) => {
|
{postDetails.map((post) => {
|
||||||
return (
|
return (
|
||||||
<div key={post.link}>
|
<div key={post.link} className="sm:max-w-1/2 grow">
|
||||||
<div className="card md:card-side">
|
<div className="card card-border m-2 bg-base-200 shadow-sm">
|
||||||
<h2>
|
<div className="card-body">
|
||||||
<Link href={post.link}>{post.metadata.title}</Link>
|
<h1 className="card-title">{post.metadata.title}</h1>
|
||||||
</h2>
|
<time dateTime={post.metadata.date}>{post.metadata.date}</time>
|
||||||
<div className="flex flex-row">
|
<div className="flex flex-row gap-2">
|
||||||
{post.metadata.tags.map((tag) => {
|
{post.metadata.tags.map((tag) => {
|
||||||
return (
|
return (
|
||||||
<div key={`${post.link}_${tag}`}>
|
<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">
|
<div className="badge badge-soft badge-info">{tag}</div>
|
||||||
{tag}
|
</div>
|
||||||
</span>
|
);
|
||||||
</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>
|
</div>
|
||||||
<p>{post.metadata.blurb}</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -25,9 +25,7 @@ export default async function LogIn(): Promise<React.JSX.Element | undefined> {
|
|||||||
>
|
>
|
||||||
<UserIcon
|
<UserIcon
|
||||||
className={`h-8 w-auto transition-colors ${
|
className={`h-8 w-auto transition-colors ${
|
||||||
session?.user
|
session?.user ? "stroke-warning" : ""
|
||||||
? "stroke-warning"
|
|
||||||
: ""
|
|
||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
<span className="sr-only">{session?.user ? "Log out" : "Log in"}</span>
|
<span className="sr-only">{session?.user ? "Log out" : "Log in"}</span>
|
||||||
|
|||||||
@@ -152,15 +152,9 @@ export default function Cv(): React.JSX.Element {
|
|||||||
</h1>
|
</h1>
|
||||||
<div className="flex flex-col gap-2 p-2">
|
<div className="flex flex-col gap-2 p-2">
|
||||||
<div className="grid grid-cols-3 border-b-2 pb-2">
|
<div className="grid grid-cols-3 border-b-2 pb-2">
|
||||||
<span className="border-r text-left">
|
<span className="border-r text-left">joemonk.co.uk</span>
|
||||||
joemonk.co.uk
|
<span className="border-x text-center">07757 017587</span>
|
||||||
</span>
|
<span className="border-l text-right">joemonk@hotmail.co.uk</span>
|
||||||
<span className="border-x text-center">
|
|
||||||
07757 017587
|
|
||||||
</span>
|
|
||||||
<span className="border-l text-right">
|
|
||||||
joemonk@hotmail.co.uk
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<p className="text-justify">
|
<p className="text-justify">
|
||||||
As a highly motivated and adaptive developer, my enthusiasm for
|
As a highly motivated and adaptive developer, my enthusiasm for
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export default function NavBarClient({
|
|||||||
}, [pathname, navigation]);
|
}, [pathname, navigation]);
|
||||||
|
|
||||||
return (
|
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}>
|
<LazyMotion features={domAnimation}>
|
||||||
<div className="mx-auto max-w-5xl px-4">
|
<div className="mx-auto max-w-5xl px-4">
|
||||||
<div className="relative flex h-16 items-center justify-between">
|
<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"
|
className="btn hidden items-center rounded border-2 border-primary/75 p-1 transition-colors hover:bg-primary/25 sm:flex"
|
||||||
href="/"
|
href="/"
|
||||||
>
|
>
|
||||||
<HomeModernIcon className="h-8 w-auto rounded-sm" />
|
<HomeModernIcon className="h-8 w-auto rounded-sm" />
|
||||||
</Link>
|
</Link>
|
||||||
<div className="ml-12 hidden gap-4 sm:flex">
|
<div className="ml-12 hidden gap-4 sm:flex">
|
||||||
{activeNavigation.map((item) => (
|
{activeNavigation.map((item) => (
|
||||||
|
|||||||
@@ -18,13 +18,13 @@ export default function PostHeader({
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h1>{metadata.title}</h1>
|
<h1>{metadata.title}</h1>
|
||||||
<div className="mb-2">{metadata.date}</div>
|
<time dateTime={metadata.date}>{metadata.date}</time>
|
||||||
<div className="mb-6">
|
<div className="mb-6 flex gap-2">
|
||||||
{metadata.tags.map((tag) => {
|
{metadata.tags.map((tag) => {
|
||||||
return (
|
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">
|
<div key={`${metadata.title}_tag_${tag}`}>
|
||||||
{tag}
|
<div className="badge badge-soft badge-info">{tag}</div>
|
||||||
</span>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import PostHeader from '@/app/_components/post-header';
|
|||||||
export const metadata = {
|
export const metadata = {
|
||||||
title: "Being a Developer",
|
title: "Being a Developer",
|
||||||
date: "2020-05-12",
|
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.",
|
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.",
|
shortBlurb: "My thoughts on being a developer vs being a programmer.",
|
||||||
tags: ["Blog", "Development"]
|
tags: ["Blog", "Development"]
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ export const metadata = {
|
|||||||
title: "Learning Kubernetes",
|
title: "Learning Kubernetes",
|
||||||
date: "2020-12-31",
|
date: "2020-12-31",
|
||||||
path: "/posts/learning-Kubernetes",
|
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\".",
|
blurb: "Learning how to use Kubenetes in an environment between \"Local testing\" and \"Full server deployments\".",
|
||||||
shortBlurb: "Finally getting around to \"learning\" Kubernetes.",
|
shortBlurb: "Finally getting around to \"learning\" Kubernetes.",
|
||||||
tags: ["Blog", "Development"],
|
tags: ["Blog", "Development"],
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import PostHeader from '@/app/_components/post-header';
|
|||||||
export const metadata = {
|
export const metadata = {
|
||||||
title: "Managing a Team Remotely",
|
title: "Managing a Team Remotely",
|
||||||
date: "2020-10-05",
|
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.",
|
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.",
|
shortBlurb: "My thoughts managing a team of developers with no physicality.",
|
||||||
tags: ["Blog", "Development"]
|
tags: ["Blog", "Development"]
|
||||||
|
|||||||
@@ -1,58 +1,59 @@
|
|||||||
|
/** biome-ignore-all lint/correctness/noUnknownProperty: Biome doesn't understand DaisyUI properties */
|
||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
@plugin "@tailwindcss/typography";
|
@plugin "@tailwindcss/typography";
|
||||||
|
|
||||||
|
|
||||||
@plugin "daisyui" {
|
@plugin "daisyui" {
|
||||||
themes: nord --default;
|
themes: nord --default;
|
||||||
};
|
}
|
||||||
|
|
||||||
@plugin "daisyui/theme" {
|
@plugin "daisyui/theme" {
|
||||||
/* Nicked from the vscode soft theme https://github.com/dracula/visual-studio-code/blob/master/src/dracula.yml */
|
/* Nicked from the vscode soft theme https://github.com/dracula/visual-studio-code/blob/master/src/dracula.yml */
|
||||||
name: "dracula-soft";
|
name: "dracula-soft";
|
||||||
default: false;
|
default: false;
|
||||||
prefersdark: false;
|
prefersdark: false;
|
||||||
color-scheme: "dark";
|
color-scheme: "dark";
|
||||||
|
|
||||||
/* --color-base-50: oklch(34.02% 0.027 276.05); */
|
/* --color-base-50: oklch(34.02% 0.027 276.05); */
|
||||||
--color-base-100: oklch(28.82% 0.022 277.51);
|
--color-base-100: oklch(28.82% 0.022 277.51);
|
||||||
--color-base-200: oklch(25.54% 0.019 280.49);
|
--color-base-200: oklch(25.54% 0.019 280.49);
|
||||||
--color-base-300: oklch(21.99% 0.014 278.80);
|
--color-base-300: oklch(21.99% 0.014 278.8);
|
||||||
--color-base-content: oklch(91% 0.020 278);
|
--color-base-content: oklch(91% 0.02 278);
|
||||||
|
|
||||||
--color-primary: oklch(88.263% 0.093 212.846);
|
--color-primary: oklch(88.263% 0.093 212.846);
|
||||||
--color-primary-content: oklch(17.652% 0.018 212.846);
|
--color-primary-content: oklch(88.263% 0.093 212.846);
|
||||||
--color-secondary: oklch(83.392% 0.124 66.558);
|
/* --color-primary-content: oklch(17.652% 0.018 212.846); */
|
||||||
--color-secondary-content: oklch(16.678% 0.024 66.558);
|
--color-secondary: oklch(83.392% 0.124 66.558);
|
||||||
--color-accent: oklch(74.202% 0.148 301.883);
|
--color-secondary-content: oklch(16.678% 0.024 66.558);
|
||||||
--color-accent-content: oklch(14.84% 0.029 301.883);
|
--color-accent: oklch(74.202% 0.148 301.883);
|
||||||
--color-neutral: oklch(38.94% 0.020 277.93);
|
--color-accent-content: oklch(14.84% 0.029 301.883);
|
||||||
--color-neutral-content: oklch(87.889% 0.006 275.524);
|
--color-neutral: oklch(38.94% 0.02 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);
|
|
||||||
|
|
||||||
--radius-selector: 0.5rem;
|
--color-info: oklch(75.461% 0.183 346.812);
|
||||||
--radius-field: 0.5rem;
|
--color-info-content: oklch(15.092% 0.036 346.812);
|
||||||
--radius-box: 0.5rem;
|
--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;
|
--radius-selector: 0.5rem;
|
||||||
--size-field: 0.25rem;
|
--radius-field: 0.5rem;
|
||||||
--border: 1px;
|
--radius-box: 0.5rem;
|
||||||
|
|
||||||
--depth: 0;
|
--size-selector: 0.25rem;
|
||||||
--noise: 0;
|
--size-field: 0.25rem;
|
||||||
|
--border: 1px;
|
||||||
|
|
||||||
|
--depth: 0;
|
||||||
|
--noise: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@theme {
|
@theme {
|
||||||
--font-sans:
|
--font-sans:
|
||||||
var(--font-inter), ui-sans-serif, system-ui, sans-serif,
|
var(--font-inter), ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji",
|
||||||
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
"Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||||
}
|
}
|
||||||
|
|
||||||
@custom-variant dark (&:where([data-theme=dracula-soft], [data-theme=dracula-soft] *));
|
@custom-variant dark (&:where([data-theme=dracula-soft], [data-theme=dracula-soft] *));
|
||||||
@@ -62,5 +63,5 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
:root .prose {
|
: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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user