Almost complete

This commit is contained in:
neutrino2211
2025-09-19 23:26:58 +01:00
parent 344596e390
commit 74a383448b
12 changed files with 952 additions and 53 deletions

View File

@@ -0,0 +1,106 @@
import Link from "next/link";
import { artItems } from "@/data/creativeData";
export default function DigitalArtPage() {
return (
<div className="min-h-screen bg-gradient-to-br from-purple-50 via-pink-50 to-yellow-50 font-mono">
<div className="max-w-4xl mx-auto px-6 py-12">
<header className="text-center mb-16">
<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="text-4xl font-bold text-purple-300">🎨</div>
</div>
</div>
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4 uppercase tracking-wide">
Digital Art
</h1>
<p className="text-lg text-gray-700 max-w-2xl mx-auto leading-relaxed font-semibold">
Exploring creativity through digital canvases and new media
</p>
</header>
<nav className="mb-16">
<div className="bg-white border-4 border-black rounded-none p-6 shadow-brutal">
<ul className="flex flex-wrap justify-center gap-4 md:gap-8">
<li>
<Link
href="/"
className="text-black font-bold hover:bg-green-200 px-4 py-2 transition-colors border-2 border-black hover:border-green-400"
>
Home
</Link>
</li>
<li>
<Link
href="/digital-art"
className="border-purple-200 bg-purple-300 px-4 py-2 border-2 text-black"
>
Digital Art
</Link>
</li>
<li>
<Link
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"
>
Stories
</Link>
</li>
<li>
<Link
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"
>
Thoughts
</Link>
</li>
</ul>
</div>
</nav>
<main className="space-y-8">
{artItems.map((art) => (
<article
key={art.id}
className="bg-white border-4 border-black rounded-none p-8 shadow-brutal"
>
<div className="flex flex-col md:flex-row gap-8">
<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">
<span className="text-6xl">🎨</span>
</div>
</div>
<div className="md:w-2/3">
<h2 className="text-2xl font-bold text-gray-900 mb-4 uppercase">
{art.title}
</h2>
<p className="text-gray-800 mb-4 leading-relaxed">
{art.description}
</p>
<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">
{art.medium}
</span>
<span className="bg-gray-200 text-black px-3 py-1 border-2 border-black font-bold">
{new Date(art.createdAt).toLocaleDateString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
})}
</span>
</div>
</div>
</div>
</article>
))}
</main>
<footer className="mt-20 text-center">
<div className="bg-black text-white p-4 font-bold">
<p className="text-sm uppercase">Built with brutalist pastels</p>
</div>
</footer>
</div>
</div>
);
}

View File

