Compare commits

..

5 Commits

Author SHA1 Message Date
neutrino2211
ac62ea0fe9 update 2025-12-17 11:03:29 +01:00
neutrino2211
69fa5b0a81 Update quote style and add markdown rendering 2025-10-12 16:43:47 +01:00
neutrino2211
ec86ffbee7 remove second thoughts link 2025-10-10 08:52:26 +01:00
neutrino2211
a7e54b358a fix links and build issues 2025-10-10 08:43:59 +01:00
neutrino2211
aeef3639a1 update links 2025-10-10 07:15:24 +01:00
13 changed files with 889 additions and 851 deletions

View File

@@ -11,7 +11,7 @@
"dependencies": { "dependencies": {
"@mdx-js/loader": "^3.1.1", "@mdx-js/loader": "^3.1.1",
"@mdx-js/react": "^3.1.1", "@mdx-js/react": "^3.1.1",
"@next/mdx": "^15.5.3", "@next/mdx": "^15.5.9",
"@types/mdx": "^2.0.13", "@types/mdx": "^2.0.13",
"gray-matter": "^4.0.3", "gray-matter": "^4.0.3",
"next": "15.5.3", "next": "15.5.3",
@@ -20,15 +20,15 @@
"react-markdown": "^10.1.0" "react-markdown": "^10.1.0"
}, },
"devDependencies": { "devDependencies": {
"@eslint/eslintrc": "^3", "@eslint/eslintrc": "^3.3.3",
"@tailwindcss/postcss": "^4", "@tailwindcss/postcss": "^4.1.18",
"@types/node": "^20", "@types/node": "^20.19.27",
"@types/react": "^19", "@types/react": "^19.2.7",
"@types/react-dom": "^19", "@types/react-dom": "^19.2.3",
"eslint": "^9", "eslint": "^9.39.2",
"eslint-config-next": "15.5.3", "eslint-config-next": "15.5.3",
"tailwindcss": "^4", "tailwindcss": "^4.1.18",
"typescript": "^5" "typescript": "^5.9.3"
}, },
"packageManager": "pnpm@10.11.0+sha512.6540583f41cc5f628eb3d9773ecee802f4f9ef9923cc45b69890fb47991d4b092964694ec3a4f738a420c918a333062c8b925d312f42e4f0c263eb603551f977" "packageManager": "pnpm@10.11.0+sha512.6540583f41cc5f628eb3d9773ecee802f4f9ef9923cc45b69890fb47991d4b092964694ec3a4f738a420c918a333062c8b925d312f42e4f0c263eb603551f977"
} }

1155
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,32 @@
@import "tailwindcss"; @import "tailwindcss";
:root { :root {
--background: #ffffff; /* Neo-brutalist muted color palette */
--foreground: #171717; --background: #FAF8F5;
--foreground: #3D3D3D;
--card-bg: #FEFDFB;
--border-color: #3D3D3D;
/* Muted accent colors */
--sage: #B8C5B3;
--sage-light: #CBD6C8;
--sage-dark: #A8B5A0;
--terracotta: #D4B5A0;
--terracotta-light: #E0C9B8;
--terracotta-dark: #C9A88E;
--blue-grey: #A5B4BE;
--blue-grey-light: #B8C5CE;
--blue-grey-dark: #9BAAB5;
--rose: #D4B5B8;
--rose-light: #E0C9CC;
--rose-dark: #C9A8AB;
--sand: #E8DCC8;
--sand-light: #F0E8D8;
--sand-dark: #DDD0BB;
} }
@theme inline { @theme inline {
@@ -14,8 +38,30 @@
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
:root { :root {
--background: #0a0a0a; --background: #1A1A1A;
--foreground: #ededed; --foreground: #E8E3D8;
--card-bg: #242424;
--border-color: #4D4D4D;
--sage: #8A9985;
--sage-light: #9BAA96;
--sage-dark: #7A8975;
--terracotta: #A38E7D;
--terracotta-light: #B29E8D;
--terracotta-dark: #937E6D;
--blue-grey: #7D8C95;
--blue-grey-light: #8D9CA5;
--blue-grey-dark: #6D7C85;
--rose: #A38E91;
--rose-light: #B39EA1;
--rose-dark: #937E81;
--sand: #B8AC98;
--sand-light: #C8BCA8;
--sand-dark: #A89C88;
} }
} }
@@ -24,3 +70,20 @@ body {
color: var(--foreground); color: var(--foreground);
font-family: Arial, Helvetica, sans-serif; font-family: Arial, Helvetica, sans-serif;
} }
/* Neo-brutalist shadow utilities */
.shadow-neo-brutal {
box-shadow: 5px 5px 0px var(--border-color);
}
.shadow-neo-brutal-hover {
box-shadow: 7px 7px 0px var(--border-color);
}
.shadow-brutal {
box-shadow: 5px 5px 0px var(--border-color);
}
.shadow-brutal-hover {
box-shadow: 7px 7px 0px var(--border-color);
}

View File

