From a4b83dbdd4b491720ad1a1328956e5720821088f Mon Sep 17 00:00:00 2001 From: Nicholai Date: Sun, 28 Dec 2025 15:29:13 -0700 Subject: [PATCH] =?UTF-8?q?Add=20Tailwind=20CSS=20configuration,=20integra?= =?UTF-8?q?te=20lucide-react=20icons,=20and=20set=20up=20initial=20compone?= =?UTF-8?q?nts=20for=20the=20Kamp=C3=BCs=20Cad=C4=B1lar=C4=B1=20website.?= =?UTF-8?q?=20Update=20package.json=20and=20pnpm-lock.yaml=20to=20include?= =?UTF-8?q?=20new=20dependencies.=20Remove=20outdated=20assets=20and=20imp?= =?UTF-8?q?lement=20new=20logo=20images.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .cursor/debug.log | 28 + ...t_vite_react_app_to_astro_2308e4b5.plan.md | 326 +++ dev/brief.md | 559 ------ dev/continuity.md | 84 - dev/design.json | 223 ++- dev/generated/.gitignore | 24 + dev/generated/App.tsx | 141 ++ dev/generated/CLAUDE.md | 126 ++ dev/generated/README.md | 20 + dev/generated/components/ArticleCard.tsx | 79 + dev/generated/components/Button.tsx | 31 + dev/generated/components/Footer.tsx | 98 + dev/generated/components/Header.tsx | 113 ++ dev/generated/components/Hero.tsx | 139 ++ dev/generated/components/Home.tsx | 291 +++ dev/generated/components/Logo.tsx | 34 + dev/generated/components/Publications.tsx | 211 ++ dev/generated/components/Reveal.tsx | 54 + dev/generated/content.ts | 179 ++ dev/generated/index.html | 110 + dev/generated/index.tsx | 15 + dev/generated/kampüs-cadıları.zip | Bin 0 -> 77095 bytes dev/generated/metadata.json | 5 + dev/generated/package-lock.json | 1777 +++++++++++++++++ dev/generated/package.json | 22 + dev/generated/tsconfig.json | 29 + dev/generated/types.ts | 46 + dev/generated/vite.config.ts | 23 + dev/visual-design-analysis.md | 237 --- package.json | 1 + pnpm-lock.yaml | 12 + public/apple-touch-icon.png | Bin 56192 -> 0 bytes public/favicon-192.png | Bin 64108 -> 0 bytes public/favicon-32.png | Bin 2185 -> 0 bytes public/favicon.ico | Bin 15086 -> 0 bytes public/favicon.svg | 9 - public/media/GSTR_01_260_breakdown.mp4 | Bin 3517755 -> 0 bytes .../media/GSTR_03_070_v10_breakdown_v01.mp4 | Bin 2302177 -> 0 bytes public/media/PLACEHOLDER_ASSETS.md | 132 -- public/media/favicon.JPG | Bin 1689526 -> 0 bytes public/media/logo_black.png | Bin 0 -> 35118 bytes public/media/logo_col.png | Bin 0 -> 86490 bytes public/media/logo_white.png | Bin 0 -> 52484 bytes public/media/logos/logo_black_large@1x.png | Bin 0 -> 7051 bytes public/media/logos/logo_black_large@1x.webp | Bin 0 -> 3138 bytes public/media/logos/logo_black_large@2x.png | Bin 0 -> 16185 bytes public/media/logos/logo_black_large@2x.webp | Bin 0 -> 6806 bytes public/media/logos/logo_black_medium@1x.png | Bin 0 -> 2925 bytes public/media/logos/logo_black_medium@1x.webp | Bin 0 -> 1368 bytes public/media/logos/logo_black_medium@2x.png | Bin 0 -> 6790 bytes public/media/logos/logo_black_medium@2x.webp | Bin 0 -> 3014 bytes public/media/logos/logo_black_small@1x.png | Bin 0 -> 1168 bytes public/media/logos/logo_black_small@1x.webp | Bin 0 -> 610 bytes public/media/logos/logo_black_small@2x.png | Bin 0 -> 2891 bytes public/media/logos/logo_black_small@2x.webp | Bin 0 -> 1356 bytes public/media/logos/logo_col_large@1x.png | Bin 0 -> 14541 bytes public/media/logos/logo_col_large@1x.webp | Bin 0 -> 5406 bytes public/media/logos/logo_col_large@2x.png | Bin 0 -> 34647 bytes public/media/logos/logo_col_large@2x.webp | Bin 0 -> 12078 bytes public/media/logos/logo_col_medium@1x.png | Bin 0 -> 5793 bytes public/media/logos/logo_col_medium@1x.webp | Bin 0 -> 2270 bytes public/media/logos/logo_col_medium@2x.png | Bin 0 -> 13932 bytes public/media/logos/logo_col_medium@2x.webp | Bin 0 -> 5200 bytes public/media/logos/logo_col_small@1x.png | Bin 0 -> 2254 bytes public/media/logos/logo_col_small@1x.webp | Bin 0 -> 942 bytes public/media/logos/logo_col_small@2x.png | Bin 0 -> 5730 bytes public/media/logos/logo_col_small@2x.webp | Bin 0 -> 2226 bytes public/media/logos/logo_white_large@1x.png | Bin 0 -> 10980 bytes public/media/logos/logo_white_large@1x.webp | Bin 0 -> 6016 bytes public/media/logos/logo_white_large@2x.png | Bin 0 -> 26739 bytes public/media/logos/logo_white_large@2x.webp | Bin 0 -> 13312 bytes public/media/logos/logo_white_medium@1x.png | Bin 0 -> 4313 bytes public/media/logos/logo_white_medium@1x.webp | Bin 0 -> 2604 bytes public/media/logos/logo_white_medium@2x.png | Bin 0 -> 10389 bytes public/media/logos/logo_white_medium@2x.webp | Bin 0 -> 5796 bytes public/media/logos/logo_white_small@1x.png | Bin 0 -> 1724 bytes public/media/logos/logo_white_small@1x.webp | Bin 0 -> 1120 bytes public/media/logos/logo_white_small@2x.png | Bin 0 -> 4294 bytes public/media/logos/logo_white_small@2x.webp | Bin 0 -> 2558 bytes public/media/nicholai-wild-portrait.JPEG | Bin 3874947 -> 0 bytes src/assets/PENCIL_1.3.1_wipe.avif | Bin 416144 -> 0 bytes src/assets/claude-nuke.avif | Bin 59808 -> 0 bytes src/assets/foxrenderfarm-arch-linux.avif | Bin 33174 -> 0 bytes src/assets/g-star-image.avif | Bin 23421 -> 0 bytes src/assets/nicholai-closeup-portrait.avif | Bin 47230 -> 0 bytes src/assets/nicholai-medium-portrait.avif | Bin 7377 -> 0 bytes src/components/App.tsx | 211 ++ src/components/ArticleCard.tsx | 80 + src/components/BaseHead.astro | 68 +- src/components/BlogCard.astro | 25 - src/components/Button.tsx | 32 + src/components/FormattedDate.astro | 17 - src/components/Home.tsx | 291 +++ src/components/Logo.astro | 42 + src/components/Logo.tsx | 46 + src/components/Publications.tsx | 211 ++ src/components/Reveal.tsx | 55 + src/consts.ts | 14 +- src/content/content.ts | 180 ++ src/layouts/BaseLayout.astro | 10 +- src/pages/index.astro | 698 +------ src/pages/publications.astro | 11 + src/styles/global.css | 132 +- src/types.ts | 47 + tailwind.config.mjs | 51 + 105 files changed, 5569 insertions(+), 1830 deletions(-) create mode 100644 .cursor/debug.log create mode 100644 .cursor/plans/convert_vite_react_app_to_astro_2308e4b5.plan.md delete mode 100644 dev/brief.md delete mode 100644 dev/continuity.md create mode 100644 dev/generated/.gitignore create mode 100644 dev/generated/App.tsx create mode 100644 dev/generated/CLAUDE.md create mode 100644 dev/generated/README.md create mode 100644 dev/generated/components/ArticleCard.tsx create mode 100644 dev/generated/components/Button.tsx create mode 100644 dev/generated/components/Footer.tsx create mode 100644 dev/generated/components/Header.tsx create mode 100644 dev/generated/components/Hero.tsx create mode 100644 dev/generated/components/Home.tsx create mode 100644 dev/generated/components/Logo.tsx create mode 100644 dev/generated/components/Publications.tsx create mode 100644 dev/generated/components/Reveal.tsx create mode 100644 dev/generated/content.ts create mode 100644 dev/generated/index.html create mode 100644 dev/generated/index.tsx create mode 100644 dev/generated/kampüs-cadıları.zip create mode 100644 dev/generated/metadata.json create mode 100644 dev/generated/package-lock.json create mode 100644 dev/generated/package.json create mode 100644 dev/generated/tsconfig.json create mode 100644 dev/generated/types.ts create mode 100644 dev/generated/vite.config.ts delete mode 100644 dev/visual-design-analysis.md delete mode 100644 public/apple-touch-icon.png delete mode 100644 public/favicon-192.png delete mode 100644 public/favicon-32.png delete mode 100644 public/favicon.ico delete mode 100644 public/favicon.svg delete mode 100644 public/media/GSTR_01_260_breakdown.mp4 delete mode 100644 public/media/GSTR_03_070_v10_breakdown_v01.mp4 delete mode 100644 public/media/PLACEHOLDER_ASSETS.md delete mode 100644 public/media/favicon.JPG create mode 100644 public/media/logo_black.png create mode 100644 public/media/logo_col.png create mode 100644 public/media/logo_white.png create mode 100644 public/media/logos/logo_black_large@1x.png create mode 100644 public/media/logos/logo_black_large@1x.webp create mode 100644 public/media/logos/logo_black_large@2x.png create mode 100644 public/media/logos/logo_black_large@2x.webp create mode 100644 public/media/logos/logo_black_medium@1x.png create mode 100644 public/media/logos/logo_black_medium@1x.webp create mode 100644 public/media/logos/logo_black_medium@2x.png create mode 100644 public/media/logos/logo_black_medium@2x.webp create mode 100644 public/media/logos/logo_black_small@1x.png create mode 100644 public/media/logos/logo_black_small@1x.webp create mode 100644 public/media/logos/logo_black_small@2x.png create mode 100644 public/media/logos/logo_black_small@2x.webp create mode 100644 public/media/logos/logo_col_large@1x.png create mode 100644 public/media/logos/logo_col_large@1x.webp create mode 100644 public/media/logos/logo_col_large@2x.png create mode 100644 public/media/logos/logo_col_large@2x.webp create mode 100644 public/media/logos/logo_col_medium@1x.png create mode 100644 public/media/logos/logo_col_medium@1x.webp create mode 100644 public/media/logos/logo_col_medium@2x.png create mode 100644 public/media/logos/logo_col_medium@2x.webp create mode 100644 public/media/logos/logo_col_small@1x.png create mode 100644 public/media/logos/logo_col_small@1x.webp create mode 100644 public/media/logos/logo_col_small@2x.png create mode 100644 public/media/logos/logo_col_small@2x.webp create mode 100644 public/media/logos/logo_white_large@1x.png create mode 100644 public/media/logos/logo_white_large@1x.webp create mode 100644 public/media/logos/logo_white_large@2x.png create mode 100644 public/media/logos/logo_white_large@2x.webp create mode 100644 public/media/logos/logo_white_medium@1x.png create mode 100644 public/media/logos/logo_white_medium@1x.webp create mode 100644 public/media/logos/logo_white_medium@2x.png create mode 100644 public/media/logos/logo_white_medium@2x.webp create mode 100644 public/media/logos/logo_white_small@1x.png create mode 100644 public/media/logos/logo_white_small@1x.webp create mode 100644 public/media/logos/logo_white_small@2x.png create mode 100644 public/media/logos/logo_white_small@2x.webp delete mode 100644 public/media/nicholai-wild-portrait.JPEG delete mode 100644 src/assets/PENCIL_1.3.1_wipe.avif delete mode 100644 src/assets/claude-nuke.avif delete mode 100644 src/assets/foxrenderfarm-arch-linux.avif delete mode 100644 src/assets/g-star-image.avif delete mode 100644 src/assets/nicholai-closeup-portrait.avif delete mode 100644 src/assets/nicholai-medium-portrait.avif create mode 100644 src/components/App.tsx create mode 100644 src/components/ArticleCard.tsx delete mode 100644 src/components/BlogCard.astro create mode 100644 src/components/Button.tsx delete mode 100644 src/components/FormattedDate.astro create mode 100644 src/components/Home.tsx create mode 100644 src/components/Logo.astro create mode 100644 src/components/Logo.tsx create mode 100644 src/components/Publications.tsx create mode 100644 src/components/Reveal.tsx create mode 100644 src/content/content.ts create mode 100644 src/pages/publications.astro create mode 100644 src/types.ts create mode 100644 tailwind.config.mjs diff --git a/.cursor/debug.log b/.cursor/debug.log new file mode 100644 index 0000000..e257028 --- /dev/null +++ b/.cursor/debug.log @@ -0,0 +1,28 @@ +{"location":"Logo.tsx:15","message":"Logo component render","data":{"variant":"white","size":"medium","className":"w-16 h-16 md:w-24 md:h-24"},"timestamp":1766959674202,"sessionId":"debug-session","runId":"run1","hypothesisId":"E"} +{"location":"Logo.tsx:22","message":"Logo path construction","data":{"basePath":"/media/logos/logo_white_medium","fallbackPath":"/media/logo_white.png","processedPath":"/media/logos/logo_white_medium@1x.png"},"timestamp":1766959674202,"sessionId":"debug-session","runId":"run1","hypothesisId":"F"} +{"location":"Logo.tsx:15","message":"Logo component render","data":{"variant":"black","size":"small","className":"w-12 h-12"},"timestamp":1766959682790,"sessionId":"debug-session","runId":"run1","hypothesisId":"E"} +{"location":"Logo.tsx:15","message":"Logo component render","data":{"variant":"white","size":"medium","className":"w-16 h-16 md:w-24 md:h-24"},"timestamp":1766959682805,"sessionId":"debug-session","runId":"run1","hypothesisId":"E"} +{"location":"Logo.tsx:22","message":"Logo path construction","data":{"basePath":"/media/logos/logo_black_small","fallbackPath":"/media/logo_black.png","processedPath":"/media/logos/logo_black_small@1x.png"},"timestamp":1766959682790,"sessionId":"debug-session","runId":"run1","hypothesisId":"F"} +{"location":"Logo.tsx:15","message":"Logo component render","data":{"variant":"white","size":"medium","className":"w-16 h-16 md:w-24 md:h-24"},"timestamp":1766959682790,"sessionId":"debug-session","runId":"run1","hypothesisId":"E"} +{"location":"Logo.tsx:22","message":"Logo path construction","data":{"basePath":"/media/logos/logo_white_medium","fallbackPath":"/media/logo_white.png","processedPath":"/media/logos/logo_white_medium@1x.png"},"timestamp":1766959682790,"sessionId":"debug-session","runId":"run1","hypothesisId":"F"} +{"location":"Logo.tsx:22","message":"Logo path construction","data":{"basePath":"/media/logos/logo_white_medium","fallbackPath":"/media/logo_white.png","processedPath":"/media/logos/logo_white_medium@1x.png"},"timestamp":1766959682805,"sessionId":"debug-session","runId":"run1","hypothesisId":"F"} +{"location":"Logo.tsx:15","message":"Logo component render","data":{"variant":"black","size":"small","className":"w-12 h-12"},"timestamp":1766959682796,"sessionId":"debug-session","runId":"run1","hypothesisId":"E"} +{"location":"Logo.tsx:22","message":"Logo path construction","data":{"basePath":"/media/logos/logo_black_small","fallbackPath":"/media/logo_black.png","processedPath":"/media/logos/logo_black_small@1x.png"},"timestamp":1766959682796,"sessionId":"debug-session","runId":"run1","hypothesisId":"F"} +{"location":"Logo.tsx:15","message":"Logo component render","data":{"variant":"black","size":"small","className":"w-12 h-12"},"timestamp":1766959683932,"sessionId":"debug-session","runId":"run1","hypothesisId":"E"} +{"location":"Logo.tsx:22","message":"Logo path construction","data":{"basePath":"/media/logos/logo_black_small","fallbackPath":"/media/logo_black.png","processedPath":"/media/logos/logo_black_small@1x.png"},"timestamp":1766959683933,"sessionId":"debug-session","runId":"run1","hypothesisId":"F"} +{"location":"Logo.tsx:15","message":"Logo component render","data":{"variant":"white","size":"medium","className":"w-16 h-16 md:w-24 md:h-24"},"timestamp":1766959683934,"sessionId":"debug-session","runId":"run1","hypothesisId":"E"} +{"location":"Logo.tsx:22","message":"Logo path construction","data":{"basePath":"/media/logos/logo_white_medium","fallbackPath":"/media/logo_white.png","processedPath":"/media/logos/logo_white_medium@1x.png"},"timestamp":1766959683934,"sessionId":"debug-session","runId":"run1","hypothesisId":"F"} +{"location":"Logo.tsx:15","message":"Logo component render","data":{"variant":"black","size":"small","className":"w-12 h-12"},"timestamp":1766959684064,"sessionId":"debug-session","runId":"run1","hypothesisId":"E"} +{"location":"Logo.tsx:22","message":"Logo path construction","data":{"basePath":"/media/logos/logo_black_small","fallbackPath":"/media/logo_black.png","processedPath":"/media/logos/logo_black_small@1x.png"},"timestamp":1766959684064,"sessionId":"debug-session","runId":"run1","hypothesisId":"F"} +{"location":"Logo.tsx:15","message":"Logo component render","data":{"variant":"white","size":"medium","className":"w-16 h-16 md:w-24 md:h-24"},"timestamp":1766959684073,"sessionId":"debug-session","runId":"run1","hypothesisId":"E"} +{"location":"Logo.tsx:22","message":"Logo path construction","data":{"basePath":"/media/logos/logo_white_medium","fallbackPath":"/media/logo_white.png","processedPath":"/media/logos/logo_white_medium@1x.png"},"timestamp":1766959684073,"sessionId":"debug-session","runId":"run1","hypothesisId":"F"} +{"location":"Logo.tsx:15","message":"Logo component render","data":{"variant":"black","size":"small","className":"w-12 h-12"},"timestamp":1766959685074,"sessionId":"debug-session","runId":"run1","hypothesisId":"E"} +{"location":"Logo.tsx:22","message":"Logo path construction","data":{"basePath":"/media/logos/logo_black_small","fallbackPath":"/media/logo_black.png","processedPath":"/media/logos/logo_black_small@1x.png"},"timestamp":1766959685074,"sessionId":"debug-session","runId":"run1","hypothesisId":"F"} +{"location":"Logo.tsx:15","message":"Logo component render","data":{"variant":"white","size":"medium","className":"w-16 h-16 md:w-24 md:h-24"},"timestamp":1766959685074,"sessionId":"debug-session","runId":"run1","hypothesisId":"E"} +{"location":"Logo.tsx:22","message":"Logo path construction","data":{"basePath":"/media/logos/logo_white_medium","fallbackPath":"/media/logo_white.png","processedPath":"/media/logos/logo_white_medium@1x.png"},"timestamp":1766959685075,"sessionId":"debug-session","runId":"run1","hypothesisId":"F"} +{"location":"Logo.tsx:35","message":"Logo image load error","data":{"variant":"black","size":"small","attemptedPath":"/media/logo_black.png"},"timestamp":1766959685082,"sessionId":"debug-session","runId":"run1","hypothesisId":"H"} +{"location":"Logo.tsx:15","message":"Logo component render","data":{"variant":"black","size":"small","className":"w-12 h-12"},"timestamp":1766959685083,"sessionId":"debug-session","runId":"run1","hypothesisId":"E"} +{"location":"Logo.tsx:22","message":"Logo path construction","data":{"basePath":"/media/logos/logo_black_small","fallbackPath":"/media/logo_black.png","processedPath":"/media/logos/logo_black_small@1x.png"},"timestamp":1766959685084,"sessionId":"debug-session","runId":"run1","hypothesisId":"F"} +{"location":"Logo.tsx:15","message":"Logo component render","data":{"variant":"white","size":"medium","className":"w-16 h-16 md:w-24 md:h-24"},"timestamp":1766959685084,"sessionId":"debug-session","runId":"run1","hypothesisId":"E"} +{"location":"Logo.tsx:22","message":"Logo path construction","data":{"basePath":"/media/logos/logo_white_medium","fallbackPath":"/media/logo_white.png","processedPath":"/media/logos/logo_white_medium@1x.png"},"timestamp":1766959685084,"sessionId":"debug-session","runId":"run1","hypothesisId":"F"} +{"location":"Logo.tsx:35","message":"Logo image load error","data":{"variant":"white","size":"medium","attemptedPath":"/media/logo_white.png"},"timestamp":1766959685090,"sessionId":"debug-session","runId":"run1","hypothesisId":"H"} diff --git a/.cursor/plans/convert_vite_react_app_to_astro_2308e4b5.plan.md b/.cursor/plans/convert_vite_react_app_to_astro_2308e4b5.plan.md new file mode 100644 index 0000000..6e6b533 --- /dev/null +++ b/.cursor/plans/convert_vite_react_app_to_astro_2308e4b5.plan.md @@ -0,0 +1,326 @@ +--- +name: Convert Vite React App to Astro +overview: "" +todos: [] +--- + +# Convert Vite React App to Astro + +Convert the Vite React SPA in `dev/generated/` to an Astro application following Astro conventions, preserving functionality and design while leveraging Astro's file-based routing and island architecture. + +## Architecture Overview + +The conversion will transform the single-page React app into an Astro multi-page application with: + +- File-based routing: `/` (home) and `/publications` (publications page) +- Astro layouts for shared structure (header, footer) +- React islands for interactive components (language switcher, filters, scroll animations) +- Client-side language switching preserved +- Design system integrated via TailwindCSS configuration + +**Key Principle: Reuse Existing Code** + +- Copy React components from `dev/generated/components/` with minimal modifications +- Extract header/footer logic from `App.tsx` rather than rewriting +- Preserve all scroll animations, state management, and interactivity as-is +- Only adapt what's necessary for Astro integration (imports, props passing) + +## Implementation Steps + +### 1. Setup and Configuration + +**Files to create/modify:** + +- `tailwind.config.mjs` - Configure TailwindCSS with brand colors, fonts, and animations from `design.json` +- `src/styles/global.css` - Update with brand colors, fonts, and custom animations +- `astro.config.mjs` - Ensure React integration is configured (already present) + +**Key changes:** + +- Extract Tailwind config from `index.html` to proper Tailwind config file +- Add brand color palette, font families (Inter, Oswald, Permanent Marker), and custom animations (blob, float, marquee) +- Configure font loading in BaseLayout + +### 2. Content Structure + +**Files to copy (reuse as-is):** + +- `src/content/content.ts` - **Copy** `dev/generated/content.ts` here (bilingual content structure) +- `src/types.ts` - **Copy** `dev/generated/types.ts` here (TypeScript types) + +**Key changes:** + +- Keep content structure as TypeScript module (not content collections) since it's structured data, not markdown +- Preserve bilingual `CONTENT` object structure exactly as it exists +- No modifications needed - these are pure data/type files + +### 2.5. Logo Image Processing + +**Files to create:** + +- `src/utils/process-logos.js` - Script to process logo images with ffmpeg + +**Process logo images:** + +- Source images: `public/media/logo_black.png`, `public/media/logo_col.png`, `public/media/logo_white.png` (786x1334px) +- Preserve aspect ratio: ~0.589 (786/1334) +- Generate multiple sizes for different use cases: +- Small (header): 28x48px (1x), 56x96px (2x) +- Medium (footer): 57x96px (1x), 114x192px (2x) +- Large (hero/featured): 118x200px (1x), 236x400px (2x) +- Formats: WebP (modern), AVIF (best compression), PNG (fallback) +- Output location: `public/media/logos/` with naming: `logo_{variant}_{size}@{density}.{format}` + +**ffmpeg commands:** + +- Resize preserving aspect ratio +- Convert to WebP and AVIF formats +- Maintain quality while optimizing file size + +### 3. Component Conversion + +**Strategy: Copy and Adapt (Minimal Changes)Pure Astro components (new, replacing SVG):** + +- `src/components/Logo.astro` - **NEW** Astro component using processed logo images +- Accept props: `variant` ('black' | 'col' | 'white'), `size` ('small' | 'medium' | 'large'), `className` +- Use Astro's `` component for optimization +- Provide srcset for responsive images (1x, 2x) +- Fallback to PNG if WebP/AVIF not supported +- **Replaces** `dev/generated/components/Logo.tsx` (SVG version) + +**React Components - Copy from `dev/generated/components/` with minimal changes:** + +- `src/components/Reveal.tsx` - **COPY** `dev/generated/components/Reveal.tsx` as-is +- No changes needed - pure React component with Intersection Observer +- Use as React island (client:load) +- `src/components/Button.tsx` - **COPY** `dev/generated/components/Button.tsx` as-is +- No changes needed - reusable button component +- Use as React island (client:load) +- `src/components/ArticleCard.tsx` - **COPY** `dev/generated/components/ArticleCard.tsx` as-is +- No changes needed - article card component +- Use as React island (client:load) if interactive +- `src/components/Home.tsx` - **COPY** `dev/generated/components/Home.tsx` with minimal adaptions +- Keep all scroll animations, parallax effects, and state management exactly as-is +- Only change: Update Logo import to use new Logo.astro (or pass as prop) +- Update import paths if needed (content.ts, types.ts) +- Use as React island (client:load) +- `src/components/Publications.tsx` - **COPY** `dev/generated/components/Publications.tsx` with minimal adaptions +- Keep all filter logic, state management exactly as-is +- Only change: Update import paths if needed (types.ts, Reveal.tsx) +- Use as React island (client:load) + +**Header/Footer - Extract from App.tsx:** + +- `src/components/Header.tsx` - **EXTRACT** header JSX from `App.tsx` (lines 54-130) +- Extract the `