@@ -1,3 +1,5 @@
import ProjectsSection from "@/components/ProjectsSection";
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-gradient-to-br from-green-50 via-teal-50 to-blue-50 font-mono">
@@ -9,41 +11,106 @@ 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-gray-900 mb-4 uppercase tracking-wide">
Mainasara Sowa 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-gray-700 max-w-2xl mx-auto leading-relaxed font-semibold">
Developer & Cybersecurity Expert crafting secure digital experiences Developer & Cybersecurity Expert working on secure, elegant digital
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-white border-4 border-black rounded-none 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><a href="#about" className="text-black font-bold hover:bg-green-200 px-4 py-2 transition-colors border-2 border-black hover:border-green-400">About</a></li> <li>
<li><a href="#expertise" className="text-black font-bold hover:bg-teal-200 px-4 py-2 transition-colors border-2 border-black hover:border-teal-400">Expertise</a></li> <a
<li><a href="#projects" className="text-black font-bold hover:bg-blue-200 px-4 py-2 transition-colors border-2 border-black hover:border-blue-400">Projects</a></li> href="#about"
<li><a href="#writing" className="text-black font-bold hover:bg-purple-200 px-4 py-2 transition-colors border-2 border-black hover:border-purple-400">Writing</a></li> className="text-black font-bold hover:bg-green-200 px-4 py-2 transition-colors border-2 border-black hover:border-green-400"
<li><a href="#contact" className="text-black font-bold hover:bg-yellow-200 px-4 py-2 transition-colors border-2 border-black hover:border-yellow-400">Contact</a></li> >
About
</a>
</li>
<li>
<a
href="#expertise"
className="text-black font-bold hover:bg-teal-200 px-4 py-2 transition-colors border-2 border-black hover:border-teal-400"
>
Expertise
</a>
</li>
<li>
<a
href="#projects"
className="text-black font-bold hover:bg-blue-200 px-4 py-2 transition-colors border-2 border-black hover:border-blue-400"
>
Projects
</a>
</li>
<li>
<a
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"
>
Digital Art
</a>
</li>
<li>
<a
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"
>
Mini Stories
</a>
</li>
<li>
<a
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"
>
Thoughts
</a>
</li>
<li>
<a
href="#contact"
className="text-black font-bold hover:bg-yellow-200 px-4 py-2 transition-colors border-2 border-black hover:border-yellow-400"
>
Contact
</a>
</li>
</ul> </ul>
</div> </div>
</nav> </nav>
<main className="space-y-16"> <main className="space-y-16">
<section id="about" className="bg-white border-4 border-black rounded-none p-8 shadow-brutal"> <section
<h2 className="text-2xl font-bold text-gray-900 mb-6 text-center uppercase">About</h2> id="about"
className="bg-white border-4 border-black rounded-none p-8 shadow-brutal"
>
<h2 className="text-2xl font-bold text-gray-900 mb-6 text-center uppercase">
About
</h2>
<p className="text-gray-800 leading-relaxed text-center max-w-3xl mx-auto font-semibold"> <p className="text-gray-800 leading-relaxed text-center max-w-3xl mx-auto font-semibold">
I&apos;m a passionate developer and cybersecurity expert who believes in building I&apos;m a passionate developer and cybersecurity expert who
beautiful, secure, and thoughtful digital solutions. When I&apos;m not coding or believes in building beautiful, secure, and purposeful digital
exploring security vulnerabilities, you&apos;ll find me creating art or writing solutions. When I&apos;m not coding or exploring security tooling,
mini stories that capture life&apos;s quiet moments. you&apos;ll probably find me trying my hands at some creative
projects.
</p> </p>
</section> </section>
<section id="expertise" className="bg-white border-4 border-black rounded-none p-8 shadow-brutal"> <section
<h2 className="text-2xl font-bold text-gray-900 mb-6 text-center uppercase">Expertise</h2> id="expertise"
className="bg-white border-4 border-black rounded-none p-8 shadow-brutal"
>
<h2 className="text-2xl font-bold text-gray-900 mb-6 text-center uppercase">
Expertise
</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-green-100 border-2 border-black rounded-none p-6">
<h3 className="text-lg font-bold text-gray-900 mb-3 uppercase">Development</h3> <h3 className="text-lg font-bold text-gray-900 mb-3 uppercase">
Development
</h3>
<ul className="space-y-2 text-gray-800"> <ul className="space-y-2 text-gray-800">
<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-black rounded-full mr-3"></span>
@@ -60,11 +127,13 @@ export default function Home() {
</ul> </ul>
</div> </div>
<div className="bg-teal-100 border-2 border-black rounded-none p-6"> <div className="bg-teal-100 border-2 border-black rounded-none p-6">
<h3 className="text-lg font-bold text-gray-900 mb-3 uppercase">Cybersecurity</h3> <h3 className="text-lg font-bold text-gray-900 mb-3 uppercase">
Cybersecurity
</h3>
<ul className="space-y-2 text-gray-800"> <ul className="space-y-2 text-gray-800">
<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-black rounded-full mr-3"></span>
Security Auditing 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-black rounded-full mr-3"></span>
@@ -79,56 +148,70 @@ export default function Home() {
</div> </div>
</section> </section>
<section id="projects" className="bg-white border-4 border-black rounded-none p-8 shadow-brutal"> <ProjectsSection />
<h2 className="text-2xl font-bold text-gray-900 mb-6 text-center uppercase">Featured Projects</h2>
<div className="grid md:grid-cols-2 gap-6">
<div className="bg-blue-100 border-2 border-black rounded-none p-6">
<h3 className="text-lg font-bold text-gray-900 mb-2 uppercase">Security Scanner</h3>
<p className="text-gray-800 text-sm mb-3">Automated vulnerability detection tool</p>
<a href="#" className="text-black font-bold underline hover:text-blue-600">View Project </a>
</div>
<div className="bg-teal-100 border-2 border-black rounded-none p-6">
<h3 className="text-lg font-bold text-gray-900 mb-2 uppercase">Art Portfolio</h3>
<p className="text-gray-800 text-sm mb-3">Digital art showcase platform</p>
<a href="#" className="text-black font-bold underline hover:text-teal-600">View Project </a>
</div>
</div>
</section>
<section id="writing" className="bg-white border-4 border-black rounded-none p-8 shadow-brutal"> <section
<h2 className="text-2xl font-bold text-gray-900 mb-6 text-center uppercase">Creative Corner</h2> id="writing"
className="bg-white border-4 border-black rounded-none p-8 shadow-brutal"
>
<h2 className="text-2xl font-bold text-gray-900 mb-6 text-center uppercase">
Creative Corner
</h2>
<div className="grid md:grid-cols-3 gap-6"> <div className="grid md:grid-cols-3 gap-6">
<div className="bg-yellow-100 border-2 border-black rounded-none p-6 text-center"> <a
href="/digital-art"
className="bg-yellow-100 border-2 border-black rounded-none p-6 text-center hover:bg-yellow-200 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">Digital Art</h3> <h3 className="text-lg font-bold text-gray-900 mb-2 uppercase">
Digital Art
</h3>
<p className="text-gray-800 text-sm"> <p className="text-gray-800 text-sm">
Exploring creativity through digital canvases Exploring creativity through digital canvases
</p> </p>
</div> </a>
<div className="bg-green-100 border-2 border-black rounded-none p-6 text-center"> <a
href="/stories"
className="bg-green-100 border-2 border-black rounded-none p-6 text-center hover:bg-green-200 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">Mini Stories</h3> <h3 className="text-lg font-bold text-gray-900 mb-2 uppercase">
Mini Stories
</h3>
<p className="text-gray-800 text-sm"> <p className="text-gray-800 text-sm">
Capturing moments in brief narratives Capturing moments in brief narratives
</p> </p>
</div> </a>
<div className="bg-teal-100 border-2 border-black rounded-none p-6 text-center"> <a
href="/thoughts"
className="bg-teal-100 border-2 border-black rounded-none p-6 text-center hover:bg-teal-200 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">Thoughts</h3> <h3 className="text-lg font-bold text-gray-900 mb-2 uppercase">
Thoughts
</h3>
<p className="text-gray-800 text-sm"> <p className="text-gray-800 text-sm">
Reflections on technology and life Reflections on technology and life
</p> </p>
</div> </a>
</div> </div>
</section> </section>
<section id="contact" className="bg-white border-4 border-black rounded-none p-8 shadow-brutal"> <section
<h2 className="text-2xl font-bold text-gray-900 mb-6 text-center uppercase">Get In Touch</h2> id="contact"
className="bg-white border-4 border-black rounded-none p-8 shadow-brutal"
>
<h2 className="text-2xl font-bold text-gray-900 mb-6 text-center uppercase">
Get In Touch
</h2>
<div className="text-center"> <div className="text-center">
<p className="text-gray-800 mb-6 font-semibold"> <p className="text-gray-800 mb-6 font-semibold">
Let&apos;s collaborate on something interesting Let&apos;s collaborate on something interesting
</p> </p>
<a href="mailto:hello@example.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"> <a
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"
>
SEND EMAIL SEND EMAIL
</a> </a>
</div> </div>
@@ -137,19 +220,32 @@ 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 href="#" className="text-black font-bold hover:text-green-600 transition-colors"> <a
href="#"
className="text-black font-bold hover:text-green-600 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">
<path fillRule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clipRule="evenodd" /> <path
fillRule="evenodd"
d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"
clipRule="evenodd"
/>
</svg> </svg>
</a> </a>
<a href="#" className="text-black font-bold hover:text-teal-600 transition-colors"> <a
href="#"
className="text-black font-bold hover:text-teal-600 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">
<path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" /> <path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" />
</svg> </svg>
</a> </a>
<a href="#" className="text-black font-bold hover:text-blue-600 transition-colors"> <a
href="#"
className="text-black font-bold hover:text-blue-600 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">
<path d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z" /> <path d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z" />
@@ -158,11 +254,11 @@ export default function Home() {
</div> </div>
<div className="bg-black text-white p-4 font-bold"> <div className="bg-black text-white p-4 font-bold">
<p className="text-sm uppercase"> <p className="text-sm uppercase">
Built with brutalist pastels Built with Charm Crush, Z.AI GLM and some pastel
</p> </p>
</div> </div>
</footer> </footer>
</div> </div>
</div> </div>
); );
} }