@@ -1,6 +1,7 @@
import type { Metadata } from "next"; import type { Metadata } from "next";
import ProjectsSection from "@/components/ProjectsSection"; import ProjectsSection from "@/components/ProjectsSection";
import Image from "next/image"; import Image from "next/image";
import Link from "next/link";
export const metadata: Metadata = { export const metadata: Metadata = {
title: "Home", title: "Home",
@@ -21,11 +22,11 @@ export const metadata: Metadata = {
export default function Home() { export default function Home() {
return ( return (
<div className="min-h-screen bg-gradient-to-br from-green-50 via-teal-50 to-blue-50 font-mono"> <div className="min-h-screen bg-[#FAF8F5] font-mono">
<div className="max-w-4xl mx-auto px-6 py-12"> <div className="max-w-4xl mx-auto px-6 py-12">
<header className="text-center mb-16"> <header className="text-center mb-16">
<div className="mb-8"> <div className="mb-8">
<div className="w-32 h-32 mx-auto bg-black rounded-full flex items-center justify-center border-4 border-green-300"> <div className="w-32 h-32 mx-auto bg-[#3D3D3D] rounded-full flex items-center justify-center border-[3px] border-[#B8C5B3]">
<Image <Image
src="/media/me/me.jpeg" src="/media/me/me.jpeg"
alt="Mainasara Tsowa" alt="Mainasara Tsowa"
@@ -35,49 +36,49 @@ export default function Home() {
/> />
</div> </div>
</div> </div>
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4 uppercase tracking-wide"> <h1 className="text-4xl md:text-5xl font-bold text-[#3D3D3D] mb-4 uppercase tracking-wide">
Mainasara Tsowa Mainasara Tsowa
</h1> </h1>
<p className="text-lg text-gray-700 max-w-2xl mx-auto leading-relaxed font-semibold"> <p className="text-lg text-[#5D5D5D] max-w-2xl mx-auto leading-relaxed font-semibold">
Developer & Cybersecurity Expert working on secure, elegant digital Developer & Cybersecurity Expert working on secure, elegant digital
solutions solutions
</p> </p>
</header> </header>
<nav className="mb-16"> <nav className="mb-16">
<div className="bg-white border-4 border-black rounded-none p-6 shadow-brutal"> <div className="bg-[#FEFDFB] border-[3px] border-[#3D3D3D] rounded-md p-6 shadow-brutal">
<ul className="flex flex-wrap justify-center gap-4 md:gap-8"> <ul className="flex flex-wrap justify-center gap-4 md:gap-8">
{/*<li> {/*<li>
<a <a
href="https://blog.mainasara.dev" href="https://blog.mainasara.dev"
className="text-black font-bold hover:bg-slate-200 px-4 py-2 transition-colors border-2 border-black hover:border-slate-400" className="text-[#3D3D3D] font-bold hover:bg-[#E8DCC8] px-4 py-2 transition-colors border-2 border-[#3D3D3D] hover:border-[#5D5D5D] rounded-sm"
> >
Blog Blog
</a> </a>
</li>*/} </li>*/}
<li> <li>
<a <Link
href="/digital-art" href="/digital-art"
className="text-black font-bold hover:bg-purple-200 px-4 py-2 transition-colors border-2 border-black hover:border-purple-400" className="text-[#3D3D3D] font-bold hover:bg-[#E0C9CC] px-4 py-2 transition-colors border-2 border-[#3D3D3D] hover:border-[#5D5D5D] rounded-sm"
> >
Digital Art Digital Art
</a> </Link>
</li> </li>
<li> <li>
<a <Link
href="/stories" href="/stories"
className="text-black font-bold hover:bg-yellow-200 px-4 py-2 transition-colors border-2 border-black hover:border-yellow-400" className="text-[#3D3D3D] font-bold hover:bg-[#F0E8D8] px-4 py-2 transition-colors border-2 border-[#3D3D3D] hover:border-[#5D5D5D] rounded-sm"
> >
Mini Stories Mini Stories
</a> </Link>
</li> </li>
<li> <li>
<a <Link
href="/thoughts" href="/thoughts"
className="text-black font-bold hover:bg-teal-200 px-4 py-2 transition-colors border-2 border-black hover:border-teal-400" className="text-[#3D3D3D] font-bold hover:bg-[#CBD6C8] px-4 py-2 transition-colors border-2 border-[#3D3D3D] hover:border-[#5D5D5D] rounded-sm"
> >
Thoughts Thoughts
</a> </Link>
</li> </li>
</ul> </ul>
</div> </div>
@@ -86,12 +87,12 @@ export default function Home() {
<main className="space-y-16"> <main className="space-y-16">
<section <section
id="about" id="about"
className="bg-white border-4 border-black rounded-none p-8 shadow-brutal" className="bg-[#FEFDFB] border-[3px] border-[#3D3D3D] rounded-md p-8 shadow-brutal"
> >
<h2 className="text-2xl font-bold text-gray-900 mb-6 text-center uppercase"> <h2 className="text-2xl font-bold text-[#3D3D3D] mb-6 text-center uppercase">
About About
</h2> </h2>
<p className="text-gray-800 leading-relaxed text-center max-w-3xl mx-auto font-semibold"> <p className="text-[#5D5D5D] leading-relaxed text-center max-w-3xl mx-auto font-semibold">
I&apos;m a passionate developer and cybersecurity expert who I&apos;m a passionate developer and cybersecurity expert who
believes in building beautiful, secure, and purposeful digital believes in building beautiful, secure, and purposeful digital
solutions. When I&apos;m not coding or exploring security tooling, solutions. When I&apos;m not coding or exploring security tooling,
@@ -102,46 +103,46 @@ export default function Home() {
<section <section
id="expertise" id="expertise"
className="bg-white border-4 border-black rounded-none p-8 shadow-brutal" className="bg-[#FEFDFB] border-[3px] border-[#3D3D3D] rounded-md p-8 shadow-brutal"
> >
<h2 className="text-2xl font-bold text-gray-900 mb-6 text-center uppercase"> <h2 className="text-2xl font-bold text-[#3D3D3D] mb-6 text-center uppercase">
Expertise Expertise
</h2> </h2>
<div className="grid md:grid-cols-2 gap-6"> <div className="grid md:grid-cols-2 gap-6">
<div className="bg-green-100 border-2 border-black rounded-none p-6"> <div className="bg-[#CBD6C8] border-2 border-[#3D3D3D] rounded-sm p-6">
<h3 className="text-lg font-bold text-gray-900 mb-3 uppercase"> <h3 className="text-lg font-bold text-[#3D3D3D] mb-3 uppercase">
Development Development
</h3> </h3>
<ul className="space-y-2 text-gray-800"> <ul className="space-y-2 text-[#5D5D5D]">
<li className="flex items-center"> <li className="flex items-center">
<span className="w-3 h-3 bg-black rounded-full mr-3"></span> <span className="w-3 h-3 bg-[#3D3D3D] rounded-full mr-3"></span>
Full-Stack Applications Full-Stack Applications
</li> </li>
<li className="flex items-center"> <li className="flex items-center">
<span className="w-3 h-3 bg-black rounded-full mr-3"></span> <span className="w-3 h-3 bg-[#3D3D3D] rounded-full mr-3"></span>
Clean Architecture Clean Architecture
</li> </li>
<li className="flex items-center"> <li className="flex items-center">
<span className="w-3 h-3 bg-black rounded-full mr-3"></span> <span className="w-3 h-3 bg-[#3D3D3D] rounded-full mr-3"></span>
Performance Optimization Performance Optimization
</li> </li>
</ul> </ul>
</div> </div>
<div className="bg-teal-100 border-2 border-black rounded-none p-6"> <div className="bg-[#B8C5CE] border-2 border-[#3D3D3D] rounded-sm p-6">
<h3 className="text-lg font-bold text-gray-900 mb-3 uppercase"> <h3 className="text-lg font-bold text-[#3D3D3D] mb-3 uppercase">
Cybersecurity Cybersecurity
</h3> </h3>
<ul className="space-y-2 text-gray-800"> <ul className="space-y-2 text-[#5D5D5D]">
<li className="flex items-center"> <li className="flex items-center">
<span className="w-3 h-3 bg-black rounded-full mr-3"></span> <span className="w-3 h-3 bg-[#3D3D3D] rounded-full mr-3"></span>
Security Tooling Security Tooling
</li> </li>
<li className="flex items-center"> <li className="flex items-center">
<span className="w-3 h-3 bg-black rounded-full mr-3"></span> <span className="w-3 h-3 bg-[#3D3D3D] rounded-full mr-3"></span>
Penetration Testing Penetration Testing
</li> </li>
<li className="flex items-center"> <li className="flex items-center">
<span className="w-3 h-3 bg-black rounded-full mr-3"></span> <span className="w-3 h-3 bg-[#3D3D3D] rounded-full mr-3"></span>
Security Architecture Security Architecture
</li> </li>
</ul> </ul>
@@ -153,65 +154,65 @@ export default function Home() {
<section <section
id="writing" id="writing"
className="bg-white border-4 border-black rounded-none p-8 shadow-brutal" className="bg-[#FEFDFB] border-[3px] border-[#3D3D3D] rounded-md p-8 shadow-brutal"
> >
<h2 className="text-2xl font-bold text-gray-900 mb-6 text-center uppercase"> <h2 className="text-2xl font-bold text-[#3D3D3D] mb-6 text-center uppercase">
Creative Corner Creative Corner
</h2> </h2>
<div className="grid md:grid-cols-3 gap-6"> <div className="grid md:grid-cols-3 gap-6">
<a <Link
href="/digital-art" href="/digital-art"
className="bg-yellow-100 border-2 border-black rounded-none p-6 text-center hover:bg-yellow-200 transition-colors" className="bg-[#F0E8D8] border-2 border-[#3D3D3D] rounded-sm p-6 text-center hover:bg-[#E8DCC8] transition-colors"
> >
<div className="text-4xl mb-3">🎨</div> <div className="text-4xl mb-3">🎨</div>
<h3 className="text-lg font-bold text-gray-900 mb-2 uppercase"> <h3 className="text-lg font-bold text-[#3D3D3D] mb-2 uppercase">
Digital Art Digital Art
</h3> </h3>
<p className="text-gray-800 text-sm"> <p className="text-[#5D5D5D] text-sm">
Someone messing around with colors and shapes. Someone messing around with colors and shapes.
</p> </p>
</a> </Link>
<a <Link
href="/stories" href="/stories"
className="bg-green-100 border-2 border-black rounded-none p-6 text-center hover:bg-green-200 transition-colors" className="bg-[#CBD6C8] border-2 border-[#3D3D3D] rounded-sm p-6 text-center hover:bg-[#B8C5B3] transition-colors"
> >
<div className="text-4xl mb-3">📝</div> <div className="text-4xl mb-3">📝</div>
<h3 className="text-lg font-bold text-gray-900 mb-2 uppercase"> <h3 className="text-lg font-bold text-[#3D3D3D] mb-2 uppercase">
Mini Stories Mini Stories
</h3> </h3>
<p className="text-gray-800 text-sm"> <p className="text-[#5D5D5D] text-sm">
I like good narratives, so I try to imitate them. I like good narratives, so I try to imitate them.
</p> </p>
</a> </Link>
<a <Link
href="/thoughts" href="/thoughts"
className="bg-teal-100 border-2 border-black rounded-none p-6 text-center hover:bg-teal-200 transition-colors" className="bg-[#B8C5CE] border-2 border-[#3D3D3D] rounded-sm p-6 text-center hover:bg-[#A5B4BE] transition-colors"
> >
<div className="text-4xl mb-3">🌸</div> <div className="text-4xl mb-3">🌸</div>
<h3 className="text-lg font-bold text-gray-900 mb-2 uppercase"> <h3 className="text-lg font-bold text-[#3D3D3D] mb-2 uppercase">
Thoughts Thoughts
</h3> </h3>
<p className="text-gray-800 text-sm"> <p className="text-[#5D5D5D] text-sm">
Rants on technology, maybe something else. Rants on technology, maybe something else.
</p> </p>
</a> </Link>
</div> </div>
</section> </section>
<section <section
id="contact" id="contact"
className="bg-white border-4 border-black rounded-none p-8 shadow-brutal" className="bg-[#FEFDFB] border-[3px] border-[#3D3D3D] rounded-md p-8 shadow-brutal"
> >
<h2 className="text-2xl font-bold text-gray-900 mb-6 text-center uppercase"> <h2 className="text-2xl font-bold text-[#3D3D3D] mb-6 text-center uppercase">
Get In Touch Get In Touch
</h2> </h2>
<div className="text-center"> <div className="text-center">
<p className="text-gray-800 mb-6 font-semibold"> <p className="text-[#5D5D5D] mb-6 font-semibold">
Let&apos;s collaborate on something interesting Let&apos;s collaborate on something interesting
</p> </p>
<a <a
href="mailto:tsowamainasara@gmail.com" href="mailto:tsowamainasara@gmail.com"
className="inline-block bg-black text-white px-8 py-4 font-bold border-2 border-black hover:bg-white hover:text-black transition-colors" className="inline-block bg-[#3D3D3D] text-white px-8 py-4 font-bold border-2 border-[#3D3D3D] hover:bg-[#FEFDFB] hover:text-[#3D3D3D] transition-colors rounded-sm"
> >
SEND EMAIL SEND EMAIL
</a> </a>
@@ -222,8 +223,8 @@ export default function Home() {
<footer className="mt-20 text-center"> <footer className="mt-20 text-center">
<div className="flex justify-center space-x-6 mb-6"> <div className="flex justify-center space-x-6 mb-6">
<a <a
href="#" href="https://github.com/neutrino2211/"
className="text-black font-bold hover:text-green-600 transition-colors" className="text-[#3D3D3D] font-bold hover:text-[#B8C5B3] transition-colors"
> >
<span className="sr-only">GitHub</span> <span className="sr-only">GitHub</span>
<svg className="w-8 h-8" fill="currentColor" viewBox="0 0 24 24"> <svg className="w-8 h-8" fill="currentColor" viewBox="0 0 24 24">
@@ -235,8 +236,8 @@ export default function Home() {
</svg> </svg>
</a> </a>
<a <a
href="#" href="https://www.linkedin.com/in/mainasara-tsowa-17098b214/"
className="text-black font-bold hover:text-teal-600 transition-colors" className="text-[#3D3D3D] font-bold hover:text-[#A5B4BE] transition-colors"
> >
<span className="sr-only">LinkedIn</span> <span className="sr-only">LinkedIn</span>
<svg className="w-8 h-8" fill="currentColor" viewBox="0 0 24 24"> <svg className="w-8 h-8" fill="currentColor" viewBox="0 0 24 24">
@@ -244,8 +245,8 @@ export default function Home() {
</svg> </svg>
</a> </a>
<a <a
href="#" href="https://x.com/neutrino2211/"
className="text-black font-bold hover:text-blue-600 transition-colors" className="text-[#3D3D3D] font-bold hover:text-[#D4B5A0] transition-colors"
> >
<span className="sr-only">Twitter</span> <span className="sr-only">Twitter</span>
<svg className="w-8 h-8" fill="currentColor" viewBox="0 0 24 24"> <svg className="w-8 h-8" fill="currentColor" viewBox="0 0 24 24">
@@ -253,9 +254,9 @@ export default function Home() {
</svg> </svg>
</a> </a>
</div> </div>
<div className="bg-black text-white p-4 font-bold"> <div className="bg-[#3D3D3D] text-white p-4 font-bold rounded-md">
<p className="text-sm uppercase"> <p className="text-sm uppercase">
Built with Charm Crush, Z.AI GLM and some pastel Built with Charm Crush, Z.AI GLM and some muted colors
</p> </p>
</div> </div>
</footer> </footer>

View File

@@ -1,7 +1,7 @@
import { notFound } from 'next/navigation'; import { notFound } from "next/navigation";
import Link from 'next/link'; import Link from "next/link";
import { loadStories } from '@/utils/mdxLoader'; import { loadStories } from "@/utils/mdxLoader";
import { formatReadingTime } from '@/utils/readingTime'; import { formatReadingTime } from "@/utils/readingTime";
interface StoryPageProps { interface StoryPageProps {
params: { params: {
@@ -9,27 +9,30 @@ interface StoryPageProps {
}; };
} }
import fs from 'fs'; import fs from "fs";
import { Metadata } from "next";
export async function generateStaticParams() { export async function generateStaticParams() {
const storiesDirectory = process.cwd() + '/src/content/stories'; const storiesDirectory = process.cwd() + "/src/content/stories";
try { try {
const filenames = fs.readdirSync(storiesDirectory); const filenames = fs.readdirSync(storiesDirectory);
return filenames.map((filename: string) => ({ return filenames.map((filename: string) => ({
slug: filename.replace(/\.mdx$/, ''), slug: filename.replace(/\.mdx$/, ""),
})); }));
} catch { } catch {
return []; return [];
} }
} }
export async function generateMetadata({ params }: StoryPageProps) { export async function generateMetadata({
params,
}: StoryPageProps): Promise<Metadata> {
const story = await getStoryBySlug(params.slug); const story = await getStoryBySlug(params.slug);
if (!story) { if (!story) {
return { return {
title: 'Story Not Found', title: "Story Not Found",
}; };
} }
@@ -50,7 +53,9 @@ export async function generateMetadata({ params }: StoryPageProps) {
async function getStoryBySlug(slug: string) { async function getStoryBySlug(slug: string) {
const stories = await loadStories(); const stories = await loadStories();
return stories.find(story => story.id === slug.replace(/[^a-zA-Z0-9]/g, '-')); return stories.find(
(story) => story.id === slug.replace(/[^a-zA-Z0-9]/g, "-"),
);
} }
export default async function StoryPage({ params }: StoryPageProps) { export default async function StoryPage({ params }: StoryPageProps) {
@@ -61,29 +66,29 @@ export default async function StoryPage({ params }: StoryPageProps) {
} }
return ( return (
<div className="min-h-screen bg-gradient-to-br from-yellow-50 via-orange-50 to-red-50 font-mono"> <div className="min-h-screen bg-[#FAF8F5] font-mono">
<div className="max-w-4xl mx-auto px-6 py-12"> <div className="max-w-4xl mx-auto px-6 py-12">
<header className="text-center mb-16"> <header className="text-center mb-16">
<div className="mb-8"> <div className="mb-8">
<div className="w-32 h-32 mx-auto bg-black rounded-full flex items-center justify-center border-4 border-yellow-300"> <div className="w-32 h-32 mx-auto bg-[#3D3D3D] rounded-full flex items-center justify-center border-[3px] border-[#F0E8D8]">
<div className="text-4xl font-bold text-yellow-300">📝</div> <div className="text-4xl font-bold text-[#F0E8D8]">📝</div>
</div> </div>
</div> </div>
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4 uppercase tracking-wide"> <h1 className="text-4xl md:text-5xl font-bold text-[#3D3D3D] mb-4 uppercase tracking-wide">
Mini Stories Mini Stories
</h1> </h1>
<p className="text-lg text-gray-700 max-w-2xl mx-auto leading-relaxed font-semibold"> <p className="text-lg text-[#5D5D5D] max-w-2xl mx-auto leading-relaxed font-semibold">
Capturing moments in brief narratives Capturing moments in brief narratives
</p> </p>
</header> </header>
<nav className="mb-16"> <nav className="mb-16">
<div className="bg-white border-4 border-black rounded-none p-6 shadow-brutal"> <div className="bg-[#FEFDFB] border-[3px] border-[#3D3D3D] rounded-md p-6 shadow-brutal">
<ul className="flex flex-wrap justify-center gap-4 md:gap-8"> <ul className="flex flex-wrap justify-center gap-4 md:gap-8">
<li> <li>
<Link <Link
href="/" href="/"
className="text-black font-bold hover:bg-green-200 px-4 py-2 transition-colors border-2 border-black hover:border-green-400" className="text-[#3D3D3D] font-bold hover:bg-[#CBD6C8] px-4 py-2 transition-colors border-2 border-[#3D3D3D] hover:border-[#5D5D5D] rounded-sm"
> >
Home Home
</Link> </Link>
@@ -91,7 +96,7 @@ export default async function StoryPage({ params }: StoryPageProps) {
<li> <li>
<Link <Link
href="/digital-art" href="/digital-art"
className="text-black font-bold hover:bg-purple-200 px-4 py-2 transition-colors border-2 border-black hover:border-purple-400" className="text-[#3D3D3D] font-bold hover:bg-[#E0C9CC] px-4 py-2 transition-colors border-2 border-[#3D3D3D] hover:border-[#5D5D5D] rounded-sm"
> >
Digital Art Digital Art
</Link> </Link>
@@ -99,7 +104,7 @@ export default async function StoryPage({ params }: StoryPageProps) {
<li> <li>
<Link <Link
href="/stories" href="/stories"
className="border-yellow-200 bg-yellow-300 px-4 py-2 border-2 text-black" className="border-[#3D3D3D] bg-[#F0E8D8] px-4 py-2 border-2 text-[#3D3D3D] rounded-sm"
> >
All Stories All Stories
</Link> </Link>
@@ -107,7 +112,7 @@ export default async function StoryPage({ params }: StoryPageProps) {
<li> <li>
<Link <Link
href="/thoughts" href="/thoughts"
className="text-black font-bold hover:bg-teal-200 px-4 py-2 transition-colors border-2 border-black hover:border-teal-400" className="text-[#3D3D3D] font-bold hover:bg-[#B8C5CE] px-4 py-2 transition-colors border-2 border-[#3D3D3D] hover:border-[#5D5D5D] rounded-sm"
> >
Thoughts Thoughts
</Link> </Link>
@@ -117,28 +122,28 @@ export default async function StoryPage({ params }: StoryPageProps) {
</nav> </nav>
<main> <main>
<article className="bg-white border-4 border-black rounded-none p-8 shadow-brutal"> <article className="bg-[#FEFDFB] border-[3px] border-[#3D3D3D] rounded-md p-8 shadow-brutal">
<div className="mb-8"> <div className="mb-8">
<h1 className="text-3xl md:text-4xl font-bold text-gray-900 uppercase mb-4"> <h1 className="text-3xl md:text-4xl font-bold text-[#3D3D3D] uppercase mb-4">
{story.title} {story.title}
</h1> </h1>
<div className="flex gap-4 text-sm mb-6"> <div className="flex gap-4 text-sm mb-6">
<span className="bg-yellow-200 text-black px-3 py-1 border-2 border-black font-bold"> <span className="bg-[#F0E8D8] text-[#3D3D3D] px-3 py-1 border-2 border-[#3D3D3D] font-bold rounded-sm">
{formatReadingTime(story.readTime)} read {formatReadingTime(story.readTime)} read
</span> </span>
<span className="bg-gray-200 text-black px-3 py-1 border-2 border-black font-bold"> <span className="bg-[#E8DCC8] text-[#3D3D3D] px-3 py-1 border-2 border-[#3D3D3D] font-bold rounded-sm">
{new Date(story.createdAt).toLocaleDateString('en-US', { {new Date(story.createdAt).toLocaleDateString("en-US", {
year: 'numeric', year: "numeric",
month: 'long', month: "long",
day: 'numeric' day: "numeric",
})} })}
</span> </span>
</div> </div>
</div> </div>
<div className="prose prose-lg max-w-none"> <div className="prose prose-lg max-w-none">
<div className="text-gray-800 leading-relaxed whitespace-pre-line"> <div className="text-[#5D5D5D] leading-relaxed whitespace-pre-line">
{story.content} {story.content}
</div> </div>
</div> </div>
@@ -146,8 +151,8 @@ export default async function StoryPage({ params }: StoryPageProps) {
</main> </main>
<footer className="mt-20 text-center"> <footer className="mt-20 text-center">
<div className="bg-black text-white p-4 font-bold"> <div className="bg-[#3D3D3D] text-white p-4 font-bold rounded-md">
<p className="text-sm uppercase">Built with brutalist pastels</p> <p className="text-sm uppercase">Built with neo-brutalist muted colors</p>
</div> </div>
</footer> </footer>
</div> </div>

View File

@@ -21,29 +21,29 @@ export default async function StoriesPage() {
const stories = await getStories(); const stories = await getStories();
return ( return (
<div className="min-h-screen bg-gradient-to-br from-yellow-50 via-orange-50 to-red-50 font-mono"> <div className="min-h-screen bg-[#FAF8F5] font-mono">
<div className="max-w-4xl mx-auto px-6 py-12"> <div className="max-w-4xl mx-auto px-6 py-12">
<header className="text-center mb-16"> <header className="text-center mb-16">
<div className="mb-8"> <div className="mb-8">
<div className="w-32 h-32 mx-auto bg-black rounded-full flex items-center justify-center border-4 border-yellow-300"> <div className="w-32 h-32 mx-auto bg-[#3D3D3D] rounded-full flex items-center justify-center border-[3px] border-[#F0E8D8]">
<div className="text-4xl font-bold text-yellow-300">📝</div> <div className="text-4xl font-bold text-[#F0E8D8]">📝</div>
</div> </div>
</div> </div>
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4 uppercase tracking-wide"> <h1 className="text-4xl md:text-5xl font-bold text-[#3D3D3D] mb-4 uppercase tracking-wide">
Mini Stories Mini Stories
</h1> </h1>
<p className="text-lg text-gray-700 max-w-2xl mx-auto leading-relaxed font-semibold"> <p className="text-lg text-[#5D5D5D] max-w-2xl mx-auto leading-relaxed font-semibold">
Capturing moments in brief narratives Capturing moments in brief narratives
</p> </p>
</header> </header>
<nav className="mb-16"> <nav className="mb-16">
<div className="bg-white border-4 border-black rounded-none p-6 shadow-brutal"> <div className="bg-[#FEFDFB] border-[3px] border-[#3D3D3D] rounded-md p-6 shadow-brutal">
<ul className="flex flex-wrap justify-center gap-4 md:gap-8"> <ul className="flex flex-wrap justify-center gap-4 md:gap-8">
<li> <li>
<Link <Link
href="/" href="/"
className="text-black font-bold hover:bg-green-200 px-4 py-2 transition-colors border-2 border-black hover:border-green-400" className="text-[#3D3D3D] font-bold hover:bg-[#CBD6C8] px-4 py-2 transition-colors border-2 border-[#3D3D3D] hover:border-[#5D5D5D] rounded-sm"
> >
Home Home
</Link> </Link>
@@ -51,7 +51,7 @@ export default async function StoriesPage() {
<li> <li>
<Link <Link
href="/digital-art" href="/digital-art"
className="text-black font-bold hover:bg-purple-200 px-4 py-2 transition-colors border-2 border-black hover:border-purple-400" className="text-[#3D3D3D] font-bold hover:bg-[#E0C9CC] px-4 py-2 transition-colors border-2 border-[#3D3D3D] hover:border-[#5D5D5D] rounded-sm"
> >
Digital Art Digital Art
</Link> </Link>
@@ -59,7 +59,7 @@ export default async function StoriesPage() {
<li> <li>
<Link <Link
href="/stories" href="/stories"
className="border-yellow-200 bg-yellow-300 px-4 py-2 border-2 text-black" className="border-[#3D3D3D] bg-[#F0E8D8] px-4 py-2 border-2 text-[#3D3D3D] rounded-sm"
> >
Stories Stories
</Link> </Link>
@@ -67,7 +67,7 @@ export default async function StoriesPage() {
<li> <li>
<Link <Link
href="/thoughts" href="/thoughts"
className="text-black font-bold hover:bg-teal-200 px-4 py-2 transition-colors border-2 border-black hover:border-teal-400" className="text-[#3D3D3D] font-bold hover:bg-[#B8C5CE] px-4 py-2 transition-colors border-2 border-[#3D3D3D] hover:border-[#5D5D5D] rounded-sm"
> >
Thoughts Thoughts
</Link> </Link>
@@ -83,8 +83,8 @@ export default async function StoriesPage() {
</main> </main>
<footer className="mt-20 text-center"> <footer className="mt-20 text-center">
<div className="bg-black text-white p-4 font-bold"> <div className="bg-[#3D3D3D] text-white p-4 font-bold rounded-md">
<p className="text-sm uppercase">Built with brutalist pastels</p> <p className="text-sm uppercase">Built with neo-brutalist muted colors</p>
</div> </div>
</footer> </footer>
</div> </div>

View File

@@ -1,7 +1,7 @@
import { notFound } from 'next/navigation'; import { notFound } from "next/navigation";
import Link from 'next/link'; import Link from "next/link";
import { loadThoughts } from '@/utils/mdxLoader'; import { loadThoughts } from "@/utils/mdxLoader";
import { formatReadingTime } from '@/utils/readingTime'; import { formatReadingTime } from "@/utils/readingTime";
interface ThoughtPageProps { interface ThoughtPageProps {
params: { params: {
@@ -9,27 +9,31 @@ interface ThoughtPageProps {
}; };
} }
import fs from 'fs'; import fs from "fs";
import { Metadata } from "next";
import Markdown from "react-markdown";
export async function generateStaticParams() { export async function generateStaticParams() {
const thoughtsDirectory = process.cwd() + '/src/content/thoughts'; const thoughtsDirectory = process.cwd() + "/src/content/thoughts";
try { try {
const filenames = fs.readdirSync(thoughtsDirectory); const filenames = fs.readdirSync(thoughtsDirectory);
return filenames.map((filename: string) => ({ return filenames.map((filename: string) => ({
slug: filename.replace(/\.mdx$/, ''), slug: filename.replace(/\.mdx$/, ""),
})); }));
} catch { } catch {
return []; return [];
} }
} }
export async function generateMetadata({ params }: ThoughtPageProps) { export async function generateMetadata({
params,
}: ThoughtPageProps): Promise<Metadata> {
const thought = await getThoughtBySlug(params.slug); const thought = await getThoughtBySlug(params.slug);
if (!thought) { if (!thought) {
return { return {
title: 'Thought Not Found', title: "Thought Not Found",
}; };
} }
@@ -50,7 +54,9 @@ export async function generateMetadata({ params }: ThoughtPageProps) {
async function getThoughtBySlug(slug: string) { async function getThoughtBySlug(slug: string) {
const thoughts = await loadThoughts(); const thoughts = await loadThoughts();
return thoughts.find(thought => thought.id === slug.replace(/[^a-zA-Z0-9]/g, '-')); return thoughts.find(
(thought) => thought.id === slug.replace(/[^a-zA-Z0-9]/g, "-"),
);
} }
export default async function ThoughtPage({ params }: ThoughtPageProps) { export default async function ThoughtPage({ params }: ThoughtPageProps) {
@@ -61,29 +67,29 @@ export default async function ThoughtPage({ params }: ThoughtPageProps) {
} }
return ( return (
<div className="min-h-screen bg-gradient-to-br from-teal-50 via-green-50 to-blue-50 font-mono"> <div className="min-h-screen bg-[#FAF8F5] font-mono">
<div className="max-w-4xl mx-auto px-6 py-12"> <div className="max-w-4xl mx-auto px-6 py-12">
<header className="text-center mb-16"> <header className="text-center mb-16">
<div className="mb-8"> <div className="mb-8">
<div className="w-32 h-32 mx-auto bg-black rounded-full flex items-center justify-center border-4 border-teal-300"> <div className="w-32 h-32 mx-auto bg-[#3D3D3D] rounded-full flex items-center justify-center border-[3px] border-[#B8C5CE]">
<div className="text-4xl font-bold text-teal-300">🌸</div> <div className="text-4xl font-bold text-[#B8C5CE]">🌸</div>
</div> </div>
</div> </div>
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4 uppercase tracking-wide"> <h1 className="text-4xl md:text-5xl font-bold text-[#3D3D3D] mb-4 uppercase tracking-wide">
Thoughts Thoughts
</h1> </h1>
<p className="text-lg text-gray-700 max-w-2xl mx-auto leading-relaxed font-semibold"> <p className="text-lg text-[#5D5D5D] max-w-2xl mx-auto leading-relaxed font-semibold">
Reflections on technology and life Reflections on technology and life
</p> </p>
</header> </header>
<nav className="mb-16"> <nav className="mb-16">
<div className="bg-white border-4 border-black rounded-none p-6 shadow-brutal"> <div className="bg-[#FEFDFB] border-[3px] border-[#3D3D3D] rounded-md p-6 shadow-brutal">
<ul className="flex flex-wrap justify-center gap-4 md:gap-8"> <ul className="flex flex-wrap justify-center gap-4 md:gap-8">
<li> <li>
<Link <Link
href="/" href="/"
className="text-black font-bold hover:bg-green-200 px-4 py-2 transition-colors border-2 border-black hover:border-green-400" className="text-[#3D3D3D] font-bold hover:bg-[#CBD6C8] px-4 py-2 transition-colors border-2 border-[#3D3D3D] hover:border-[#5D5D5D] rounded-sm"
> >
Home Home
</Link> </Link>
@@ -91,7 +97,7 @@ export default async function ThoughtPage({ params }: ThoughtPageProps) {
<li> <li>
<Link <Link
href="/digital-art" href="/digital-art"
className="text-black font-bold hover:bg-purple-200 px-4 py-2 transition-colors border-2 border-black hover:border-purple-400" className="text-[#3D3D3D] font-bold hover:bg-[#E0C9CC] px-4 py-2 transition-colors border-2 border-[#3D3D3D] hover:border-[#5D5D5D] rounded-sm"
> >
Digital Art Digital Art
</Link> </Link>
@@ -99,7 +105,7 @@ export default async function ThoughtPage({ params }: ThoughtPageProps) {
<li> <li>
<Link <Link
href="/stories" href="/stories"
className="text-black font-bold hover:bg-yellow-200 px-4 py-2 transition-colors border-2 border-black hover:border-yellow-400" className="text-[#3D3D3D] font-bold hover:bg-[#F0E8D8] px-4 py-2 transition-colors border-2 border-[#3D3D3D] hover:border-[#5D5D5D] rounded-sm"
> >
Stories Stories
</Link> </Link>
@@ -107,7 +113,7 @@ export default async function ThoughtPage({ params }: ThoughtPageProps) {
<li> <li>
<Link <Link
href="/thoughts" href="/thoughts"
className="border-teal-200 bg-teal-300 px-4 py-2 border-2 text-black" className="border-[#3D3D3D] bg-[#B8C5CE] px-4 py-2 border-2 text-[#3D3D3D] rounded-sm"
> >
All Thoughts All Thoughts
</Link> </Link>
@@ -117,40 +123,40 @@ export default async function ThoughtPage({ params }: ThoughtPageProps) {
</nav> </nav>
<main> <main>
<article className="bg-white border-4 border-black rounded-none p-8 shadow-brutal"> <article className="bg-[#FEFDFB] border-[3px] border-[#3D3D3D] rounded-md p-8 shadow-brutal">
<div className="mb-8"> <div className="mb-8">
<h1 className="text-3xl md:text-4xl font-bold text-gray-900 uppercase mb-4"> <h1 className="text-3xl md:text-4xl font-bold text-[#3D3D3D] uppercase mb-4">
{thought.title} {thought.title}
</h1> </h1>
<div className="flex gap-4 text-sm mb-6"> <div className="flex gap-4 text-sm mb-6">
<span className="bg-teal-200 text-black px-3 py-1 border-2 border-black font-bold"> <span className="bg-[#B8C5CE] text-[#3D3D3D] px-3 py-1 border-2 border-[#3D3D3D] font-bold rounded-sm">
{thought.category} {thought.category}
</span> </span>
<span className="bg-teal-200 text-black px-3 py-1 border-2 border-black font-bold"> <span className="bg-[#B8C5CE] text-[#3D3D3D] px-3 py-1 border-2 border-[#3D3D3D] font-bold rounded-sm">
{formatReadingTime(thought.readTime)} read {formatReadingTime(thought.readTime)} read
</span> </span>
<span className="bg-gray-200 text-black px-3 py-1 border-2 border-black font-bold"> <span className="bg-[#E8DCC8] text-[#3D3D3D] px-3 py-1 border-2 border-[#3D3D3D] font-bold rounded-sm">
{new Date(thought.createdAt).toLocaleDateString('en-US', { {new Date(thought.createdAt).toLocaleDateString("en-US", {
year: 'numeric', year: "numeric",
month: 'long', month: "long",
day: 'numeric' day: "numeric",
})} })}
</span> </span>
</div> </div>
</div> </div>
<div className="prose prose-lg max-w-none"> <div className="prose prose-lg max-w-none">
<div className="text-gray-800 leading-relaxed whitespace-pre-line"> <div className="text-[#5D5D5D] leading-relaxed whitespace-pre-line">
{thought.content} <Markdown>{thought.content}</Markdown>
</div> </div>
</div> </div>
</article> </article>
</main> </main>
<footer className="mt-20 text-center"> <footer className="mt-20 text-center">
<div className="bg-black text-white p-4 font-bold"> <div className="bg-[#3D3D3D] text-white p-4 font-bold rounded-md">
<p className="text-sm uppercase">Built with brutalist pastels</p> <p className="text-sm uppercase">Built with neo-brutalist muted colors</p>
</div> </div>
</footer> </footer>
</div> </div>

View File

@@ -21,29 +21,29 @@ export default async function ThoughtsPage() {
const thoughts = await getThoughts(); const thoughts = await getThoughts();
return ( return (
<div className="min-h-screen bg-gradient-to-br from-teal-50 via-green-50 to-blue-50 font-mono"> <div className="min-h-screen bg-[#FAF8F5] font-mono">
<div className="max-w-4xl mx-auto px-6 py-12"> <div className="max-w-4xl mx-auto px-6 py-12">
<header className="text-center mb-16"> <header className="text-center mb-16">
<div className="mb-8"> <div className="mb-8">
<div className="w-32 h-32 mx-auto bg-black rounded-full flex items-center justify-center border-4 border-teal-300"> <div className="w-32 h-32 mx-auto bg-[#3D3D3D] rounded-full flex items-center justify-center border-[3px] border-[#B8C5CE]">
<div className="text-4xl font-bold text-teal-300">🌸</div> <div className="text-4xl font-bold text-[#B8C5CE]">🌸</div>
</div> </div>
</div> </div>
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4 uppercase tracking-wide"> <h1 className="text-4xl md:text-5xl font-bold text-[#3D3D3D] mb-4 uppercase tracking-wide">
Thoughts Thoughts
</h1> </h1>
<p className="text-lg text-gray-700 max-w-2xl mx-auto leading-relaxed font-semibold"> <p className="text-lg text-[#5D5D5D] max-w-2xl mx-auto leading-relaxed font-semibold">
Reflections on technology and life Reflections on technology and life
</p> </p>
</header> </header>
<nav className="mb-16"> <nav className="mb-16">
<div className="bg-white border-4 border-black rounded-none p-6 shadow-brutal"> <div className="bg-[#FEFDFB] border-[3px] border-[#3D3D3D] rounded-md p-6 shadow-brutal">
<ul className="flex flex-wrap justify-center gap-4 md:gap-8"> <ul className="flex flex-wrap justify-center gap-4 md:gap-8">
<li> <li>
<Link <Link
href="/" href="/"
className="text-black font-bold hover:bg-green-200 px-4 py-2 transition-colors border-2 border-black hover:border-green-400" className="text-[#3D3D3D] font-bold hover:bg-[#CBD6C8] px-4 py-2 transition-colors border-2 border-[#3D3D3D] hover:border-[#5D5D5D] rounded-sm"
> >
Home Home
</Link> </Link>
@@ -51,7 +51,7 @@ export default async function ThoughtsPage() {
<li> <li>
<Link <Link
href="/digital-art" href="/digital-art"
className="text-black font-bold hover:bg-purple-200 px-4 py-2 transition-colors border-2 border-black hover:border-purple-400" className="text-[#3D3D3D] font-bold hover:bg-[#E0C9CC] px-4 py-2 transition-colors border-2 border-[#3D3D3D] hover:border-[#5D5D5D] rounded-sm"
> >
Digital Art Digital Art
</Link> </Link>
@@ -59,7 +59,7 @@ export default async function ThoughtsPage() {
<li> <li>
<Link <Link
href="/stories" href="/stories"
className="text-black font-bold hover:bg-yellow-200 px-4 py-2 transition-colors border-2 border-black hover:border-yellow-400" className="text-[#3D3D3D] font-bold hover:bg-[#F0E8D8] px-4 py-2 transition-colors border-2 border-[#3D3D3D] hover:border-[#5D5D5D] rounded-sm"
> >
Stories Stories
</Link> </Link>
@@ -67,7 +67,7 @@ export default async function ThoughtsPage() {
<li> <li>
<Link <Link
href="/thoughts" href="/thoughts"
className="border-teal-200 bg-teal-300 px-4 py-2 border-2 text-black" className="border-[#3D3D3D] bg-[#B8C5CE] px-4 py-2 border-2 text-[#3D3D3D] rounded-sm"
> >
Thoughts Thoughts
</Link> </Link>
@@ -83,8 +83,8 @@ export default async function ThoughtsPage() {
</main> </main>
<footer className="mt-20 text-center"> <footer className="mt-20 text-center">
<div className="bg-black text-white p-4 font-bold"> <div className="bg-[#3D3D3D] text-white p-4 font-bold rounded-md">
<p className="text-sm uppercase">Built with brutalist pastels</p> <p className="text-sm uppercase">Built with neo-brutalist muted colors</p>
</div> </div>
</footer> </footer>
</div> </div>

View File

@@ -29,29 +29,29 @@ export default function DigitalArt() {
}; };
return ( return (
<div className="min-h-screen bg-gradient-to-br from-purple-50 via-pink-50 to-yellow-50 font-mono"> <div className="min-h-screen bg-[#FAF8F5] font-mono">
<div className="max-w-4xl mx-auto px-6 py-12"> <div className="max-w-4xl mx-auto px-6 py-12">
<header className="text-center mb-16"> <header className="text-center mb-16">
<div className="mb-8"> <div className="mb-8">
<div className="w-32 h-32 mx-auto bg-black rounded-full flex items-center justify-center border-4 border-purple-300"> <div className="w-32 h-32 mx-auto bg-[#3D3D3D] rounded-full flex items-center justify-center border-[3px] border-[#E0C9CC]">
<div className="text-4xl font-bold text-purple-300">🎨</div> <div className="text-4xl font-bold text-[#E0C9CC]">🎨</div>
</div> </div>
</div> </div>
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4 uppercase tracking-wide"> <h1 className="text-4xl md:text-5xl font-bold text-[#3D3D3D] mb-4 uppercase tracking-wide">
Digital Art Digital Art
</h1> </h1>
<p className="text-lg text-gray-700 max-w-2xl mx-auto leading-relaxed font-semibold"> <p className="text-lg text-[#5D5D5D] max-w-2xl mx-auto leading-relaxed font-semibold">
Exploring creativity through digital canvases and new media Exploring creativity through digital canvases and new media
</p> </p>
</header> </header>
<nav className="mb-16"> <nav className="mb-16">
<div className="bg-white border-4 border-black rounded-none p-6 shadow-brutal"> <div className="bg-[#FEFDFB] border-[3px] border-[#3D3D3D] rounded-md p-6 shadow-brutal">
<ul className="flex flex-wrap justify-center gap-4 md:gap-8"> <ul className="flex flex-wrap justify-center gap-4 md:gap-8">
<li> <li>
<Link <Link
href="/" href="/"
className="text-black font-bold hover:bg-green-200 px-4 py-2 transition-colors border-2 border-black hover:border-green-400" className="text-[#3D3D3D] font-bold hover:bg-[#CBD6C8] px-4 py-2 transition-colors border-2 border-[#3D3D3D] hover:border-[#5D5D5D] rounded-sm"
> >
Home Home
</Link> </Link>
@@ -59,7 +59,7 @@ export default function DigitalArt() {
<li> <li>
<Link <Link
href="/digital-art" href="/digital-art"
className="border-purple-200 bg-purple-300 px-4 py-2 border-2 text-black" className="border-[#3D3D3D] bg-[#E0C9CC] px-4 py-2 border-2 text-[#3D3D3D] rounded-sm"
> >
Digital Art Digital Art
</Link> </Link>
@@ -67,7 +67,7 @@ export default function DigitalArt() {
<li> <li>
<Link <Link
href="/stories" href="/stories"
className="text-black font-bold hover:bg-yellow-200 px-4 py-2 transition-colors border-2 border-black hover:border-yellow-400" className="text-[#3D3D3D] font-bold hover:bg-[#F0E8D8] px-4 py-2 transition-colors border-2 border-[#3D3D3D] hover:border-[#5D5D5D] rounded-sm"
> >
Stories Stories
</Link> </Link>
@@ -75,7 +75,7 @@ export default function DigitalArt() {
<li> <li>
<Link <Link
href="/thoughts" href="/thoughts"
className="text-black font-bold hover:bg-teal-200 px-4 py-2 transition-colors border-2 border-black hover:border-teal-400" className="text-[#3D3D3D] font-bold hover:bg-[#B8C5CE] px-4 py-2 transition-colors border-2 border-[#3D3D3D] hover:border-[#5D5D5D] rounded-sm"
> >
Thoughts Thoughts
</Link> </Link>
@@ -88,12 +88,12 @@ export default function DigitalArt() {
{artItems.map((art) => ( {artItems.map((art) => (
<article <article
key={art.id} key={art.id}
className="bg-white border-4 border-black rounded-none p-8 shadow-brutal cursor-pointer hover:shadow-brutal-hover transition-shadow" className="bg-[#FEFDFB] border-[3px] border-[#3D3D3D] rounded-md p-8 shadow-brutal cursor-pointer hover:shadow-brutal-hover transition-shadow"
onClick={() => handleArtClick(art)} onClick={() => handleArtClick(art)}
> >
<div className="flex flex-col md:flex-row gap-8"> <div className="flex flex-col md:flex-row gap-8">
<div className="md:w-1/3"> <div className="md:w-1/3">
<div className="bg-purple-100 border-2 border-black rounded-none w-full h-48 flex items-center justify-center"> <div className="bg-[#E0C9CC] border-2 border-[#3D3D3D] rounded-sm w-full h-48 flex items-center justify-center">
<img <img
src={ src={
art.type === "collection" art.type === "collection"
@@ -106,20 +106,20 @@ export default function DigitalArt() {
</div> </div>
</div> </div>
<div className="md:w-2/3"> <div className="md:w-2/3">
<h2 className="text-2xl font-bold text-gray-900 mb-4 uppercase"> <h2 className="text-2xl font-bold text-[#3D3D3D] mb-4 uppercase">
{art.title} {art.title}
</h2> </h2>
<p className="text-gray-800 mb-4 leading-relaxed"> <p className="text-[#5D5D5D] mb-4 leading-relaxed">
{art.description} {art.description}
</p> </p>
<div className="flex flex-wrap gap-4 text-sm"> <div className="flex flex-wrap gap-4 text-sm">
<span className="bg-purple-200 text-black px-3 py-1 border-2 border-black font-bold"> <span className="bg-[#E0C9CC] text-[#3D3D3D] px-3 py-1 border-2 border-[#3D3D3D] font-bold rounded-sm">
{art.medium} {art.medium}
</span> </span>
<span className="bg-gray-200 text-black px-3 py-1 border-2 border-black font-bold"> <span className="bg-[#E8DCC8] text-[#3D3D3D] px-3 py-1 border-2 border-[#3D3D3D] font-bold rounded-sm">
{art.type === "collection" ? "Collection" : "Single"} {art.type === "collection" ? "Collection" : "Single"}
</span> </span>
<span className="bg-gray-200 text-black px-3 py-1 border-2 border-black font-bold"> <span className="bg-[#E8DCC8] text-[#3D3D3D] px-3 py-1 border-2 border-[#3D3D3D] font-bold rounded-sm">
{new Date(art.createdAt).toLocaleDateString("en-US", { {new Date(art.createdAt).toLocaleDateString("en-US", {
year: "numeric", year: "numeric",
month: "long", month: "long",
@@ -127,7 +127,7 @@ export default function DigitalArt() {
})} })}
</span> </span>
{art.type === "collection" && art.images && ( {art.type === "collection" && art.images && (
<span className="bg-blue-200 text-black px-3 py-1 border-2 border-black font-bold"> <span className="bg-[#B8C5CE] text-[#3D3D3D] px-3 py-1 border-2 border-[#3D3D3D] font-bold rounded-sm">
{art.images.length} images {art.images.length} images
</span> </span>
)} )}
@@ -139,8 +139,8 @@ export default function DigitalArt() {
</main> </main>
<footer className="mt-20 text-center"> <footer className="mt-20 text-center">
<div className="bg-black text-white p-4 font-bold"> <div className="bg-[#3D3D3D] text-white p-4 font-bold rounded-md">
<p className="text-sm uppercase">Built with brutalist pastels</p> <p className="text-sm uppercase">Built with neo-brutalist muted colors</p>
</div> </div>
</footer> </footer>
</div> </div>

View File

@@ -50,25 +50,25 @@ export default function ArtModal({
return ( return (
<div <div
className="fixed inset-0 bg-black bg-opacity-75 flex items-center justify-center z-50 p-4" className="fixed inset-0 bg-[#3D3D3D] bg-opacity-90 flex items-center justify-center z-50 p-4"
onClick={handleBackdropClick} onClick={handleBackdropClick}
> >
<div className="max-w-4xl w-full max-h-[90vh] overflow-y-auto"> <div className="max-w-4xl w-full max-h-[90vh] overflow-y-auto bg-[#FEFDFB] border-[3px] border-[#3D3D3D] rounded-md shadow-brutal">
<div className="p-6"> <div className="p-6">
<div className="flex justify-between items-start mb-6"> <div className="flex justify-between items-start mb-6">
<div> <div>
<h2 className="text-3xl font-bold text-gray-900 mb-2 uppercase"> <h2 className="text-3xl font-bold text-[#3D3D3D] mb-2 uppercase">
{artItem.title} {artItem.title}
</h2> </h2>
<p className="text-gray-700 mb-4">{artItem.description}</p> <p className="text-[#5D5D5D] mb-4">{artItem.description}</p>
<div className="flex gap-4 text-sm"> <div className="flex gap-4 text-sm flex-wrap">
<span className="text-purple-200 px-3 py-1 border-2 border-black font-bold"> <span className="bg-[#E0C9CC] text-[#3D3D3D] px-3 py-1 border-2 border-[#3D3D3D] font-bold rounded-sm">
{artItem.medium} {artItem.medium}
</span> </span>
<span className="text-gray-200 px-3 py-1 border-2 border-black font-bold"> <span className="bg-[#E8DCC8] text-[#3D3D3D] px-3 py-1 border-2 border-[#3D3D3D] font-bold rounded-sm">
{artItem.type === "collection" ? "Collection" : "Single"} {artItem.type === "collection" ? "Collection" : "Single"}
</span> </span>
<span className="text-gray-200 px-3 py-1 border-2 border-black font-bold"> <span className="bg-[#E8DCC8] text-[#3D3D3D] px-3 py-1 border-2 border-[#3D3D3D] font-bold rounded-sm">
{new Date(artItem.createdAt).toLocaleDateString("en-US", { {new Date(artItem.createdAt).toLocaleDateString("en-US", {
year: "numeric", year: "numeric",
month: "long", month: "long",
@@ -79,7 +79,7 @@ export default function ArtModal({
</div> </div>
<button <button
onClick={onClose} onClick={onClose}
className="text-2xl font-bold text-white w-10 h-10 flex items-center justify-center" className="text-3xl font-bold text-[#3D3D3D] w-10 h-10 flex items-center justify-center hover:text-[#E0C9CC] transition-colors"
> >
× ×
</button> </button>
@@ -87,7 +87,7 @@ export default function ArtModal({
{currentImage && ( {currentImage && (
<div className="relative"> <div className="relative">
<div className="w-full h-96 flex items-center justify-center mb-4"> <div className="w-full h-96 flex items-center justify-center mb-4 bg-[#E0C9CC] border-2 border-[#3D3D3D] rounded-sm">
<img <img
src={currentImage.url} src={currentImage.url}
alt={currentImage.title} alt={currentImage.title}
@@ -101,13 +101,13 @@ export default function ArtModal({
<> <>
<button <button
onClick={handlePrevImage} onClick={handlePrevImage}
className="absolute left-2 top-1/2 transform -translate-y-1/2 px-3 py-1 font-bold" className="absolute left-2 top-1/2 transform -translate-y-1/2 bg-[#FEFDFB] text-[#3D3D3D] border-2 border-[#3D3D3D] px-4 py-2 font-bold hover:bg-[#E0C9CC] transition-colors rounded-sm"
> >
</button> </button>
<button <button
onClick={handleNextImage} onClick={handleNextImage}
className="absolute right-2 top-1/2 transform -translate-y-1/2 px-3 py-1 font-bold" className="absolute right-2 top-1/2 transform -translate-y-1/2 bg-[#FEFDFB] text-[#3D3D3D] border-2 border-[#3D3D3D] px-4 py-2 font-bold hover:bg-[#E0C9CC] transition-colors rounded-sm"
> >
</button> </button>
@@ -115,11 +115,11 @@ export default function ArtModal({
)} )}
<div className="text-center"> <div className="text-center">
<h3 className="text-xl font-bold text-gray-900 mb-2"> <h3 className="text-xl font-bold text-[#3D3D3D] mb-2">
{currentImage.title || `Image ${currentImageIndex + 1}`} {currentImage.title || `Image ${currentImageIndex + 1}`}
</h3> </h3>
{currentImage.description && ( {currentImage.description && (
<p className="text-gray-700">{currentImage.description}</p> <p className="text-[#5D5D5D]">{currentImage.description}</p>
)} )}
</div> </div>
</div> </div>
@@ -129,7 +129,7 @@ export default function ArtModal({
artItem.images && artItem.images &&
artItem.images.length > 1 && ( artItem.images.length > 1 && (
<div className="mt-6"> <div className="mt-6">
<h4 className="text-lg font-bold mb-3 text-center"> <h4 className="text-lg font-bold mb-3 text-center text-[#3D3D3D] uppercase">
Collection Preview Collection Preview
</h4> </h4>
<div className="flex gap-2 overflow-x-auto pb-2 justify-center"> <div className="flex gap-2 overflow-x-auto pb-2 justify-center">
@@ -139,9 +139,9 @@ export default function ArtModal({
onClick={() => onImageChange(index)} onClick={() => onImageChange(index)}
className={`flex-shrink-0 w-20 h-20 border-2 ${ className={`flex-shrink-0 w-20 h-20 border-2 ${
index === currentImageIndex index === currentImageIndex
? "border-purple-500" ? "border-[#E0C9CC] bg-[#E0C9CC]"
: "border-black" : "border-[#3D3D3D] bg-[#F0E8D8]"
} rounded-none flex items-center justify-center`} } rounded-sm flex items-center justify-center hover:border-[#E0C9CC] transition-colors`}
> >
<img <img
src={image.url} src={image.url}

View File

@@ -13,33 +13,33 @@ export default function ExpandableStory({ story }: ExpandableStoryProps) {
const [isExpanded, setIsExpanded] = useState(false); const [isExpanded, setIsExpanded] = useState(false);
return ( return (
<article className="bg-white border-4 border-black rounded-none p-8 shadow-brutal"> <article className="bg-[#FEFDFB] border-[3px] border-[#3D3D3D] rounded-md p-8 shadow-brutal">
<div <div
className="cursor-pointer" className="cursor-pointer"
onClick={() => setIsExpanded(!isExpanded)} onClick={() => setIsExpanded(!isExpanded)}
> >
<div className="flex justify-between items-start mb-4"> <div className="flex justify-between items-start mb-4">
<h2 className="text-2xl font-bold text-gray-900 uppercase flex-1 pr-4"> <h2 className="text-2xl font-bold text-[#3D3D3D] uppercase flex-1 pr-4">
{story.title} {story.title}
</h2> </h2>
<div className="text-black font-bold text-lg bg-yellow-200 border-2 border-black px-3 py-1 whitespace-nowrap"> <div className="text-[#3D3D3D] font-bold text-lg bg-[#F0E8D8] border-2 border-[#3D3D3D] px-3 py-1 whitespace-nowrap rounded-sm">
{isExpanded ? '▼' : '▶'} {isExpanded ? '▼' : '▶'}
</div> </div>
</div> </div>
<p className="text-gray-600 italic mb-4">{story.excerpt}</p> <p className="text-[#6D6D6D] italic mb-4">{story.excerpt}</p>
<div className="flex gap-4 text-sm"> <div className="flex gap-4 text-sm">
<Link <Link
href={`/stories/${story.id}`} href={`/stories/${story.id}`}
className="bg-yellow-200 text-black px-3 py-1 border-2 border-black font-bold hover:bg-yellow-300 transition-colors" className="bg-[#F0E8D8] text-[#3D3D3D] px-3 py-1 border-2 border-[#3D3D3D] font-bold hover:bg-[#E8DCC8] transition-colors rounded-sm"
> >
Read Full Story Read Full Story
</Link> </Link>
<span className="bg-yellow-200 text-black px-3 py-1 border-2 border-black font-bold"> <span className="bg-[#F0E8D8] text-[#3D3D3D] px-3 py-1 border-2 border-[#3D3D3D] font-bold rounded-sm">
{formatReadingTime(story.readTime)} read {formatReadingTime(story.readTime)} read
</span> </span>
<span className="bg-gray-200 text-black px-3 py-1 border-2 border-black font-bold"> <span className="bg-[#E8DCC8] text-[#3D3D3D] px-3 py-1 border-2 border-[#3D3D3D] font-bold rounded-sm">
{new Date(story.createdAt).toLocaleDateString('en-US', { {new Date(story.createdAt).toLocaleDateString('en-US', {
year: 'numeric', year: 'numeric',
month: 'long', month: 'long',
@@ -54,9 +54,9 @@ export default function ExpandableStory({ story }: ExpandableStoryProps) {
isExpanded ? 'max-h-[2000px] opacity-100 mt-6' : 'max-h-0 opacity-0' isExpanded ? 'max-h-[2000px] opacity-100 mt-6' : 'max-h-0 opacity-0'
}`} }`}
> >
<div className="border-t-2 border-black pt-6"> <div className="border-t-2 border-[#3D3D3D] pt-6">
<div className="prose prose-lg max-w-none"> <div className="prose prose-lg max-w-none">
<div className="text-gray-800 leading-relaxed whitespace-pre-line"> <div className="text-[#5D5D5D] leading-relaxed whitespace-pre-line">
{story.content} {story.content}
</div> </div>
</div> </div>

View File

@@ -11,47 +11,47 @@ interface ExpandableThoughtProps {
} }
const categoryColors = { const categoryColors = {
technology: "bg-blue-200", technology: "bg-[#B8C5CE]",
life: "bg-green-200", life: "bg-[#CBD6C8]",
creativity: "bg-purple-200", creativity: "bg-[#E0C9CC]",
}; };
export default function ExpandableThought({ thought }: ExpandableThoughtProps) { export default function ExpandableThought({ thought }: ExpandableThoughtProps) {
const [isExpanded, setIsExpanded] = useState(false); const [isExpanded, setIsExpanded] = useState(false);
return ( return (
<article className="bg-white border-4 border-black rounded-none p-8 shadow-brutal"> <article className="bg-[#FEFDFB] border-[3px] border-[#3D3D3D] rounded-md p-8 shadow-brutal">
<div <div
className="cursor-pointer" className="cursor-pointer"
onClick={() => setIsExpanded(!isExpanded)} onClick={() => setIsExpanded(!isExpanded)}
> >
<div className="flex justify-between items-start mb-4"> <div className="flex justify-between items-start mb-4">
<h2 className="text-2xl font-bold text-gray-900 uppercase flex-1 pr-4"> <h2 className="text-2xl font-bold text-[#3D3D3D] uppercase flex-1 pr-4">
{thought.title} {thought.title}
</h2> </h2>
<div className="text-black font-bold text-lg bg-teal-200 border-2 border-black px-3 py-1 whitespace-nowrap"> <div className="text-[#3D3D3D] font-bold text-lg bg-[#B8C5CE] border-2 border-[#3D3D3D] px-3 py-1 whitespace-nowrap rounded-sm">
{isExpanded ? "▼" : "▶"} {isExpanded ? "▼" : "▶"}
</div> </div>
</div> </div>
<p className="text-gray-600 italic mb-4">{thought.excerpt}</p> <p className="text-[#6D6D6D] italic mb-4">{thought.excerpt}</p>
<div className="flex gap-4 text-sm"> <div className="flex gap-4 text-sm">
<Link <Link
href={`/thoughts/${thought.id}`} href={`/thoughts/${thought.id}`}
className="bg-teal-200 text-black px-3 py-1 border-2 border-black font-bold hover:bg-teal-300 transition-colors" className="bg-[#B8C5CE] text-[#3D3D3D] px-3 py-1 border-2 border-[#3D3D3D] font-bold hover:bg-[#A5B4BE] transition-colors rounded-sm"
> >
Read Full Thought Read Full Thought
</Link> </Link>
<span <span
className={`${categoryColors[thought.category]} text-black px-3 py-1 border-2 border-black font-bold`} className={`${categoryColors[thought.category]} text-[#3D3D3D] px-3 py-1 border-2 border-[#3D3D3D] font-bold rounded-sm`}
> >
{thought.category} {thought.category}
</span> </span>
<span className="bg-teal-200 text-black px-3 py-1 border-2 border-black font-bold"> <span className="bg-[#B8C5CE] text-[#3D3D3D] px-3 py-1 border-2 border-[#3D3D3D] font-bold rounded-sm">
{formatReadingTime(thought.readTime)} read {formatReadingTime(thought.readTime)} read
</span> </span>
<span className="bg-gray-200 text-black px-3 py-1 border-2 border-black font-bold"> <span className="bg-[#E8DCC8] text-[#3D3D3D] px-3 py-1 border-2 border-[#3D3D3D] font-bold rounded-sm">
{new Date(thought.createdAt).toLocaleDateString("en-GB", { {new Date(thought.createdAt).toLocaleDateString("en-GB", {
year: "numeric", year: "numeric",
month: "long", month: "long",
@@ -66,9 +66,9 @@ export default function ExpandableThought({ thought }: ExpandableThoughtProps) {
isExpanded ? "max-h-[2000px] opacity-100 mt-6" : "max-h-0 opacity-0" isExpanded ? "max-h-[2000px] opacity-100 mt-6" : "max-h-0 opacity-0"
}`} }`}
> >
<div className="border-t-2 border-black pt-6"> <div className="border-t-2 border-[#3D3D3D] pt-6">
<div className="prose prose-lg max-w-none"> <div className="prose prose-lg max-w-none">
<div className="text-gray-800 leading-relaxed whitespace-pre-line"> <div className="text-[#5D5D5D] leading-relaxed whitespace-pre-line">
<Markdown>{thought.content}</Markdown> <Markdown>{thought.content}</Markdown>
</div> </div>
</div> </div>

View File

@@ -4,17 +4,17 @@ import { useState } from "react";
import { projects, Project } from "@/data/projects"; import { projects, Project } from "@/data/projects";
const categoryColors = { const categoryColors = {
security: "bg-red-100 hover:border-red-400", security: "bg-[#E0C9B8] hover:border-[#5D5D5D]",
development: "bg-blue-100 hover:border-blue-400", development: "bg-[#B8C5CE] hover:border-[#5D5D5D]",
art: "bg-purple-100 hover:border-purple-400", art: "bg-[#E0C9CC] hover:border-[#5D5D5D]",
other: "bg-gray-100 hover:border-gray-400", other: "bg-[#E8DCC8] hover:border-[#5D5D5D]",
}; };
const categoryHoverColors = { const categoryHoverColors = {
security: "hover:text-red-600", security: "hover:text-[#C9A88E]",
development: "hover:text-blue-600", development: "hover:text-[#9BAAB5]",
art: "hover:text-purple-600", art: "hover:text-[#C9A8AB]",
other: "hover:text-gray-600", other: "hover:text-[#DDD0BB]",
}; };
export default function ProjectsSection() { export default function ProjectsSection() {
@@ -26,9 +26,9 @@ export default function ProjectsSection() {
return ( return (
<section <section
id="projects" id="projects"
className="bg-white border-4 border-black rounded-none p-8 shadow-brutal" className="bg-[#FEFDFB] border-[3px] border-[#3D3D3D] rounded-md p-8 shadow-brutal"
> >
<h2 className="text-2xl font-bold text-gray-900 mb-6 text-center uppercase"> <h2 className="text-2xl font-bold text-[#3D3D3D] mb-6 text-center uppercase">
Featured Projects Featured Projects
</h2> </h2>
@@ -54,7 +54,7 @@ export default function ProjectsSection() {
<div className="text-center mt-6"> <div className="text-center mt-6">
<button <button
onClick={() => setIsExpanded(!isExpanded)} onClick={() => setIsExpanded(!isExpanded)}
className="bg-black text-white px-6 py-3 font-bold border-2 border-black hover:bg-white hover:text-black transition-colors uppercase" className="bg-[#3D3D3D] text-white px-6 py-3 font-bold border-2 border-[#3D3D3D] hover:bg-[#FEFDFB] hover:text-[#3D3D3D] transition-colors uppercase rounded-sm"
> >
{isExpanded ? "Show Less" : "Read More"} {isExpanded ? "Show Less" : "Read More"}
</button> </button>
@@ -70,16 +70,16 @@ function ProjectCard({ project }: { project: Project }) {
return ( return (
<div <div
className={`${colorClass} border-2 border-black rounded-none p-6 transition-colors`} className={`${colorClass} border-2 border-[#3D3D3D] rounded-sm p-6 transition-colors`}
> >
<h3 className="text-lg font-bold text-gray-900 mb-2 uppercase"> <h3 className="text-lg font-bold text-[#3D3D3D] mb-2 uppercase">
{project.title} {project.title}
</h3> </h3>
<p className="text-gray-800 text-sm mb-3">{project.description}</p> <p className="text-[#5D5D5D] text-sm mb-3">{project.description}</p>
{project.link && ( {project.link && (
<a <a
href={project.link} href={project.link}
className={`text-black font-bold underline ${hoverColorClass} transition-colors`} className={`text-[#3D3D3D] font-bold underline ${hoverColorClass} transition-colors`}
> >
View Project View Project
</a> </a>