+ {/* Top row: date + arrow */}
+
+ {date}
+ →
+
+
+ {/* Bottom block */}
+
+
+ {frontmatter.title}
+
+
+ {frontmatter.description}
+
+ {frontmatter.tags && frontmatter.tags.length > 0 && (
+
+ {frontmatter.tags.map((tag) => (
+
+ {tag}
+
+ ))}
+
+ )}
+
+
+
+ );
+}
diff --git a/src/components/ProjectCard.tsx b/src/components/ProjectCard.tsx
index 645a57a..b5df29a 100644
--- a/src/components/ProjectCard.tsx
+++ b/src/components/ProjectCard.tsx
@@ -33,7 +33,7 @@ export default function ProjectCard({
overflow: 'hidden',
background: 'rgba(26,27,58,.6)',
border: '1px solid var(--line)',
- padding: '22px',
+ padding: '28px',
display: 'flex',
flexDirection: 'column',
justifyContent: 'space-between',
@@ -135,10 +135,10 @@ export default function ProjectCard({
borderRadius: '12px',
background: 'rgba(10,14,39,.6)',
border: '1px solid var(--line)',
- padding: '14px',
+ padding: '16px',
display: 'flex',
flexDirection: 'column',
- gap: '10px',
+ gap: '12px',
backdropFilter: 'blur(6px)',
overflow: 'hidden',
}}
@@ -259,7 +259,7 @@ export default function ProjectCard({
{project.stack.map((s) => (
diff --git a/src/components/ProjectNavigation.tsx b/src/components/ProjectNavigation.tsx
new file mode 100644
index 0000000..6b71637
--- /dev/null
+++ b/src/components/ProjectNavigation.tsx
@@ -0,0 +1,118 @@
+import Link from 'next/link';
+import type { ContentItem } from '@/lib/content';
+
+type Props = { prev: ContentItem | null; next: ContentItem | null };
+
+export default function ProjectNavigation({ prev, next }: Props) {
+ return (
+ <>
+
+
+ >
+ );
+}
diff --git a/src/components/ProjectsSection.tsx b/src/components/ProjectsSection.tsx
index 58423f9..b96bde9 100644
--- a/src/components/ProjectsSection.tsx
+++ b/src/components/ProjectsSection.tsx
@@ -95,8 +95,8 @@ export default function ProjectsSection() {
#projects { padding: 72px 0 !important; }
#projects .bento {
grid-template-columns: repeat(2, 1fr) !important;
- grid-auto-rows: 180px !important;
- gap: 14px !important;
+ grid-auto-rows: 220px !important;
+ gap: 18px !important;
}
#projects .c-2x2, #projects .c-2x1, #projects .c-1x1, #projects .c-1x2 {
grid-column: span 2 !important;
@@ -247,8 +247,8 @@ export default function ProjectsSection() {
style={{
display: 'grid',
gridTemplateColumns: 'repeat(6, 1fr)',
- gap: '20px',
- gridAutoRows: '220px',
+ gap: '24px',
+ gridAutoRows: '260px',
}}
>
{filtered.map((project) => (
diff --git a/src/components/RevealOnScroll.tsx b/src/components/RevealOnScroll.tsx
new file mode 100644
index 0000000..52a3797
--- /dev/null
+++ b/src/components/RevealOnScroll.tsx
@@ -0,0 +1,33 @@
+'use client';
+
+import { useEffect, useRef } from 'react';
+
+export default function RevealOnScroll({ children }: { children: React.ReactNode }) {
+ const wrapperRef = useRef
(null);
+
+ useEffect(() => {
+ const wrapper = wrapperRef.current;
+ if (!wrapper) return;
+
+ const observer = new IntersectionObserver(
+ (entries) => {
+ entries.forEach((entry) => {
+ if (entry.isIntersecting) {
+ (entry.target as HTMLElement).classList.add('in');
+ }
+ });
+ },
+ { threshold: 0.1 },
+ );
+
+ const revealEls = wrapper.querySelectorAll('.reveal');
+ revealEls.forEach((el, i) => {
+ el.style.transitionDelay = `${i * 0.05}s`;
+ observer.observe(el);
+ });
+
+ return () => observer.disconnect();
+ }, []);
+
+ return {children}
;
+}
diff --git a/src/lib/content.ts b/src/lib/content.ts
index 8343d6e..ab5e182 100644
--- a/src/lib/content.ts
+++ b/src/lib/content.ts
@@ -71,3 +71,17 @@ export function getAllSlugs(type: 'projects' | 'posts'): string[] {
.filter((f) => f.endsWith('.mdx'))
.map((f) => f.replace(/\.mdx$/, ''));
}
+
+export function getAdjacentContent(
+ type: 'projects' | 'posts',
+ slug: string,
+): { prev: ContentItem | null; next: ContentItem | null } {
+ const items = getAllContent(type); // already date-desc
+ const idx = items.findIndex((x) => x.slug === slug);
+ if (idx === -1) return { prev: null, next: null };
+ // prev = older entry → comes after in date-desc array
+ // next = newer entry → comes before in date-desc array
+ const prev = idx < items.length - 1 ? items[idx + 1] : null;
+ const next = idx > 0 ? items[idx - 1] : null;
+ return { prev, next };
+}