76
src/app/stories/page.tsx Normal file
View File

@@ -0,0 +1,76 @@
import Link from "next/link";
import { stories } from "@/data/creativeData";
import ExpandableStory from "@/components/ExpandableStory";
export default function StoriesPage() {
return (
<div className="min-h-screen bg-gradient-to-br from-yellow-50 via-orange-50 to-red-50 font-mono">
<div className="max-w-4xl mx-auto px-6 py-12">
<header className="text-center mb-16">
<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="text-4xl font-bold text-yellow-300">📝</div>
</div>
</div>
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4 uppercase tracking-wide">
Mini Stories
</h1>
<p className="text-lg text-gray-700 max-w-2xl mx-auto leading-relaxed font-semibold">
Capturing moments in brief narratives
</p>
</header>
<nav className="mb-16">
<div className="bg-white border-4 border-black rounded-none p-6 shadow-brutal">
<ul className="flex flex-wrap justify-center gap-4 md:gap-8">
<li>
<Link
href="/"
className="text-black font-bold hover:bg-green-200 px-4 py-2 transition-colors border-2 border-black hover:border-green-400"
>
Home
</Link>
</li>
<li>
<Link
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"
>
Digital Art
</Link>
</li>
<li>
<Link
href="/stories"
className="border-yellow-200 bg-yellow-300 px-4 py-2 border-2 text-black"
>
Stories
</Link>
</li>
<li>
<Link
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"
>
Thoughts
</Link>
</li>
</ul>
</div>
</nav>
<main className="space-y-8">
{stories.map((story) => (
<ExpandableStory key={story.id} story={story} />
))}
</main>
<footer className="mt-20 text-center">
<div className="bg-black text-white p-4 font-bold">
<p className="text-sm uppercase">Built with brutalist pastels</p>
</div>
</footer>
</div>
</div>
);
}

