diff --git a/.cursor/worktrees.json b/.cursor/worktrees.json new file mode 100644 index 0000000..f862bfd --- /dev/null +++ b/.cursor/worktrees.json @@ -0,0 +1,7 @@ +{ + "setup-worktree": [ + "# fnm use", + "# npm install", + "# cp $ROOT_WORKTREE_PATH/.env .env" + ] +} diff --git a/IMPLEMENTATION_COMPLETE.md b/IMPLEMENTATION_COMPLETE.md new file mode 100644 index 0000000..ac49449 --- /dev/null +++ b/IMPLEMENTATION_COMPLETE.md @@ -0,0 +1,124 @@ +# Portfolio Site Integration - Implementation Complete + +## Summary + +Successfully implemented the V7 Industrial Dark Mode design system for Nicholai Vogel's portfolio site, integrating all components from the reference `index.html` into the Astro blog template. + +## Completed Tasks + +### Phase 1: Foundation Setup ✅ +- **Updated `src/styles/global.css`**: Configured Tailwind v4 with V7 design system tokens + - Brand colors (dark, panel, accent, cyan) + - Font families (Inter + Space Mono) + - Custom utilities (grid-overlay, text-massive, text-stroke, skill-tag, btn-primary, btn-ghost) + - Scrollbar styling, reveal animations + - Prose/blog content styles + +- **Updated `src/consts.ts`**: Added site metadata + - Contact information (email, phone) + - Location and timezone + - Availability status + - Social links (website, Instagram, LinkedIn, Biohazard) + - Navigation links + +### Phase 2: Core Components ✅ +- **Modified `src/components/BaseHead.astro`**: + - Added Google Fonts preconnect and stylesheet (Inter, Space Mono) + - Added Lucide icons CDN script + - Removed old Atkinson font preloads + - Kept canonical links and meta tags per user preferences + +- **Created Layout Components**: + - `src/components/GridOverlay.astro`: Fixed background grid + 12-column guide + - `src/components/Navigation.astro`: Fixed nav with logo, status badge, links, contact CTA + - `src/components/Footer.astro`: Contact CTA, social links, copyright, decorative text + - `src/components/CustomCursor.tsx`: React island for custom cursor with dot + outline + +- **Created Section Components** (in `src/components/sections/`): + - `Hero.astro`: Hero section with massive typography, description, live clock + - `Experience.astro`: Timeline with Biohazard VFX, Stinkfilms, Freelance + - `FeaturedProject.astro`: G-Star Raw Olympics full-width showcase + - `Skills.astro`: Technical arsenal 4-column grid + +### Phase 3: Layouts ✅ +- **Created `src/layouts/BaseLayout.astro`**: + - Wraps BaseHead, GridOverlay, Navigation, main slot, Footer + - Includes CustomCursor React island with `client:load` + - Body classes for selection styling + - Inline script for Lucide icons initialization and reveal animations + +- **Kept `src/layouts/BlogPost.astro`**: Already styled for V7 dark theme + +### Phase 4: Pages ✅ +- **`src/pages/index.astro`**: Already composed with all section components: + - Hero → Divider → Experience → Divider → FeaturedProject → Skills + +- **`src/pages/blog/index.astro`**: Already styled with dark theme, card hover effects + +- **`src/pages/blog/[...slug].astro`**: Uses BlogPost layout (no changes needed) + +- **Removed `src/pages/about.astro`**: Already deleted + +### Phase 5: Build & Verify ✅ +- Build command executed successfully (exit code 0) +- All files created and properly structured +- No syntax errors detected in components + +## Key Files Modified + +1. `src/styles/global.css` - Complete rewrite with Tailwind v4 and V7 design system +2. `src/consts.ts` - Updated with Nicholai's site metadata +3. `src/components/BaseHead.astro` - Updated fonts and icons +4. `src/components/Footer.astro` - Complete rewrite +5. `src/layouts/BaseLayout.astro` - New shared layout + +## Key Files Created + +1. `src/components/GridOverlay.astro` +2. `src/components/Navigation.astro` +3. `src/components/CustomCursor.tsx` +4. `src/components/sections/Hero.astro` +5. `src/components/sections/Experience.astro` +6. `src/components/sections/FeaturedProject.astro` +7. `src/components/sections/Skills.astro` +8. `src/layouts/BaseLayout.astro` + +## Design System Features Implemented + +- **Colors**: Dark mode with brand colors (dark #0B0D11, accent #FFB84C, cyan #22D3EE) +- **Typography**: Inter (primary) + Space Mono (monospace), massive hero text +- **Grid System**: Visible 12-column grid overlay as design element +- **Custom Cursor**: Animated dot + outline (React component) +- **Animations**: Reveal text on scroll, smooth transitions, hover effects +- **Components**: Buttons (primary, ghost), skill tags, prose styling +- **Navigation**: Fixed header with status badge and contact CTA +- **Footer**: Large typography with social links and decorative elements + +## Next Steps for User + +1. **Test the site**: Run `pnpm dev` to view the site locally +2. **Verify responsive design**: Check mobile, tablet, and desktop layouts +3. **Update content**: Customize experience timeline, project details, skills as needed +4. **Add images**: Replace placeholder images with actual project images +5. **Deploy**: Run `pnpm deploy` to publish to Cloudflare Pages + +## Technical Notes + +- Using Tailwind CSS v4 with @theme directive +- React integration for interactive custom cursor +- Lucide icons via CDN +- Google Fonts (Inter + Space Mono) loaded via CDN with preconnect +- Intersection Observer for scroll-triggered reveal animations +- Responsive breakpoints: sm (640px), md (768px), lg (1024px) +- Custom scrollbar styling for webkit browsers +- Selection styling with brand accent color + +## Browser Support + +Modern browsers supporting: +- CSS custom properties +- Backdrop blur +- Mix blend modes +- Grid layout +- Custom scrollbars (webkit) + diff --git a/dev/plan.md b/dev/plan.md new file mode 100644 index 0000000..4f365cd --- /dev/null +++ b/dev/plan.md @@ -0,0 +1,125 @@ +# Portfolio Site Integration Plan + +## Phase 1: Foundation Setup + +### Tailwind Configuration + +Update `src/styles/global.css` to configure Tailwind v4 with the V7 design system tokens from `design.json`: + +- Brand colors (dark: #0B0D11, panel: #151921, accent: #FFB84C, cyan: #22D3EE) +- Font families (Inter + Space Mono from Google Fonts) +- Custom utilities (grid-overlay, text-massive, text-stroke, skill-tag, btn-primary, btn-ghost) +- Scrollbar styling, reveal animations, cursor styles + +### Constants Update + +Update `src/consts.ts` with Nicholai's site metadata: + +- SITE_TITLE, SITE_DESCRIPTION, contact info, social links + +## Phase 2: Core Components + +### BaseHead.astro + +Modify to include: + +- Google Fonts preconnect/stylesheet (Inter, Space Mono) +- Lucide icons CDN script +- Remove old Atkinson font preloads + +### Layout Components (new files in `src/components/`) + +Extract from index.html: + +| Component | Purpose | + +|-----------|---------| + +| `GridOverlay.astro` | Fixed background grid + 12-column guide | + +| `Navigation.astro` | Fixed nav with logo, status badge, links, contact CTA | + +| `Footer.astro` | Replace existing - contact CTA, social links, copyright | + +| `CustomCursor.tsx` | React island for cursor dot + outline with mousemove tracking | + +### Section Components (new files in `src/components/sections/`) + +| Component | Purpose | + +|-----------|---------| + +| `Hero.astro` | Hero with title, subtitle, description, clock | + +| `Experience.astro` | Timeline with Biohazard VFX, Stinkfilms, Freelance | + +| `FeaturedProject.astro` | G-Star Raw Olympics full-width showcase | + +| `Skills.astro` | Technical arsenal 4-column grid | + +## Phase 3: Layouts + +### BaseLayout.astro (new) + +Create shared layout wrapping: + +- BaseHead, GridOverlay, Navigation, main slot, Footer, CustomCursor island +- Body classes: `antialiased selection:bg-brand-accent selection:text-brand-dark` + +### BlogPost.astro + +Restyle to match V7 dark theme while keeping content structure. + +## Phase 4: Pages + +### index.astro + +Compose from section components: + +```astro + + + + + + + + +``` + +### blog/index.astro + +Restyle post grid with dark theme, card hover effects, accent colors. + +### blog/[...slug].astro + +Uses updated BlogPost layout (no changes needed to routing logic). + +### Delete about.astro + +Remove the about page entirely. + +## Phase 5: Assets + +- Add favicon matching brand identity to `public/` +- Keep existing blog placeholder images +- Fonts served via Google Fonts CDN (no local files needed) + +## Key Files to Modify + +- `src/styles/global.css` - Tailwind config + custom CSS +- `src/consts.ts` - Site metadata +- `src/components/BaseHead.astro` - Font/icon loading +- `src/components/Footer.astro` - Complete rewrite +- `src/layouts/BlogPost.astro` - Restyle for dark theme + +## Key Files to Create + +- `src/components/GridOverlay.astro` +- `src/components/Navigation.astro` +- `src/components/CustomCursor.tsx` +- `src/components/sections/Hero.astro` +- `src/components/sections/Experience.astro` +- `src/components/sections/FeaturedProject.astro` +- `src/components/sections/Skills.astro` +- `src/layouts/BaseLayout.astro` diff --git a/public/favicon.svg b/public/favicon.svg index f157bd1..6f7dc41 100644 --- a/public/favicon.svg +++ b/public/favicon.svg @@ -1,9 +1,5 @@ - - - + + + + NV diff --git a/src/components/BaseHead.astro b/src/components/BaseHead.astro index a0f9a7c..ce2bf4a 100644 --- a/src/components/BaseHead.astro +++ b/src/components/BaseHead.astro @@ -30,9 +30,18 @@ const { title, description, image = FallbackImage } = Astro.props; /> - - - + + + + + @@ -55,3 +64,6 @@ const { title, description, image = FallbackImage } = Astro.props; + + + diff --git a/src/components/CustomCursor.tsx b/src/components/CustomCursor.tsx new file mode 100644 index 0000000..b6b299f --- /dev/null +++ b/src/components/CustomCursor.tsx @@ -0,0 +1,51 @@ +import { useEffect, useState } from 'react'; + +export default function CustomCursor() { + const [position, setPosition] = useState({ x: 0, y: 0 }); + const [isVisible, setIsVisible] = useState(false); + + useEffect(() => { + const updatePosition = (e: MouseEvent) => { + setPosition({ x: e.clientX, y: e.clientY }); + if (!isVisible) setIsVisible(true); + }; + + const handleMouseLeave = () => { + setIsVisible(false); + }; + + window.addEventListener('mousemove', updatePosition); + document.addEventListener('mouseleave', handleMouseLeave); + + return () => { + window.removeEventListener('mousemove', updatePosition); + document.removeEventListener('mouseleave', handleMouseLeave); + }; + }, [isVisible]); + + if (!isVisible) return null; + + return ( + <> + {/* Cursor Dot */} +
+ + {/* Cursor Outline */} +
+ + ); +} diff --git a/src/components/Footer.astro b/src/components/Footer.astro index 96c2fce..42b7e79 100644 --- a/src/components/Footer.astro +++ b/src/components/Footer.astro @@ -1,62 +1,53 @@ --- -const today = new Date(); +import { CONTACT_EMAIL, CONTACT_PHONE, SOCIAL_LINKS } from '../consts'; --- -
- © {today.getFullYear()} Your name here. All rights reserved. - +
+ + diff --git a/src/pages/about.astro b/src/pages/about.astro deleted file mode 100644 index 86c7499..0000000 --- a/src/pages/about.astro +++ /dev/null @@ -1,63 +0,0 @@ ---- -import AboutHeroImage from '../assets/blog-placeholder-about.jpg'; -import Layout from '../layouts/BlogPost.astro'; ---- - - -

- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut - labore et dolore magna aliqua. Vitae ultricies leo integer malesuada nunc vel risus commodo - viverra. Adipiscing enim eu turpis egestas pretium. Euismod elementum nisi quis eleifend quam - adipiscing. In hac habitasse platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus - et malesuada fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus - vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea dictumst quisque - sagittis. Integer quis auctor elit sed vulputate mi. Dictumst quisque sagittis purus sit amet. -

- -

- Morbi tristique senectus et netus. Id semper risus in hendrerit gravida rutrum quisque non - tellus. Habitasse platea dictumst quisque sagittis purus sit amet. Tellus molestie nunc non - blandit massa. Cursus vitae congue mauris rhoncus. Accumsan tortor posuere ac ut. Fringilla urna - porttitor rhoncus dolor. Elit ullamcorper dignissim cras tincidunt lobortis. In cursus turpis - massa tincidunt dui ut ornare lectus. Integer feugiat scelerisque varius morbi enim nunc. - Bibendum neque egestas congue quisque egestas diam. Cras ornare arcu dui vivamus arcu felis - bibendum. Dignissim suspendisse in est ante in nibh mauris. Sed tempus urna et pharetra pharetra - massa massa ultricies mi. -

- -

- Mollis nunc sed id semper risus in. Convallis a cras semper auctor neque. Diam sit amet nisl - suscipit. Lacus viverra vitae congue eu consequat ac felis donec. Egestas integer eget aliquet - nibh praesent tristique magna sit amet. Eget magna fermentum iaculis eu non diam. In vitae - turpis massa sed elementum. Tristique et egestas quis ipsum suspendisse ultrices. Eget lorem - dolor sed viverra ipsum. Vel turpis nunc eget lorem dolor sed viverra. Posuere ac ut consequat - semper viverra nam. Laoreet suspendisse interdum consectetur libero id faucibus. Diam phasellus - vestibulum lorem sed risus ultricies tristique. Rhoncus dolor purus non enim praesent elementum - facilisis. Ultrices tincidunt arcu non sodales neque. Tempus egestas sed sed risus pretium quam - vulputate. Viverra suspendisse potenti nullam ac tortor vitae purus faucibus ornare. Fringilla - urna porttitor rhoncus dolor purus non. Amet dictum sit amet justo donec enim. -

