Load mdx files, make navbar good
This commit is contained in:
@@ -20,6 +20,10 @@ const config = {
|
||||
protocol: "https",
|
||||
hostname: "fly.storage.tigris.dev",
|
||||
},
|
||||
{
|
||||
protocol: "https",
|
||||
hostname: "img.daisyui.com",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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 />
|
||||
|
||||
@@ -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 />;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) => (
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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"],
|
||||
|
||||
@@ -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"]
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user