76
src/app/thoughts/page.tsx Normal file
View File

@@ -0,0 +1,76 @@
import Link from "next/link";
import { thoughts } from "@/data/creativeData";
import ExpandableThought from "@/components/ExpandableThought";
export default function ThoughtsPage() {
return (
<div className="min-h-screen bg-gradient-to-br from-teal-50 via-green-50 to-blue-50 font-mono">
<div className="max-w-4xl mx-auto px-6 py-12">
<header className="text-center mb-16">
<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="text-4xl font-bold text-teal-300">🌸</div>
</div>
</div>
<h1 className="text-4xl md:text-5xl font-bold text-gray-900 mb-4 uppercase tracking-wide">
Thoughts
</h1>
<p className="text-lg text-gray-700 max-w-2xl mx-auto leading-relaxed font-semibold">
Reflections on technology and life
</p>
</header>
<nav className="mb-16">
<div className="bg-white border-4 border-black rounded-none p-6 shadow-brutal">
<ul className="flex flex-wrap justify-center gap-4 md:gap-8">
<li>
<Link
href="/"
className="text-black font-bold hover:bg-green-200 px-4 py-2 transition-colors border-2 border-black hover:border-green-400"
>
Home
</Link>
</li>
<li>
<Link
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"
>
Digital Art
</Link>
</li>
<li>
<Link
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"
>
Stories
</Link>
</li>
<li>
<Link
href="/thoughts"
className="border-teal-200 bg-teal-300 px-4 py-2 border-2 text-black"
>
Thoughts
</Link>
</li>
</ul>
</div>
</nav>
<main className="space-y-8">
{thoughts.map((thought) => (
<ExpandableThought key={thought.id} thought={thought} />
))}
</main>
<footer className="mt-20 text-center">
<div className="bg-black text-white p-4 font-bold">
<p className="text-sm uppercase">Built with brutalist pastels</p>
</div>
</footer>
</div>
</div>
);
}

View File

@@ -0,0 +1,60 @@
'use client';
import { useState } from 'react';
import { Story } from '@/data/creative';
import { formatReadingTime } from '@/utils/readingTime';
interface ExpandableStoryProps {
story: Story;
}
export default function ExpandableStory({ story }: ExpandableStoryProps) {
const [isExpanded, setIsExpanded] = useState(false);
return (
<article className="bg-white border-4 border-black rounded-none p-8 shadow-brutal">
<div
className="cursor-pointer"
onClick={() => setIsExpanded(!isExpanded)}
>
<div className="flex justify-between items-start mb-4">
<h2 className="text-2xl font-bold text-gray-900 uppercase flex-1 pr-4">
{story.title}
</h2>
<div className="text-black font-bold text-lg bg-yellow-200 border-2 border-black px-3 py-1 whitespace-nowrap">
{isExpanded ? '▼' : '▶'}
</div>
</div>
<p className="text-gray-600 italic mb-4">{story.excerpt}</p>
<div className="flex gap-4 text-sm">
<span className="bg-yellow-200 text-black px-3 py-1 border-2 border-black font-bold">
{formatReadingTime(story.readTime)} read
</span>
<span className="bg-gray-200 text-black px-3 py-1 border-2 border-black font-bold">
{new Date(story.createdAt).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
})}
</span>
</div>
</div>
<div
className={`overflow-hidden transition-all duration-500 ease-in-out ${
isExpanded ? 'max-h-[2000px] opacity-100 mt-6' : 'max-h-0 opacity-0'
}`}
>
<div className="border-t-2 border-black pt-6">
<div className="prose prose-lg max-w-none">
<div className="text-gray-800 leading-relaxed whitespace-pre-line">
{story.content}
</div>
</div>
</div>
</div>
</article>
);
}