- -

- Mattis ullamcorper velit sed ullamcorper morbi tincidunt. Tortor posuere ac ut consequat semper - viverra. Tellus mauris a diam maecenas sed enim ut sem viverra. Venenatis urna cursus eget nunc - scelerisque viverra mauris in. Arcu ac tortor dignissim convallis aenean et tortor at. Curabitur - gravida arcu ac tortor dignissim convallis aenean et tortor. Egestas tellus rutrum tellus - pellentesque eu. Fusce ut placerat orci nulla pellentesque dignissim enim sit amet. Ut enim - blandit volutpat maecenas volutpat blandit aliquam etiam. Id donec ultrices tincidunt arcu. Id - cursus metus aliquam eleifend mi. -

- -

- Tempus quam pellentesque nec nam aliquam sem. Risus at ultrices mi tempus imperdiet. Id porta - nibh venenatis cras sed felis eget velit. Ipsum a arcu cursus vitae. Facilisis magna etiam - tempor orci eu lobortis elementum. Tincidunt dui ut ornare lectus sit. Quisque non tellus orci - ac. Blandit libero volutpat sed cras. Nec tincidunt praesent semper feugiat nibh sed pulvinar - proin gravida. Egestas integer eget aliquet nibh praesent tristique magna. -

-
diff --git a/src/pages/blog/index.astro b/src/pages/blog/index.astro index 5b08c9f..86cb79d 100644 --- a/src/pages/blog/index.astro +++ b/src/pages/blog/index.astro @@ -1,114 +1,52 @@ --- import { Image } from 'astro:assets'; import { getCollection } from 'astro:content'; -import BaseHead from '../../components/BaseHead.astro'; -import Footer from '../../components/Footer.astro'; +import BaseLayout from '../../layouts/BaseLayout.astro'; import FormattedDate from '../../components/FormattedDate.astro'; -import Header from '../../components/Header.astro'; -import { SITE_DESCRIPTION, SITE_TITLE } from '../../consts'; +import { SITE_TITLE, SITE_DESCRIPTION } from '../../consts'; const posts = (await getCollection('blog')).sort( (a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf(), ); --- - - - - - - - -
-
-
- -
-
-
+ + diff --git a/src/pages/index.astro b/src/pages/index.astro index 55caf7e..494f989 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,49 +1,19 @@ --- -import BaseHead from '../components/BaseHead.astro'; -import Footer from '../components/Footer.astro'; -import Header from '../components/Header.astro'; -import { SITE_DESCRIPTION, SITE_TITLE } from '../consts'; +import BaseLayout from '../layouts/BaseLayout.astro'; +import Hero from '../components/sections/Hero.astro'; +import Experience from '../components/sections/Experience.astro'; +import FeaturedProject from '../components/sections/FeaturedProject.astro'; +import Skills from '../components/sections/Skills.astro'; +import { SITE_TITLE, SITE_DESCRIPTION } from '../consts'; --- - - - - - - -
-
-

🧑‍🚀 Hello, Astronaut!

-

- Welcome to the official Astro blog starter template. This - template serves as a lightweight, minimally-styled starting point for anyone looking to build - a personal website, blog, or portfolio with Astro. -

-

- This template comes with a few integrations already configured in your - astro.config.mjs file. You can customize your setup with - Astro Integrations to add tools like Tailwind, - React, or Vue to your project. -

-

Here are a few ideas on how to get started with the template:

-
    -
  • Edit this page in src/pages/index.astro
  • -
  • Edit the site header items in src/components/Header.astro
  • -
  • Add your name to the footer in src/components/Footer.astro
  • -
  • Check out the included blog posts in src/content/blog/
  • -
  • Customize the blog post page layout in src/layouts/BlogPost.astro
  • -
-

- Have fun! If you get stuck, remember to - read the docs - or join us on Discord to ask questions. -

-

- Looking for a blog template with a bit more personality? Check out - astro-blog-template - by Maxi Ferreira. -

-
-