📄 a couple updates

This commit is contained in:
RJ
2025-12-02 17:57:31 +02:00
committed by Rares J
parent a1fbd5e374
commit 072320ed73
17 changed files with 335 additions and 294 deletions

View File

@@ -2,8 +2,8 @@ import { Metadata } from 'next'
import { Navbar } from '@/components/blog/navbar' import { Navbar } from '@/components/blog/navbar'
export const metadata: Metadata = { export const metadata: Metadata = {
title: 'Despre', title: 'About',
description: 'Află mai multe despre mine și acest blog', description: 'Learn more about me and this blog',
} }
export default function AboutPage() { export default function AboutPage() {
@@ -15,10 +15,10 @@ export default function AboutPage() {
{/* Classification Header */} {/* Classification Header */}
<div className="border-2 border-[rgb(var(--border-primary))] p-8 mb-10"> <div className="border-2 border-[rgb(var(--border-primary))] p-8 mb-10">
<p className="text-[rgb(var(--text-muted))] font-mono text-xs uppercase tracking-widest mb-4"> <p className="text-[rgb(var(--text-muted))] font-mono text-xs uppercase tracking-widest mb-4">
&gt;&gt; CLASSIFIED_DOC://PUBLIC_ACCESS &gt;&gt; _DOC://PUBLIC_ACCESS
</p> </p>
<h1 className="text-4xl md:text-5xl font-mono font-bold uppercase text-[rgb(var(--text-primary))] tracking-tight"> <h1 className="text-4xl md:text-5xl font-mono font-bold uppercase text-[rgb(var(--text-primary))] tracking-tight">
DESPRE MINE_ ABOUT ME_
</h1> </h1>
</div> </div>
@@ -28,111 +28,220 @@ export default function AboutPage() {
<section className="border-2 border-[rgb(var(--border-primary))] p-8"> <section className="border-2 border-[rgb(var(--border-primary))] p-8">
<div className="border-l-4 border-[var(--neon-cyan)] pl-6"> <div className="border-l-4 border-[var(--neon-cyan)] pl-6">
<p className="font-mono text-base text-[rgb(var(--text-primary))] leading-relaxed mb-4"> <p className="font-mono text-base text-[rgb(var(--text-primary))] leading-relaxed mb-4">
Bun venit pe blogul meu! Sunt un dezvoltator pasionat de tehnologie, specializat Welcome to my corner of the internet! This is where I share my thoughts, opinions,
în dezvoltarea web modernă cu Next.js, React și TypeScript. and experiences - from tech adventures to life as a family man. Yes, I love
technology, but there&apos;s so much more to life than just code and servers.
</p> </p>
<p className="font-mono text-sm text-[rgb(var(--text-muted))] uppercase tracking-wider"> <p className="font-mono text-sm text-[rgb(var(--text-muted))] uppercase tracking-wider">
STATUS: ACTIVE // LEVEL: SENIOR DEV STATUS: ACTIVE // ROLE: DAD + DEV + LIFE ENTHUSIAST
</p> </p>
</div> </div>
</section> </section>
{/* Life & Values Section */}
<section className="border-2 border-[rgb(var(--border-primary))] p-8">
<h2 className="text-2xl font-mono font-bold uppercase text-[rgb(var(--text-primary))] mb-6 pb-3 border-b-2 border-[rgb(var(--border-primary))]">
&gt; LIFE & VALUES
</h2>
<div className="space-y-4">
<div className="border-l-4 border-[var(--neon-pink)] pl-6">
<h3 className="font-mono text-sm font-bold text-[var(--neon-pink)] uppercase mb-2">
[FAMILY FIRST]
</h3>
<p className="font-mono text-sm text-[rgb(var(--text-primary))] leading-relaxed">
Being a dad to an amazing toddler is my most important role. Family time is
sacred - whether it&apos;s building block towers, exploring parks, or just
enjoying the chaos of everyday life together. Tech can wait; these moments
can&apos;t.
</p>
</div>
<div className="border-l-4 border-[var(--neon-cyan)] pl-6">
<h3 className="font-mono text-sm font-bold text-[var(--neon-cyan)] uppercase mb-2">
[ACTIVE LIFESTYLE]
</h3>
<p className="font-mono text-sm text-[rgb(var(--text-primary))] leading-relaxed">
I believe in keeping the body active. Whether it&apos;s hitting the gym, playing
sports, or just staying on the move - physical activity keeps me sharp,
balanced, and ready for whatever life throws my way.
</p>
</div>
<div className="border-l-4 border-[var(--neon-green)] pl-6">
<h3 className="font-mono text-sm font-bold text-[var(--neon-green)] uppercase mb-2">
[ENJOYING THE SIMPLE THINGS]
</h3>
<p className="font-mono text-sm text-[rgb(var(--text-primary))] leading-relaxed">
Life&apos;s too short not to enjoy it. A good drink, a relaxing
evening after a long day, or just not doing anything a blowing some steam off.
</p>
</div>
<div className="border-l-4 border-[var(--neon-orange)] pl-6">
<h3 className="font-mono text-sm font-bold text-[var(--neon-orange)] uppercase mb-2">
[TECH WITH PURPOSE]
</h3>
<p className="font-mono text-sm text-[rgb(var(--text-primary))] leading-relaxed">
Yes, I love tech - self-hosting, privacy, tinkering with hardware. But it&apos;s
a tool, not a lifestyle. Tech should serve life, not the other way around.
</p>
</div>
</div>
</section>
{/* Content Section */} {/* Content Section */}
<section className="border-2 border-[rgb(var(--border-primary))] p-8"> <section className="border-2 border-[rgb(var(--border-primary))] p-8">
<h2 className="text-2xl font-mono font-bold uppercase text-[rgb(var(--text-primary))] mb-6 pb-3 border-b-2 border-[rgb(var(--border-primary))]"> <h2 className="text-2xl font-mono font-bold uppercase text-[rgb(var(--text-primary))] mb-6 pb-3 border-b-2 border-[rgb(var(--border-primary))]">
&gt; CE VEI GĂSI AICI &gt; WHAT YOU&apos;LL FIND HERE
</h2> </h2>
<p className="font-mono text-sm text-[rgb(var(--text-muted))] uppercase tracking-wider mb-6">
CONTENT SCOPE // EVERYTHING FROM TECH TO LIFE
</p>
<ul className="space-y-3"> <ul className="space-y-3">
<li className="flex items-start gap-3"> <li className="flex items-start gap-3">
<span className="text-[var(--neon-cyan)] font-mono font-bold">&gt;</span> <span className="text-[var(--neon-pink)] font-mono font-bold">&gt;</span>
<span className="font-mono text-sm text-[rgb(var(--text-primary))] leading-relaxed"> <span className="font-mono text-sm text-[rgb(var(--text-primary))] leading-relaxed">
Tutoriale despre dezvoltare web <strong>Thoughts & Opinions</strong> - My take on life, work, and everything in
between
</span>
</li>
<li className="flex items-start gap-3">
<span className="text-[var(--neon-pink)] font-mono font-bold">&gt;</span>
<span className="font-mono text-sm text-[rgb(var(--text-primary))] leading-relaxed">
<strong>Life & Family</strong> - Adventures in parenting, sports, and enjoying
the simple things
</span> </span>
</li> </li>
<li className="flex items-start gap-3"> <li className="flex items-start gap-3">
<span className="text-[var(--neon-cyan)] font-mono font-bold">&gt;</span> <span className="text-[var(--neon-cyan)] font-mono font-bold">&gt;</span>
<span className="font-mono text-sm text-[rgb(var(--text-primary))] leading-relaxed"> <span className="font-mono text-sm text-[rgb(var(--text-primary))] leading-relaxed">
Ghiduri practice pentru Next.js și React <strong>Tech Research</strong> - When I dive into interesting technologies and
experiments
</span> </span>
</li> </li>
<li className="flex items-start gap-3"> <li className="flex items-start gap-3">
<span className="text-[var(--neon-cyan)] font-mono font-bold">&gt;</span> <span className="text-[var(--neon-cyan)] font-mono font-bold">&gt;</span>
<span className="font-mono text-sm text-[rgb(var(--text-primary))] leading-relaxed"> <span className="font-mono text-sm text-[rgb(var(--text-primary))] leading-relaxed">
Sfaturi despre design și UX <strong>System Administration</strong> - Self-hosting, infrastructure, and
DevOps adventures
</span> </span>
</li> </li>
<li className="flex items-start gap-3"> <li className="flex items-start gap-3">
<span className="text-[var(--neon-cyan)] font-mono font-bold">&gt;</span> <span className="text-[var(--neon-cyan)] font-mono font-bold">&gt;</span>
<span className="font-mono text-sm text-[rgb(var(--text-primary))] leading-relaxed"> <span className="font-mono text-sm text-[rgb(var(--text-primary))] leading-relaxed">
Experiențe din proiecte reale <strong>Development Insights</strong> - Lessons learned from building software
</span>
</li>
<li className="flex items-start gap-3">
<span className="text-[var(--neon-green)] font-mono font-bold">&gt;</span>
<span className="font-mono text-sm text-[rgb(var(--text-primary))] leading-relaxed">
<strong>Random Stuff</strong> - Because life doesn&apos;t fit into neat
categories!
</span> </span>
</li> </li>
</ul> </ul>
</section> </section>
{/* Tech Stack Section */} {/* Areas of Focus Section */}
<section className="border-2 border-[rgb(var(--border-primary))] p-8"> <section className="border-2 border-[rgb(var(--border-primary))] p-8">
<h2 className="text-2xl font-mono font-bold uppercase text-[rgb(var(--text-primary))] mb-6 pb-3 border-b-2 border-[rgb(var(--border-primary))]"> <h2 className="text-2xl font-mono font-bold uppercase text-[rgb(var(--text-primary))] mb-6 pb-3 border-b-2 border-[rgb(var(--border-primary))]">
&gt; TEHNOLOGII FOLOSITE &gt; AREAS OF FOCUS
</h2> </h2>
<p className="font-mono text-sm text-[rgb(var(--text-muted))] uppercase tracking-wider mb-6"> <div className="grid md:grid-cols-2 gap-4">
SYSTEM STACK // VERSION 2.0
</p>
<div className="grid gap-4">
<div className="border border-[rgb(var(--border-primary))] p-4"> <div className="border border-[rgb(var(--border-primary))] p-4">
<h3 className="font-mono text-sm font-bold text-[var(--neon-cyan)] uppercase mb-2"> <h3 className="font-mono text-xs font-bold text-[var(--neon-pink)] uppercase mb-2">
[FRAMEWORK] [BEING A DAD]
</h3> </h3>
<p className="font-mono text-sm text-[rgb(var(--text-primary))]"> <p className="font-mono text-xs text-[rgb(var(--text-primary))] leading-relaxed">
<strong>Next.js 16</strong> - Framework React pentru producție Playing with my boy, teaching moments, watching him grow, building memories
together
</p> </p>
</div> </div>
<div className="border border-[rgb(var(--border-primary))] p-4"> <div className="border border-[rgb(var(--border-primary))] p-4">
<h3 className="font-mono text-sm font-bold text-[var(--neon-cyan)] uppercase mb-2"> <h3 className="font-mono text-xs font-bold text-[var(--neon-cyan)] uppercase mb-2">
[LANGUAGE] [STAYING ACTIVE]
</h3> </h3>
<p className="font-mono text-sm text-[rgb(var(--text-primary))]"> <p className="font-mono text-xs text-[rgb(var(--text-primary))] leading-relaxed">
<strong>TypeScript</strong> - Pentru type safety Gym sessions, sports, keeping fit, maintaining energy for life&apos;s demands
</p> </p>
</div> </div>
<div className="border border-[rgb(var(--border-primary))] p-4"> <div className="border border-[rgb(var(--border-primary))] p-4">
<h3 className="font-mono text-sm font-bold text-[var(--neon-cyan)] uppercase mb-2"> <h3 className="font-mono text-xs font-bold text-[var(--neon-green)] uppercase mb-2">
[STYLING] [TECHNOLOGY & SYSTEMS]
</h3> </h3>
<p className="font-mono text-sm text-[rgb(var(--text-primary))]"> <p className="font-mono text-xs text-[rgb(var(--text-primary))] leading-relaxed">
<strong>Tailwind CSS</strong> - Pentru stilizare rapidă Software development, infrastructure, DevOps, self-hosting adventures
</p> </p>
</div> </div>
<div className="border border-[rgb(var(--border-primary))] p-4"> <div className="border border-[rgb(var(--border-primary))] p-4">
<h3 className="font-mono text-sm font-bold text-[var(--neon-cyan)] uppercase mb-2"> <h3 className="font-mono text-xs font-bold text-[var(--neon-orange)] uppercase mb-2">
[CONTENT] [LIFE BALANCE]
</h3> </h3>
<p className="font-mono text-sm text-[rgb(var(--text-primary))]"> <p className="font-mono text-xs text-[rgb(var(--text-primary))] leading-relaxed">
<strong>Markdown</strong> - Pentru conținut Relaxing with good company, enjoying downtime, appreciating the simple moments
</p>
</div>
</div>
</section>
{/* Tech Stack Section */}
<section className="border-2 border-[rgb(var(--border-primary))] p-8">
<h2 className="text-2xl font-mono font-bold uppercase text-[rgb(var(--text-primary))] mb-6 pb-3 border-b-2 border-[rgb(var(--border-primary))]">
&gt; TECH STACK
</h2>
<p className="font-mono text-sm text-[rgb(var(--text-muted))] uppercase tracking-wider mb-6">
TOOLS I USE // WHEN NEEDED
</p>
<div className="grid md:grid-cols-2 gap-4">
<div className="border border-[rgb(var(--border-primary))] p-4">
<h3 className="font-mono text-xs font-bold text-[var(--neon-cyan)] uppercase mb-2">
[DEVELOPMENT]
</h3>
<p className="font-mono text-xs text-[rgb(var(--text-primary))] leading-relaxed">
.NET, Golang, TypeScript, Next.js, React
</p>
</div>
<div className="border border-[rgb(var(--border-primary))] p-4">
<h3 className="font-mono text-xs font-bold text-[var(--neon-cyan)] uppercase mb-2">
[INFRASTRUCTURE]
</h3>
<p className="font-mono text-xs text-[rgb(var(--text-primary))] leading-relaxed">
Windows Server, Linux, Docker, Hyper-V
</p>
</div>
<div className="border border-[rgb(var(--border-primary))] p-4">
<h3 className="font-mono text-xs font-bold text-[var(--neon-cyan)] uppercase mb-2">
[DESIGN]
</h3>
<p className="font-mono text-xs text-[rgb(var(--text-primary))] leading-relaxed">
Tailwind CSS, Markdown, Terminal aesthetics
</p>
</div>
<div className="border border-[rgb(var(--border-primary))] p-4">
<h3 className="font-mono text-xs font-bold text-[var(--neon-cyan)] uppercase mb-2">
[SELF-HOSTING]
</h3>
<p className="font-mono text-xs text-[rgb(var(--text-primary))] leading-relaxed">
Home lab, privacy-focused services, full control, Git server
</p> </p>
</div> </div>
</div> </div>
</section> </section>
{/* Contact Section */} {/* Contact Section */}
<section className="border-2 border-[rgb(var(--border-primary))] p-8"> <section className="border-2 border-[rgb(var(--border-primary))] p-8">
<h2 className="text-2xl font-mono font-bold uppercase text-[rgb(var(--text-primary))] mb-6 pb-3 border-b-2 border-[rgb(var(--border-primary))]"> <h2 className="text-2xl font-mono font-bold uppercase text-[rgb(var(--text-primary))] mb-6 pb-3 border-b-2 border-[rgb(var(--border-primary))]">
&gt; CONTACT &gt; CONTACT
</h2> </h2>
<div className="border-l-4 border-[var(--neon-pink)] pl-6"> <div className="border-l-4 border-[var(--neon-pink)] pl-6">
<p className="font-mono text-sm text-[rgb(var(--text-primary))] leading-relaxed mb-4"> {/* <p className="font-mono text-sm text-[rgb(var(--text-primary))] leading-relaxed mb-4">
poți contacta pe{' '} You can reach me at{' '}
<a <a
href="mailto:email@example.com" href="mailto:email@example.com"
className="text-[var(--neon-cyan)] hover:text-[var(--neon-pink)] underline transition-colors" className="text-[var(--neon-cyan)] hover:text-[var(--neon-pink)] underline transition-colors"
> >
email@example.com email@example.com
</a>{' '} </a>{' '}
sau poți găsi pe rețelele sociale. or find me on social media.
</p> </p> */}
<p className="font-mono text-xs text-[rgb(var(--text-muted))] uppercase tracking-wider"> {/* <p className="font-mono text-xs text-[rgb(var(--text-muted))] uppercase tracking-wider">
RESPONSE TIME: &lt; 24H // STATUS: MONITORED RESPONSE TIME: &lt; 24H // STATUS: MONITORED
</p> </p> */}
</div> </div>
</section> </section>
</div> </div>

View File

@@ -91,7 +91,7 @@ export default async function BlogPostPage({ params }: { params: Promise<{ slug:
<div className="border-b border-[var(--neon-pink)] pb-4 mb-6 relative"> <div className="border-b border-[var(--neon-pink)] pb-4 mb-6 relative">
<div className="flex items-center gap-3 mb-3 justify-end"> <div className="flex items-center gap-3 mb-3 justify-end">
<p className="font-mono text-xs text-[var(--neon-cyan)] uppercase tracking-widest"> <p className="font-mono text-xs text-[var(--neon-cyan)] uppercase tracking-widest">
&gt;&gt; CLASSIFIED_DOC://PUBLIC_ACCESS &gt;&gt; _DOC://PUBLIC_ACCESS
</p> </p>
<div className="flex gap-1.5"> <div className="flex gap-1.5">
<div className="w-4 h-4 border border-[rgb(var(--border-primary))] hover:bg-red-500/10 cursor-pointer" /> <div className="w-4 h-4 border border-[rgb(var(--border-primary))] hover:bg-red-500/10 cursor-pointer" />

View File

@@ -437,10 +437,9 @@
} }
.cyberpunk-prose img { .cyberpunk-prose img {
margin-top: 2rem; margin: 2rem;
margin-bottom: 2rem; /* border: 4px solid var(--neon-pink); */
border: 4px solid var(--neon-pink); box-shadow: 0 0 2px rgba(155, 90, 110, 0.5);
box-shadow: 0 0 20px rgba(155, 90, 110, 0.5);
} }
.cyberpunk-prose hr { .cyberpunk-prose hr {

View File

@@ -49,7 +49,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
<div className="border-2 border-slate-300 dark:border-slate-800 p-6"> <div className="border-2 border-slate-300 dark:border-slate-800 p-6">
<p className="text-center text-slate-500 dark:text-slate-500 font-mono text-xs uppercase tracking-wider"> <p className="text-center text-slate-500 dark:text-slate-500 font-mono text-xs uppercase tracking-wider">
© 2025 <span style={{ color: 'var(--neon-cyan)' }}>//</span> BLOG &{' '} © 2025 <span style={{ color: 'var(--neon-cyan)' }}>//</span> BLOG &{' '}
<span style={{ color: 'var(--neon-pink)' }}>PORTOFOLIU</span>{' '} <span style={{ color: 'var(--neon-pink)' }}>RANDOM THOUGHTS</span>{' '}
<span style={{ color: 'var(--neon-cyan)' }}>//</span> ALL RIGHTS RESERVED <span style={{ color: 'var(--neon-cyan)' }}>//</span> ALL RIGHTS RESERVED
</p> </p>
</div> </div>

View File

@@ -45,7 +45,7 @@ export default async function HomePage() {
<div className="border-l-4 border-cyan-700 dark:border-cyan-900 pl-6 mb-8"> <div className="border-l-4 border-cyan-700 dark:border-cyan-900 pl-6 mb-8">
<p className="font-mono text-xs text-slate-500 dark:text-slate-500 uppercase tracking-widest mb-2"> <p className="font-mono text-xs text-slate-500 dark:text-slate-500 uppercase tracking-widest mb-2">
DOCUMENT LEVEL-1 // CLASSIFIED DOCUMENT LEVEL-1 //
</p> </p>
<h1 className="text-4xl md:text-6xl lg:text-7xl font-mono font-bold text-slate-900 dark:text-slate-100 uppercase tracking-tight mb-6"> <h1 className="text-4xl md:text-6xl lg:text-7xl font-mono font-bold text-slate-900 dark:text-slate-100 uppercase tracking-tight mb-6">
BUILD. WRITE. BUILD. WRITE.
@@ -53,7 +53,7 @@ export default async function HomePage() {
SHARE. SHARE.
</h1> </h1>
<p className="text-base md:text-lg lg:text-xl text-slate-700 dark:text-slate-400 font-mono leading-relaxed max-w-2xl"> <p className="text-base md:text-lg lg:text-xl text-slate-700 dark:text-slate-400 font-mono leading-relaxed max-w-2xl">
&gt; Explorează idei despre dezvoltare, design și tehnologie_ &gt; Explore ideas
</p> </p>
</div> </div>
@@ -62,13 +62,13 @@ export default async function HomePage() {
href="/blog" href="/blog"
className="px-6 md:px-8 py-3 md:py-4 bg-cyan-700 dark:bg-cyan-900 text-white dark:text-slate-100 border-2 border-cyan-600 dark:border-cyan-700 font-mono font-bold uppercase text-xs md:text-sm tracking-wider hover:bg-cyan-600 dark:hover:bg-cyan-800 hover:border-cyan-500 dark:hover:border-cyan-600 rounded-none transition-colors duration-200" className="px-6 md:px-8 py-3 md:py-4 bg-cyan-700 dark:bg-cyan-900 text-white dark:text-slate-100 border-2 border-cyan-600 dark:border-cyan-700 font-mono font-bold uppercase text-xs md:text-sm tracking-wider hover:bg-cyan-600 dark:hover:bg-cyan-800 hover:border-cyan-500 dark:hover:border-cyan-600 rounded-none transition-colors duration-200"
> >
[EXPLOREAZĂ BLOG] [CHECK POSTS]
</Link> </Link>
<Link <Link
href="/about" href="/about"
className="px-6 md:px-8 py-3 md:py-4 bg-transparent text-slate-700 dark:text-slate-300 border-2 border-slate-400 dark:border-slate-700 font-mono font-bold uppercase text-xs md:text-sm tracking-wider hover:bg-slate-200 dark:hover:bg-slate-800 hover:border-slate-500 dark:hover:border-slate-600 rounded-none transition-colors duration-200" className="px-6 md:px-8 py-3 md:py-4 bg-transparent text-slate-700 dark:text-slate-300 border-2 border-slate-400 dark:border-slate-700 font-mono font-bold uppercase text-xs md:text-sm tracking-wider hover:bg-slate-200 dark:hover:bg-slate-800 hover:border-slate-500 dark:hover:border-slate-600 rounded-none transition-colors duration-200"
> >
[DESPRE MINE] [ABOUT ME]
</Link> </Link>
</div> </div>
</div> </div>
@@ -83,7 +83,7 @@ export default async function HomePage() {
ARCHIVE ACCESS // RECENT ENTRIES ARCHIVE ACCESS // RECENT ENTRIES
</p> </p>
<h2 className="text-3xl md:text-5xl font-mono font-bold text-slate-900 dark:text-slate-100 uppercase tracking-tight"> <h2 className="text-3xl md:text-5xl font-mono font-bold text-slate-900 dark:text-slate-100 uppercase tracking-tight">
&gt; POSTĂRI RECENTE_ &gt; RECENT ENTRIES
</h2> </h2>
</div> </div>
@@ -146,28 +146,28 @@ export default async function HomePage() {
href="/blog" href="/blog"
className="inline-flex items-center px-8 py-4 bg-transparent text-slate-700 dark:text-slate-300 border-2 border-slate-400 dark:border-slate-700 font-mono font-bold uppercase text-sm tracking-wider hover:bg-slate-200 dark:hover:bg-slate-800 hover:border-slate-500 dark:hover:border-slate-600 transition-colors duration-200" className="inline-flex items-center px-8 py-4 bg-transparent text-slate-700 dark:text-slate-300 border-2 border-slate-400 dark:border-slate-700 font-mono font-bold uppercase text-sm tracking-wider hover:bg-slate-200 dark:hover:bg-slate-800 hover:border-slate-500 dark:hover:border-slate-600 transition-colors duration-200"
> >
[VEZI TOATE ARTICOLELE] &gt;&gt; [SEE POSTS] &gt;&gt;
</Link> </Link>
)} )}
<Link <Link
href="/tags" href="/tags"
className="inline-flex items-center px-8 py-4 bg-transparent text-slate-700 dark:text-slate-300 border-2 border-slate-400 dark:border-slate-700 font-mono font-bold uppercase text-sm tracking-wider hover:bg-slate-200 dark:hover:bg-slate-800 hover:border-slate-500 dark:hover:border-slate-600 transition-colors duration-200" className="inline-flex items-center px-8 py-4 bg-transparent text-slate-700 dark:text-slate-300 border-2 border-slate-400 dark:border-slate-700 font-mono font-bold uppercase text-sm tracking-wider hover:bg-slate-200 dark:hover:bg-slate-800 hover:border-slate-500 dark:hover:border-slate-600 transition-colors duration-200"
> >
[VEZI TOATE TAG-URILE] &gt;&gt; [SEE ALL TAGS] &gt;&gt;
</Link> </Link>
</div> </div>
</div> </div>
</section> </section>
{/* Stats Section - from worktree-agent-1 */} {/* Stats Section - from worktree-agent-1 */}
<section className="py-24 bg-zinc-50 dark:bg-zinc-900 border-y-4 border-slate-300 dark:border-slate-800 transition-colors duration-300"> {/* <section className="py-24 bg-zinc-50 dark:bg-zinc-900 border-y-4 border-slate-300 dark:border-slate-800 transition-colors duration-300">
<div className="max-w-7xl mx-auto px-6"> <div className="max-w-7xl mx-auto px-6">
<div className="border-l-4 border-teal-700 dark:border-teal-900 pl-6 mb-12"> <div className="border-l-4 border-teal-700 dark:border-teal-900 pl-6 mb-12">
<p className="font-mono text-xs text-slate-500 dark:text-slate-500 uppercase tracking-widest mb-2"> <p className="font-mono text-xs text-slate-500 dark:text-slate-500 uppercase tracking-widest mb-2">
SYSTEM STATISTICS // DATABASE METRICS SYSTEM STATISTICS // DATABASE METRICS
</p> </p>
<h2 className="text-3xl md:text-5xl font-mono font-bold text-slate-900 dark:text-slate-100 uppercase tracking-tight"> <h2 className="text-3xl md:text-5xl font-mono font-bold text-slate-900 dark:text-slate-100 uppercase tracking-tight">
&gt; METRICI_ &gt; METRICS
</h2> </h2>
</div> </div>
@@ -177,7 +177,7 @@ export default async function HomePage() {
{allPosts.length}+ {allPosts.length}+
</div> </div>
<p className="text-slate-600 dark:text-slate-400 font-mono text-sm uppercase tracking-wider border-t-2 border-slate-300 dark:border-slate-800 pt-4"> <p className="text-slate-600 dark:text-slate-400 font-mono text-sm uppercase tracking-wider border-t-2 border-slate-300 dark:border-slate-800 pt-4">
ARTICOLE PUBLICATE PUBLISHED
</p> </p>
</div> </div>
@@ -200,10 +200,10 @@ export default async function HomePage() {
</div> </div>
</div> </div>
</div> </div>
</section> </section> */}
{/* Newsletter CTA - from worktree-agent-1 */} {/* Newsletter CTA - from worktree-agent-1 */}
<section className="py-24 bg-zinc-100 dark:bg-slate-900 border-t-4 border-slate-300 dark:border-slate-800 transition-colors duration-300"> {/* <section className="py-24 bg-zinc-100 dark:bg-slate-900 border-t-4 border-slate-300 dark:border-slate-800 transition-colors duration-300">
<div className="max-w-3xl mx-auto px-6"> <div className="max-w-3xl mx-auto px-6">
<div className="border-4 border-slate-300 dark:border-slate-700 bg-white dark:bg-zinc-900 p-12 transition-colors duration-300"> <div className="border-4 border-slate-300 dark:border-slate-700 bg-white dark:bg-zinc-900 p-12 transition-colors duration-300">
<p className="font-mono text-xs text-slate-500 dark:text-slate-500 uppercase tracking-widest mb-2"> <p className="font-mono text-xs text-slate-500 dark:text-slate-500 uppercase tracking-widest mb-2">
@@ -233,7 +233,7 @@ export default async function HomePage() {
</p> </p>
</div> </div>
</div> </div>
</section> </section> */}
</main> </main>
) )
} }

View File

@@ -27,16 +27,15 @@ export function OptimizedImage({
if (hasError) { if (hasError) {
return ( return (
<div className="my-8 rounded-lg border border-zinc-800 bg-zinc-900/50 p-8 text-center"> <span className="block my-8 rounded-lg border border-zinc-800 bg-zinc-900/50 p-8 text-center">
<p className="text-zinc-400">Failed to load image</p> <span className="block text-zinc-400">Failed to load image</span>
{caption && <p className="mt-2 text-sm text-zinc-500">{caption}</p>} {caption && <span className="block mt-2 text-sm text-zinc-500">{caption}</span>}
</div> </span>
) )
} }
return ( const imageElement = (
<figure className={`my-8 ${className}`}> <span className="block relative overflow-hidden rounded-lg border border-zinc-800 bg-zinc-900/50">
<div className="relative overflow-hidden rounded-lg border border-zinc-800 bg-zinc-900/50">
<Image <Image
src={src} src={src}
alt={alt} alt={alt}
@@ -51,14 +50,21 @@ export function OptimizedImage({
blurDataURL="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='300'%3E%3Crect width='400' height='300' fill='%2318181b'/%3E%3C/svg%3E" blurDataURL="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='300'%3E%3Crect width='400' height='300' fill='%2318181b'/%3E%3C/svg%3E"
/> />
{isLoading && ( {isLoading && (
<div className="absolute inset-0 flex items-center justify-center"> <span className="absolute inset-0 flex items-center justify-center">
<div className="h-8 w-8 animate-spin rounded-full border-2 border-emerald-500 border-t-transparent" /> <span className="block h-8 w-8 animate-spin rounded-full border-2 border-emerald-500 border-t-transparent" />
</div> </span>
)} )}
</div> </span>
)
// Always use <span> to avoid invalid HTML nesting in <p> tags
// This prevents hydration mismatches between server and client
return (
<span className={`block my-8 ${className}`}>
{imageElement}
{caption && ( {caption && (
<figcaption className="mt-3 text-center text-sm text-zinc-400">{caption}</figcaption> <span className="block mt-3 text-center text-sm text-zinc-400">{caption}</span>
)} )}
</figure> </span>
) )
} }

View File

@@ -18,17 +18,50 @@ export default function MarkdownRenderer({ content, className = '' }: MarkdownRe
<div className={`prose prose-invert prose-zinc max-w-none ${className}`}> <div className={`prose prose-invert prose-zinc max-w-none ${className}`}>
<ReactMarkdown <ReactMarkdown
remarkPlugins={[remarkGfm]} remarkPlugins={[remarkGfm]}
rehypePlugins={[rehypeRaw, [rehypeSanitize, { rehypePlugins={[
tagNames: ['p', 'a', 'img', 'code', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', rehypeRaw,
'ul', 'ol', 'li', 'blockquote', 'table', 'thead', 'tbody', 'tr', 'th', 'td', [
'strong', 'em', 'del', 'br', 'hr', 'div', 'span'], rehypeSanitize,
{
tagNames: [
'p',
'a',
'img',
'code',
'pre',
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'ul',
'ol',
'li',
'blockquote',
'table',
'thead',
'tbody',
'tr',
'th',
'td',
'strong',
'em',
'del',
'br',
'hr',
'div',
'span',
],
attributes: { attributes: {
a: ['href', 'rel', 'target'], a: ['href', 'rel', 'target'],
img: ['src', 'alt', 'title', 'width', 'height'], img: ['src', 'alt', 'title', 'width', 'height'],
code: ['className'], code: ['className'],
'*': ['className', 'id'] '*': ['className', 'id'],
} },
}]]} },
],
]}
components={{ components={{
img: ({ node, src, alt, title, ...props }) => { img: ({ node, src, alt, title, ...props }) => {
if (!src || typeof src !== 'string') return null if (!src || typeof src !== 'string') return null
@@ -55,19 +88,19 @@ export default function MarkdownRenderer({ content, className = '' }: MarkdownRe
: [alt, undefined] : [alt, undefined]
const url = new URL(absoluteSrc, 'http://localhost') const url = new URL(absoluteSrc, 'http://localhost')
const width = url.searchParams.get('w') ? parseInt(url.searchParams.get('w')!) : 800 const width = url.searchParams.get('w') ? parseInt(url.searchParams.get('w')!) : null
const height = url.searchParams.get('h') ? parseInt(url.searchParams.get('h')!) : 600 const height = url.searchParams.get('h') ? parseInt(url.searchParams.get('h')!) : null
const cleanSrc = absoluteSrc.split('?')[0] const cleanSrc = absoluteSrc.split('?')[0]
return ( const imageProps = {
<OptimizedImage src: cleanSrc,
src={cleanSrc} alt: altText || alt || '',
alt={altText || alt || ''} caption: caption,
caption={caption} ...(width && { width }),
width={width} ...(height && { height }),
height={height} }
/>
) return <OptimizedImage {...imageProps} />
}, },
code: ({ node, className, children, ...props }) => { code: ({ node, className, children, ...props }) => {
const inline = !className && typeof children === 'string' && !children.includes('\n') const inline = !className && typeof children === 'string' && !children.includes('\n')

View File

@@ -51,6 +51,12 @@ export function Navbar() {
className="font-mono text-sm text-zinc-400 dark:text-zinc-500 uppercase tracking-wider hover:text-cyan-400 dark:hover:text-cyan-300 transition-colors cursor-pointer" className="font-mono text-sm text-zinc-400 dark:text-zinc-500 uppercase tracking-wider hover:text-cyan-400 dark:hover:text-cyan-300 transition-colors cursor-pointer"
> >
[ABOUT] [ABOUT]
</Link>
<Link
href="/blog"
className="font-mono text-sm text-zinc-400 dark:text-zinc-500 uppercase tracking-wider hover:text-cyan-400 dark:hover:text-cyan-300 transition-colors cursor-pointer"
>
[BLOG]
</Link> </Link>
<ThemeToggle /> <ThemeToggle />
</div> </div>

View File

@@ -1,34 +0,0 @@
---
title: 'Getting Started with Next.js 15'
description: 'Learn how to build modern web applications with Next.js 15 and TypeScript.'
date: '2025-01-07'
author: 'John Doe'
category: 'Tutorial'
tags: ['nextjs', 'typescript', 'tutorial']
---
# Getting Started with Next.js 15
Welcome to this example blog post! This post demonstrates how markdown content is rendered.
## Features
- Server Components by default
- Improved performance
- Better TypeScript support
## Code Example
```typescript
export default function Page() {
return <h1>Hello, Next.js 15!</h1>
}
```
### Check out this article:
[Check this out](tech/articol-tehnic.md)
## Conclusion
Next.js 15 brings many improvements for building modern web applications.

View File

@@ -1,20 +0,0 @@
---
title: 'Technical Article'
description: 'A technical article to test internal links'
date: '2025-01-10'
author: 'John Doe'
category: 'Tech'
tags: ['tech', 'test']
---
# Technical Article
This is a test article for internal blog post linking.
Imagine cooler:
![Cooler image:](./cooler.jpg)
## Content
You are reading the technical article that was linked from the example post.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 KiB

View File

@@ -1,109 +0,0 @@
---
title: 'Test Complet Markdown'
description: 'Un articol de test care demonstrează toate elementele markdown suportate'
date: '2025-01-15'
author: 'Test Author'
category: 'Tutorial'
tags: ['markdown', 'test', 'demo']
image: '/38636.jpg'
draft: false
---
# Heading 1
Acesta este un paragraf normal cu **text bold** și _text italic_. Putem combina **_bold și italic_**.
## Heading 2
### Heading 3
#### Heading 4
##### Heading 5
###### Heading 6
## Liste
### Listă neordonată
- Item 1
- Item 2
- Subitem 2.1
- Subitem 2.2
- Item 3
### Listă ordonată
1. Primul item
2. Al doilea item
3. Al treilea item
## Cod
Cod inline: `const x = 42;`
Bloc de cod JavaScript:
```javascript
function greet(name) {
console.log(`Hello, ${name}!`)
return true
}
greet('World')
```
Bloc de cod Python:
```python
def calculate_sum(a, b):
"""Calculate sum of two numbers"""
return a + b
result = calculate_sum(5, 10)
print(f"Result: {result}")
```
## Blockquote
> Acesta este un blockquote.
> Poate avea multiple linii.
>
> Și paragrafe separate.
## Link-uri
[Link intern](/blog/alt-articol)
[Link extern](https://example.com)
## Imagini
![Alt text pentru imagine](./tech/cooler.jpg)
## Tabele
| Coloana 1 | Coloana 2 | Coloana 3 |
| --------- | --------- | --------- |
| Celula 1 | Celula 2 | Celula 3 |
| Date 1 | Date 2 | Date 3 |
| Info 1 | Info 2 | Info 3 |
## Linie orizontală
---
## Task List (GFM)
- [x] Task completat
- [ ] Task incomplet
- [ ] Alt task
## Strikethrough
~~Text șters~~
## Concluzie
Acesta este sfârșitul articolului de test.

View File

@@ -0,0 +1,41 @@
---
title: 'Why I created this page'
description: 'First post'
date: '2025-12-02'
author: 'Rares'
category: 'Opinion'
tags: ['opinion']
image: ''
draft: false
---
# Why I Created This Blog & Why It's Not Just About Tech
Hi there! Welcome to my blog. If you're wondering why I created this space, it's because I wanted to share more than just technical tutorials or how-to guides though you'll find those here too. This blog is a reflection of me and my journey through the world of technology, self-hosting, and beyond.
## Why a blog?
You might be thinking, "Why create another tech blog? There are plenty out there."
Well, yes, there are. But I believe that sharing some of my opinions and experiences will eventually act out as a journal:
1. **Personal touch**: Even though i've been working corporate all my career, this webpage won't contain that sugar coated language 😅. It's a place where you'll get to know me my thoughts, my mistakes, and my victories. I believe that this personal touch makes the content more engaging and relatable.
2. **Beyond tech**: While I'll be writing about technology, I also want to explore other topics that interest me, such as mental health, productivity and so on.... I think a well-rounded approach can help create a more engaging and informative space.
3. **Self-hosting adventure**: As you might have guessed from the title, this blog is self-hosted. This was an exciting journey for me, and I'll be sharing my experiences, challenges, and learnings along the way. If you're interested in self-hosting or just want to understand what it's all about, you might find what worked for me or didn't.
## Why self-host?
![Selfhosting rig](./whythispage/selfhostedrig.gif?w=400 "My self-hosting setup | A look at the hardware running this blog")
Now, let's talk about why I chose to self-host this blog. In a nutshell, self-hosting gave me:
- **Full control**: By hosting my own website, I have complete control over my content and how it's displayed. No more compromises or limitations imposed by third-party platforms.
- **Owning my data**: It's just, that I can have control over my data without others snooping around.
- **It's fun**: Started looking into sysadmin/devops for a long time, after a burnout I stepped into selfhosting more convincingly.
## What to expect
As I mentioned earlier, this blog will be a mix of tech tutorials, personal thoughts, and everything in between. Here's what you can look forward to:
- **Tech how-tos**: Step-by-step guides on various topics, from setting up your own development environment to configuring your server.
- **Self-hosting adventures**: My experiences, learnings, and tips on self-hosting, including challenges faced and solutions implemented.
- **Random musings**: Thoughts on productivity, mental health, and other interests of mine that might not be directly related to tech.

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 MiB

View File

@@ -1,18 +1,18 @@
export function formatDate(dateString: string): string { export function formatDate(dateString: string): string {
const date = new Date(dateString) const date = new Date(dateString)
const months = [ const months = [
'ianuarie', 'January',
'februarie', 'February',
'martie', 'March',
'aprilie', 'April',
'mai', 'May',
'iunie', 'June',
'iulie', 'July',
'august', 'August',
'septembrie', 'September',
'octombrie', 'October',
'noiembrie', 'November',
'decembrie', 'December',
] ]
return `${date.getDate()} ${months[date.getMonth()]} ${date.getFullYear()}` return `${date.getDate()} ${months[date.getMonth()]} ${date.getFullYear()}`
@@ -24,12 +24,22 @@ export function formatRelativeDate(dateString: string): string {
const diffTime = Math.abs(now.getTime() - date.getTime()) const diffTime = Math.abs(now.getTime() - date.getTime())
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
if (diffDays === 0) return 'astăzi' if (diffDays === 0) return 'today'
if (diffDays === 1) return 'ieri' if (diffDays === 1) return 'yesterday'
if (diffDays < 7) return `acum ${diffDays} zile` if (diffDays < 7) {
if (diffDays < 30) return `acum ${Math.floor(diffDays / 7)} săptămâni` const days = diffDays
if (diffDays < 365) return `acum ${Math.floor(diffDays / 30)} luni` return `${days} day${days > 1 ? 's' : ''} ago`
return `acum ${Math.floor(diffDays / 365)} ani` }
if (diffDays < 30) {
const weeks = Math.floor(diffDays / 7)
return `${weeks} week${weeks > 1 ? 's' : ''} ago`
}
if (diffDays < 365) {
const months = Math.floor(diffDays / 30)
return `${months} month${months > 1 ? 's' : ''} ago`
}
const years = Math.floor(diffDays / 365)
return `${years} year${years > 1 ? 's' : ''} ago`
} }
export function generateExcerpt(content: string, maxLength = 160): string { export function generateExcerpt(content: string, maxLength = 160): string {