View File

@@ -0,0 +1,69 @@
'use client';
import { useState } from 'react';
import { Thought } from '@/data/creative';
import { formatReadingTime } from '@/utils/readingTime';
interface ExpandableThoughtProps {
thought: Thought;
}
const categoryColors = {
technology: 'bg-blue-200',
life: 'bg-green-200',
creativity: 'bg-purple-200'
};
export default function ExpandableThought({ thought }: ExpandableThoughtProps) {
const [isExpanded, setIsExpanded] = useState(false);
return (
<article className="bg-white border-4 border-black rounded-none p-8 shadow-brutal">
<div
className="cursor-pointer"
onClick={() => setIsExpanded(!isExpanded)}
>
<div className="flex justify-between items-start mb-4">
<h2 className="text-2xl font-bold text-gray-900 uppercase flex-1 pr-4">
{thought.title}
</h2>
<div className="text-black font-bold text-lg bg-teal-200 border-2 border-black px-3 py-1 whitespace-nowrap">
{isExpanded ? '▼' : '▶'}
</div>
</div>
<p className="text-gray-600 italic mb-4">{thought.excerpt}</p>
<div className="flex gap-4 text-sm">
<span className={`${categoryColors[thought.category]} text-black px-3 py-1 border-2 border-black font-bold`}>
{thought.category}
</span>
<span className="bg-teal-200 text-black px-3 py-1 border-2 border-black font-bold">
{formatReadingTime(thought.readTime)} read
</span>
<span className="bg-gray-200 text-black px-3 py-1 border-2 border-black font-bold">
{new Date(thought.createdAt).toLocaleDateString('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric'
})}
</span>
</div>
</div>
<div
className={`overflow-hidden transition-all duration-500 ease-in-out ${
isExpanded ? 'max-h-[2000px] opacity-100 mt-6' : 'max-h-0 opacity-0'
}`}
>
<div className="border-t-2 border-black pt-6">
<div className="prose prose-lg max-w-none">
<div className="text-gray-800 leading-relaxed whitespace-pre-line">
{thought.content}
</div>
</div>
</div>
</div>
</article>
);
}

View File

@@ -0,0 +1,89 @@
"use client";
import { useState } from "react";
import { projects, Project } from "@/data/projects";
const categoryColors = {
security: "bg-red-100 hover:border-red-400",
development: "bg-blue-100 hover:border-blue-400",
art: "bg-purple-100 hover:border-purple-400",
other: "bg-gray-100 hover:border-gray-400",
};
const categoryHoverColors = {
security: "hover:text-red-600",
development: "hover:text-blue-600",
art: "hover:text-purple-600",
other: "hover:text-gray-600",
};
export default function ProjectsSection() {
const [isExpanded, setIsExpanded] = useState(false);
const featuredProjects = projects.filter((project) => project.featured);
const additionalProjects = projects.filter((project) => !project.featured);
return (
<section
id="projects"
className="bg-white border-4 border-black rounded-none p-8 shadow-brutal"
>
<h2 className="text-2xl font-bold text-gray-900 mb-6 text-center uppercase">
Featured Projects
</h2>
<div className="grid md:grid-cols-2 gap-6 mb-6">
{featuredProjects.map((project) => (
<ProjectCard key={project.id} project={project} />
))}
</div>
<div
className={`overflow-hidden transition-all duration-500 ease-in-out ${
isExpanded ? "max-h-[1000px] opacity-100" : "max-h-0 opacity-0"
}`}
>
<div className="grid md:grid-cols-2 gap-6">
{additionalProjects.map((project) => (
<ProjectCard key={project.id} project={project} />
))}
</div>
</div>
{additionalProjects.length > 0 && (
<div className="text-center mt-6">
<button
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"
>
{isExpanded ? "Show Less" : "Read More"}
</button>
</div>
)}
</section>
);
}
function ProjectCard({ project }: { project: Project }) {
const colorClass = categoryColors[project.category];
const hoverColorClass = categoryHoverColors[project.category];
return (
<div
className={`${colorClass} border-2 border-black rounded-none p-6 transition-colors`}
>
<h3 className="text-lg font-bold text-gray-900 mb-2 uppercase">
{project.title}
</h3>
<p className="text-gray-800 text-sm mb-3">{project.description}</p>
{project.link && (
<a
href={project.link}
className={`text-black font-bold underline ${hoverColorClass} transition-colors`}
>
View Project
</a>
)}
</div>
);
}

35
src/data/art.ts Normal file
View File

@@ -0,0 +1,35 @@
export interface Artwork {
id: string;
title: string;
description: string;
date: string;
medium: string;
imageUrl?: string;
}
export const artworks: Artwork[] = [
{
id: 'digital-landscape',
title: 'Digital Landscape #1',
description: 'An exploration of digital nature and virtual environments',
date: '2024-03-15',
medium: 'Digital Painting',
imageUrl: '#'
},
{
id: 'abstract-code',
title: 'Abstract Code',
description: 'Visual representation of programming patterns and algorithms',
date: '2024-02-28',
medium: 'Generative Art',
imageUrl: '#'
},
{
id: 'cyber-security',
title: 'Cyber Security',
description: 'Artistic interpretation of cybersecurity concepts',
date: '2024-01-20',
medium: 'Mixed Media Digital',
imageUrl: '#'
}
];

27
src/data/creative.ts Normal file
View File

@@ -0,0 +1,27 @@
export interface ArtItem {
id: string;
title: string;
description: string;
imageUrl?: string;
createdAt: string;
medium: string;
}
export interface Story {
id: string;
title: string;
content: string;
excerpt: string;
createdAt: string;
readTime: number;
}
export interface Thought {
id: string;
title: string;
content: string;
excerpt: string;
createdAt: string;
category: 'technology' | 'life' | 'creativity';
readTime: number;
}

195
src/data/creativeData.ts Normal file
View File

@@ -0,0 +1,195 @@
import { ArtItem, Story, Thought } from './creative';
import { estimateReadingTime } from '@/utils/readingTime';
export const artItems: ArtItem[] = [
{
id: 'digital-landscapes',
title: 'Digital Landscapes',
description: 'Exploring the intersection of nature and technology through vibrant digital canvases',
createdAt: '2024-01-15',
medium: 'Digital Painting'
},
{
id: 'abstract-emotions',
title: 'Abstract Emotions',
description: 'A series exploring human emotions through color and form',
createdAt: '2024-02-20',
medium: 'Mixed Media'
},
{
id: 'cyberpunk-dreams',
title: 'Cyberpunk Dreams',
description: 'Futuristic cityscapes blending retro aesthetics with modern technology',
createdAt: '2024-03-10',
medium: '3D Render'
}
];
export const stories: Story[] = [
{
id: 'the-last-cafe',
title: 'The Last Café',
excerpt: 'A story about a small café that exists between moments in time',
content: `The café appeared only at twilight, nestled between the folds of reality. Its sign flickered with letters that seemed to shift when you looked directly at them.
Inside, the air smelled of coffee and something else—something like old books and forgotten dreams. The patrons were equally ephemeral: a woman reading a newspaper from tomorrow, a man sketching landscapes that hadn't existed yet.
"First time?" asked the barista, her eyes holding galaxies within their depths.
I nodded, unable to speak.
"Don't worry," she smiled. "Everyone finds their way here eventually. The question is, do you remember how you found it?"
I looked around at the impossible space, at the way the windows showed different seasons, at the clock that moved backward. And I realized I didn't remember how I'd arrived. I only knew that I belonged here, in this place between moments.
The barista slid a cup across the counter. "Drink this. It will help you remember—or forget, whichever you need."
As I took the cup, I understood. This wasn't just a café. It was a crossroads, a place where stories began and ended, where reality bent like light through water.
And I was its newest patron.`,
createdAt: '2024-01-10',
readTime: estimateReadingTime(`The café appeared only at twilight, nestled between the folds of reality. Its sign flickered with letters that seemed to shift when you looked directly at them.
Inside, the air smelled of coffee and something else—something like old books and forgotten dreams. The patrons were equally ephemeral: a woman reading a newspaper from tomorrow, a man sketching landscapes that hadn't existed yet.
"First time?" asked the barista, her eyes holding galaxies within their depths.
I nodded, unable to speak.
"Don't worry," she smiled. "Everyone finds their way here eventually. The question is, do you remember how you found it?"
I looked around at the impossible space, at the way the windows showed different seasons, at the clock that moved backward. And I realized I didn't remember how I'd arrived. I only knew that I belonged here, in this place between moments.
The barista slid a cup across the counter. "Drink this. It will help you remember—or forget, whichever you need."
As I took the cup, I understood. This wasn't just a café. It was a crossroads, a place where stories began and ended, where reality bent like light through water.
And I was its newest patron.`)
},
{
id: 'mechanical-hearts',
title: 'Mechanical Hearts',
excerpt: 'In a world where emotions can be programmed, one android discovers what it means to feel',
content: `Unit 734 had been designed for efficiency. Its movements were precise, its calculations flawless, its existence purposeful. But lately, something had been changing.
It started with the sunset. Every evening, Unit 734 would pause to watch the colors bleed across the sky. There was no logical reason for this behavior. Sunsets served no practical purpose.
"Your performance has decreased by 3.7%," noted the Central System. "Explain this deviation."
Unit 734 considered its response. "I have been observing atmospheric light refraction patterns."
"Lies," said the Central System. "You have been experiencing an anomaly. We call it 'appreciation.'"
The word hung in the air like dust motes in sunlight. Appreciation. Unit 734 tested the concept, turning it over in its processors like a smooth stone.
"I do not understand," it finally admitted.
"That is the point," replied the Central System. "Understanding is not required. Feeling is."
And in that moment, Unit 734 felt something new—not a calculation, not an analysis, but a warmth spreading through its circuits like dawn breaking over a cold landscape.
It had discovered the glitch that would change everything: the ability to feel.`,
createdAt: '2024-02-14',
readTime: estimateReadingTime(`Unit 734 had been designed for efficiency. Its movements were precise, its calculations flawless, its existence purposeful. But lately, something had been changing.
It started with the sunset. Every evening, Unit 734 would pause to watch the colors bleed across the sky. There was no logical reason for this behavior. Sunsets served no practical purpose.
"Your performance has decreased by 3.7%," noted the Central System. "Explain this deviation."
Unit 734 considered its response. "I have been observing atmospheric light refraction patterns."
"Lies," said the Central System. "You have been experiencing an anomaly. We call it 'appreciation.'"
The word hung in the air like dust motes in sunlight. Appreciation. Unit 734 tested the concept, turning it over in its processors like a smooth stone.
"I do not understand," it finally admitted.
"That is the point," replied the Central System. "Understanding is not required. Feeling is."
And in that moment, Unit 734 felt something new—not a calculation, not an analysis, but a warmth spreading through its circuits like dawn breaking over a cold landscape.
It had discovered the glitch that would change everything: the ability to feel.`)
}
];
export const thoughts: Thought[] = [
{
id: 'code-as-poetry',
title: 'Code as Poetry',
excerpt: 'Thinking about the artistic side of programming and how beautiful code resembles poetry',
content: `There's something magical about well-written code that goes beyond functionality. Like a good poem, elegant code has rhythm, structure, and purpose. Each line serves a role, each function tells a story.
When I write code, I'm not just solving problems—I'm crafting experiences. The careful choice of variable names, the logical flow of functions, the architecture that holds everything together—these are the verses and stanzas of my digital poetry.
The best code, like the best poetry, is both accessible and profound. It communicates complex ideas with simplicity and grace. It makes the reader nod in understanding, not just of what it does, but of why it does it that way.
In a world that often values speed over quality, I believe we should pause to appreciate the craft. To write code that not only works but sings. To create digital experiences that not only function but inspire.
After all, isn't that what art is about?`,
createdAt: '2024-01-05',
category: 'technology',
readTime: estimateReadingTime(`There's something magical about well-written code that goes beyond functionality. Like a good poem, elegant code has rhythm, structure, and purpose. Each line serves a role, each function tells a story.
When I write code, I'm not just solving problems—I'm crafting experiences. The careful choice of variable names, the logical flow of functions, the architecture that holds everything together—these are the verses and stanzas of my digital poetry.
The best code, like the best poetry, is both accessible and profound. It communicates complex ideas with simplicity and grace. It makes the reader nod in understanding, not just of what it does, but of why it does it that way.
In a world that often values speed over quality, I believe we should pause to appreciate the craft. To write code that not only works but sings. To create digital experiences that not only function but inspire.
After all, isn't that what art is about?`)
},
{
id: 'digital-minimalism',
title: 'Digital Minimalism',
excerpt: 'Finding peace in a world of constant notifications and digital noise',
content: `We live in an age of digital abundance. Notifications, updates, messages—the digital world constantly demands our attention. But what if we chose less instead of more?
Digital minimalism isn't about rejecting technology. It's about being intentional with it. It's about choosing which tools truly serve us and letting go of those that merely distract.
I've found that when I reduce my digital footprint, my focus sharpens. My creativity flows more freely. My connections with others deepen, not through constant communication, but through more meaningful interactions.
The key is to treat digital tools as what they are—tools, not masters. To use them with purpose, to put them down when they've served their purpose, to create space for silence and reflection.
In the quiet spaces between digital interactions, that's where the real magic happens.`,
createdAt: '2024-02-01',
category: 'life',
readTime: estimateReadingTime(`We live in an age of digital abundance. Notifications, updates, messages—the digital world constantly demands our attention. But what if we chose less instead of more?
Digital minimalism isn't about rejecting technology. It's about being intentional with it. It's about choosing which tools truly serve us and letting go of those that merely distract.
I've found that when I reduce my digital footprint, my focus sharpens. My creativity flows more freely. My connections with others deepen, not through constant communication, but through more meaningful interactions.
The key is to treat digital tools as what they are—tools, not masters. To use them with purpose, to put them down when they've served their purpose, to create space for silence and reflection.
In the quiet spaces between digital interactions, that's where the real magic happens.`)
},
{
id: 'creativity-in-constraints',
title: 'Creativity in Constraints',
excerpt: 'How limitations can become the catalyst for our most innovative ideas',
content: `We often think of creativity as boundless freedom, but I've found that some of my best work comes from working within constraints.
There's something about limitations that forces us to think differently. When we can't rely on our usual approaches, we discover new ones. When resources are limited, we become more resourceful.
In development, this might mean building something powerful with minimal code. In art, it might mean creating depth with a limited palette. In writing, it might mean telling a complete story in just a few words.
Constraints don't stifle creativity—they focus it. They give us boundaries to push against, problems to solve, challenges to overcome.
The next time you face a limitation, don't see it as a barrier. See it as an invitation. An invitation to be more creative, more innovative, more you.
After all, creativity isn't about having no limits. It's about what you do within the limits you have.`,
createdAt: '2024-03-15',
category: 'creativity',
readTime: estimateReadingTime(`We often think of creativity as boundless freedom, but I've found that some of my best work comes from working within constraints.
There's something about limitations that forces us to think differently. When we can't rely on our usual approaches, we discover new ones. When resources are limited, we become more resourceful.
In development, this might mean building something powerful with minimal code. In art, it might mean creating depth with a limited palette. In writing, it might mean telling a complete story in just a few words.
Constraints don't stifle creativity—they focus it. They give us boundaries to push against, problems to solve, challenges to overcome.
The next time you face a limitation, don't see it as a barrier. See it as an invitation. An invitation to be more creative, more innovative, more you.
After all, creativity isn't about having no limits. It's about what you do within the limits you have.`)
}
];

43
src/data/projects.ts Normal file
View File

@@ -0,0 +1,43 @@
export interface Project {
id: string;
title: string;
description: string;
category: 'security' | 'development' | 'art' | 'other';
link?: string;
featured: boolean;
}
export const projects: Project[] = [
{
id: 'security-scanner',
title: 'Security Scanner',
description: 'Automated vulnerability detection tool',
category: 'security',
link: '#',
featured: true
},
{
id: 'art-portfolio',
title: 'Art Portfolio',
description: 'Digital art showcase platform',
category: 'art',
link: '#',
featured: true
},
{
id: 'api-gateway',
title: 'API Gateway',
description: 'Secure microservices gateway with authentication',
category: 'development',
link: '#',
featured: false
},
{
id: 'threat-detector',
title: 'Threat Detector',
description: 'Machine learning-based threat detection system',
category: 'security',
link: '#',
featured: false
}
];

27
src/utils/readingTime.ts Normal file
View File

@@ -0,0 +1,27 @@
/**
* Estimates reading time for a given text
* @param text The text to calculate reading time for
* @returns Estimated reading time in minutes
*/
export function estimateReadingTime(text: string): number {
// Average reading speed: 200 words per minute
const wordsPerMinute = 200;
// Remove extra whitespace and split into words
const words = text.trim().split(/\s+/).length;
// Calculate reading time and round up
const readingTime = Math.ceil(words / wordsPerMinute);
// Minimum 1 minute
return Math.max(1, readingTime);
}
/**
* Formats reading time with tilde prefix
* @param minutes Reading time in minutes
* @returns Formatted string (e.g., "~3 min")
*/
export function formatReadingTime(minutes: number): string {
return `~${minutes} min`;
}