From 50f9a2df68e3840db515ce93bf261e1dd8a798ea Mon Sep 17 00:00:00 2001 From: Nicholai Date: Thu, 18 Dec 2025 15:22:34 -0700 Subject: [PATCH] Remove dev documentation and add design spec to CLAUDE.md - Delete dev/CLAUDE.md, dev/blog-example.html, dev/contact-form-plan.md, dev/index.html, dev/optimization-guidelines.md, dev/plan.md - Update CLAUDE.md to include Design Specification section referencing dev/design.json - Modify dev/design.json with V7 Industrial Dark Mode system details - Update src/utils/git-commit.js to reflect new commit message format --- CLAUDE.md | 11 +- dev/CLAUDE.md | 61 ---- dev/blog-example.html | 1 - dev/contact-form-plan.md | 262 -------------- dev/design.json | 3 +- dev/index.html | 603 --------------------------------- dev/optimization-guidelines.md | 243 ------------- dev/plan.md | 125 ------- 8 files changed, 8 insertions(+), 1301 deletions(-) delete mode 100644 dev/CLAUDE.md delete mode 100644 dev/blog-example.html delete mode 100644 dev/contact-form-plan.md delete mode 100644 dev/index.html delete mode 100644 dev/optimization-guidelines.md delete mode 100644 dev/plan.md diff --git a/CLAUDE.md b/CLAUDE.md index bf381ba..f3c0bfc 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -88,10 +88,13 @@ MDX file → src/content.config.ts schema → getCollection() → Component prop - Static files in `public/media/` are served as-is (use absolute paths like `/media/file.mp4`) - AVIF conversion utility available for optimization -### Styling -- Tailwind CSS v4 via Vite plugin -- Custom animation classes: `.animate-on-scroll`, `.slide-up`, `.stagger-*`, `.fade-in` -- Monospace font used for technical labels and metadata +## Design Specification + +`dev/design.json` contains V7 Industrial Dark Mode system specification (not yet implemented): +- Dark mode native with `#0B0D11` primary background +- Orange/yellow accent `#FFB84C` for CTAs +- Brutalist/industrial aesthetic with visible grid structure +- Heavy typography emphasis ### Deployment - Cloudflare Pages adapter configured in `astro.config.mjs` diff --git a/dev/CLAUDE.md b/dev/CLAUDE.md deleted file mode 100644 index 30196fb..0000000 --- a/dev/CLAUDE.md +++ /dev/null @@ -1,61 +0,0 @@ -# CLAUDE.md - -This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. - -## Project Overview - -Astro 5 blog with Cloudflare Pages deployment. Uses PNPM as package manager. - -## Commands - -```bash -pnpm dev # Start dev server at localhost:4321 -pnpm build # Build production site to ./dist/ -pnpm preview # Build and preview locally via Wrangler -pnpm deploy # Build and deploy to Cloudflare Pages -pnpm cf-typegen # Generate Wrangler types for Cloudflare bindings -``` - -## Architecture - -### Content System -- Blog posts in `src/content/blog/` as Markdown/MDX files -- Content schema defined in `src/content.config.ts` with Zod validation -- Required frontmatter: `title`, `description`, `pubDate` -- Optional frontmatter: `updatedDate`, `heroImage` - -### Routing -- `src/pages/` - File-based routing -- `src/pages/blog/[...slug].astro` - Dynamic blog post routes -- `src/pages/rss.xml.js` - RSS feed endpoint - -### Components -- `src/components/BaseHead.astro` - SEO metadata, og:image, Twitter cards -- `src/layouts/BlogPost.astro` - Blog post layout template -- `src/consts.ts` - Site title and description constants - -### Styling -- Tailwind CSS via Vite plugin -- Design tokens in `src/styles/global.css` as CSS custom properties -- Current accent color: `#2337ff` (blue) -- Max content width: 720px - -### Cloudflare Integration -- Adapter: `@astrojs/cloudflare` with platform proxy enabled -- Wrangler config: `wrangler.jsonc` -- Environment types: `src/env.d.ts` -- Node.js compatibility enabled via `nodejs_compat` flag - -## Design Specification - -`design.json` contains V7 Industrial Dark Mode system specification (not yet implemented): -- Dark mode native with `#0B0D11` primary background -- Orange/yellow accent `#FFB84C` for CTAs -- Brutalist/industrial aesthetic with visible grid structure -- Heavy typography emphasis - -## Key Configuration - -- **Site URL**: Currently `https://example.com` in `astro.config.mjs` - update for production -- **Project name**: `nicholai-work-2026` in `wrangler.jsonc` -- **TypeScript**: Strict mode with Astro and Cloudflare Worker types diff --git a/dev/blog-example.html b/dev/blog-example.html deleted file mode 100644 index 050b765..0000000 --- a/dev/blog-example.html +++ /dev/null @@ -1 +0,0 @@ -

Become an AI-Powered Marketer

The Averi Blog

Don't Feed the Algorithm

By signing up you agree to our privacy policy

Latest

Search

Don't Feed the Algorithm

“Top 3 tech + AI newsletters in the country. Always sharp, always actionable.”

"Genuinely my favorite newsletter in tech. No fluff, no cheesy ads, just great content."

“Clear, practical, and on-point. Helps me keep up without drowning in noise.”

\ No newline at end of file diff --git a/dev/contact-form-plan.md b/dev/contact-form-plan.md deleted file mode 100644 index 9185a15..0000000 --- a/dev/contact-form-plan.md +++ /dev/null @@ -1,262 +0,0 @@ -# Contact Form → n8n Webhook with Personalized MDX Response Plan - -## Overview -Wire the existing Astro contact form to an n8n webhook using `PUBLIC_N8N_WEBHOOK_URL`, enable n8n to return a personalized MDX/Markdown message, render it on the client, and implement automatic fallback to a standard toast notification when n8n is down or fails. - ---- - -## Implementation Steps - -### 1. n8n Webhook + Environment Setup - -**Verify n8n Webhook Configuration:** -- In your n8n instance, create or verify a Webhook node configured for `POST` requests -- Use a path like `contact-form` -- Note the complete webhook URL (e.g., `https://your-n8n-instance.com/webhook/contact-form`) - -**Define Response Contract:** -The n8n workflow should return JSON in one of these formats: -- **Success:** `{ success: true, format: 'mdx', message: '...markdown/mdx string...' }` -- **Handled Error:** `{ success: false, error: 'Human-friendly error message' }` - -**Environment Variable:** -- Confirm `PUBLIC_N8N_WEBHOOK_URL` is set in `.env` with the webhook URL -- Ensure the same variable is configured in your Cloudflare Pages environment settings -- Optional: Update `env.d.ts` to type `import.meta.env.PUBLIC_N8N_WEBHOOK_URL` for TypeScript safety - ---- - -### 2. Wire Astro Contact Form to n8n (with Robust Error Detection) - -**File to modify:** `src/pages/contact.astro` - -**Form Markup Updates:** -- Add `id="contact-form"` to the form element -- Remove `action="#"` and `method="POST"` attributes (JavaScript will handle submission) -- Preserve all existing classes, labels, and the custom subject dropdown - -**Client-Side Submit Handler:** -Add a new script block (or extend the existing one) with: - -1. **Form submission interception:** - - Attach a `submit` event listener that calls `preventDefault()` - - Extract form data using `FormData` API - - Build JSON payload including: - - `name`, `email`, `subject`, `message` - - Metadata: `timestamp` (ISO string), `source: 'portfolio-website'` - -2. **Fetch with timeout wrapper:** - - Use `fetch(import.meta.env.PUBLIC_N8N_WEBHOOK_URL, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) })` - - Wrap with `AbortController` or `Promise.race` for 8-10 second timeout - -3. **Failure detection conditions** (any of these triggers fallback): - - Network error or thrown exception - - Timeout reached - - Non-2xx HTTP response - - 2xx response with `success: false` in JSON - -4. **Success path:** - - Extract the `message` field from response - - Pass to MDX/Markdown rendering logic (see Step 3) - - Show brief success state on submit button - -5. **Failure path:** - - Display standard toast notification with error message - - Keep form data intact (don't reset) - - Re-enable submit button - -**Button UX States:** -- **Waiting:** Disable button, change text to "Transmitting..." -- **Success:** Briefly show "Message Sent!" then re-enable -- **Failure:** Show "Transmission Failed" then revert to original text - ---- - -### 3. Render Personalized MDX/Markdown Response - -**Add Markdown Renderer:** -- Install a lightweight markdown library via `pnpm add marked` (or `markdown-it`) -- Import it in the client-side script section - -**Response Panel UI:** -- Create a dedicated container near the form submit area (e.g., bordered card) -- Initially hidden (`hidden` class or `display: none`) -- Becomes visible only when successful response is received -- Style with existing design system classes for consistency - -**Rendering Logic:** -When response has `success: true` and `format: 'mdx'`: -1. Convert the `message` string to HTML using the markdown library -2. Inject into response panel using `innerHTML` -3. Apply typography classes (`prose` or custom) for proper formatting -4. If markdown conversion throws, treat as failure and show fallback toast - -**Accessibility:** -- Add `role="status"` to the response panel -- Ensure proper color contrast -- Test with keyboard navigation and screen readers - -**Security:** -- Since content comes from your own n8n instance, it's trusted -- Still avoid allowing script tags in the markdown content -- Keep response panel visually constrained - ---- - -### 4. n8n Workflow Processing & Templating - -**In your n8n workflow (after the Webhook node):** - -**Template the Personalized Message:** -- Use Set or Function nodes to build a Markdown/MDX string -- Use incoming fields like `{{ $json.name }}`, `{{ $json.subject }}`, `{{ $json.message }}` -- Example structure: - ```markdown - # Thanks, {{ name }}! - - I received your message about **{{ subject }}**. - - I'll review it and get back to you within 24-48 hours at {{ email }}. - - In the meantime, feel free to check out [my recent work](/work) or [blog posts](/blog). - - — Nicholai - ``` - -**Workflow Branches:** -- **Validation node:** Check for required fields (name, email, message) - - If missing: Return `{ success: false, error: 'Please fill in all required fields' }` -- **Email notification node:** Send yourself a formatted email with the submission details -- **Optional logging node:** Save to Google Sheets, database, or CRM - -**Webhook Response Node:** -- At the end of the workflow, add a "Respond to Webhook" node -- Return JSON matching the contract: - - Success: `{ success: true, format: 'mdx', message: '...' }` - - Error: `{ success: false, error: '...' }` -- For unexpected internal errors, either: - - Let workflow fail (frontend timeout will catch it), or - - Wrap in try/catch and still return `{ success: false }` - ---- - -### 5. Fallback Toast & Automatic Failure Detection UX - -**Toast Notification Implementation:** -- Create a reusable toast function (if not already present) -- Should support both success and error styles -- Position in top-right or bottom-right of viewport -- Auto-dismiss after 5-7 seconds with smooth fade-out - -**Error Toast Content:** -``` -"We couldn't reach the messaging system. Please try again or email me directly at nicholai@nicholai.work" -``` - -**Automatic Detection:** -- Trigger error toast for any failure condition from Step 2 -- Works even if n8n is completely unreachable (DNS/SSL issues, 500 errors, timeouts) - -**User Experience:** -- On failure: **Do not clear the form** (preserves user's work) -- Optional: Add inline text under submit button: "Auto-response unavailable; message will still be delivered via email" -- Ensure toast has `role="alert"` for accessibility - ---- - -### 6. Testing & Validation - -**Happy Path Tests:** -- With n8n workflow active and webhook listening: - 1. Submit form with various subject/message combinations - 2. Verify n8n receives correct payload with all fields - 3. Confirm n8n builds expected personalized MDX string - 4. Check that frontend displays rendered response panel with proper formatting - 5. Verify email notification is sent - 6. Test that form resets appropriately - -**Failure Path Tests:** -1. **n8n completely down:** - - Stop n8n instance or point env var to invalid URL - - Submit form - - Confirm: Timeout triggers, error toast appears, form data preserved, no response panel shown - -2. **n8n returns error:** - - Modify workflow to return `{ success: false, error: 'Test error' }` - - Submit form - - Confirm: Error toast shows n8n's error message, no response panel - -3. **Network timeout:** - - Add artificial delay in n8n workflow (>10 seconds) - - Confirm: Frontend timeout triggers fallback - -4. **Invalid markdown:** - - Have n8n return malformed markdown that breaks the parser - - Confirm: Rendering error is caught and fallback toast appears - -**Browser & Responsiveness:** -- Test on desktop (Chrome, Firefox, Safari) -- Test on mobile viewport (iOS Safari, Chrome Android) -- Verify response panel and toasts don't break layout -- Check animations and transitions are smooth -- Test with keyboard-only navigation -- Test with screen reader (VoiceOver or NVDA) - -**Production Verification:** -- After deploying with env var configured: - 1. Submit real test message from live site - 2. Confirm end-to-end flow works - 3. Check browser console for CORS errors (adjust n8n/proxy if needed) - 4. Verify SSL/HTTPS works correctly - 5. Test from different networks (WiFi, mobile data) - ---- - -### 7. Future-Proofing Options - -**Server-Side Proxy (Optional):** -If you want to hide the webhook URL and do MDX→HTML conversion server-side: - -1. Create an Astro API route (e.g., `/api/contact.ts`) or Cloudflare Worker -2. Have it: - - Accept form JSON from browser - - Add server-side validation/rate limiting - - Call n8n webhook - - Convert returned MDX to HTML server-side - - Return normalized `{ success, html }` to client -3. Frontend code changes minimally (just POST URL changes) - -**Benefits:** -- Webhook URL never exposed to client -- Additional security layer -- Server-side rate limiting -- Can add spam protection (honeypot, CAPTCHA) - -**Richer MDX Components:** -If you later want actual MDX components (not just markdown): -- Add runtime MDX renderer like `@mdx-js/mdx` on client -- Or render MDX to React components server-side in the proxy route -- Would allow n8n to return interactive components, not just static markdown - ---- - -## Critical Files - -- **`src/pages/contact.astro`** - Main file to modify (form markup + client script) -- **`.env`** - Contains `PUBLIC_N8N_WEBHOOK_URL` -- **`env.d.ts`** - Optional TypeScript environment variable typing -- **n8n workflow** - Webhook node + processing nodes + response node - ---- - -## Success Criteria - -✅ Form submits to n8n webhook successfully -✅ n8n returns personalized MDX message -✅ Frontend renders markdown as HTML in response panel -✅ Timeout/error conditions trigger fallback toast -✅ Form data preserved on failure -✅ Works on desktop and mobile -✅ Accessible to keyboard and screen reader users -✅ No CORS issues in production -✅ Email notifications sent from n8n \ No newline at end of file diff --git a/dev/design.json b/dev/design.json index 7eda148..2b732c2 100644 --- a/dev/design.json +++ b/dev/design.json @@ -40,8 +40,7 @@ "usage": "Secondary backgrounds, panels, cards" }, "brand_accent": { - "hex": "#ff4d00", - "rgb": "255, 77, 0", + "hex": "#dd4132", "name": "Vibrant Orange", "usage": "Primary accent, CTAs, highlights, interactive elements, status indicators", "opacity_variants": [ diff --git a/dev/index.html b/dev/index.html deleted file mode 100644 index d780945..0000000 --- a/dev/index.html +++ /dev/null @@ -1,603 +0,0 @@ - - - - - - - Nicholai Vogel | VFX Artist & Technical Generalist - - - - - - - - - - - - - - - - - - - - - - - - - -
- - -
- - - - - - - - - - - -
- - - - - -
- - -
-
-
-

/// TECHNICAL GENERALIST & VFX - SUPERVISOR

-

- Visual - Alchemist -

-
-
-

- I am a problem solver who loves visual effects. With 10 years of experience creating end-to-end - visual content for clients like Post Malone, Stinkfilms, and Adidas. Comfortable managing teams while staying - knee-deep in hands-on shot work. -

- -
-
- - - -
- - -
- - -
-
-
-

Experience

-

History

-

- From founding my own VFX house to supervising global campaigns. I bridge the gap between - creative vision and technical execution. -

- - Visit Biohazard VFX - -
- -
- -
-
- - -
-
-
-
-

Biohazard VFX

- FOUNDER / VFX - SUPERVISOR - MAR 2022 - OCT 2025 -
-

- Founded and led a VFX studio specializing in high-end commercial and music video work for - Post Malone, ENHYPEN, and Nike. Architected a custom pipeline combining cloud and - self-hosted infrastructure. -

-
    -
  • - - Designed 7-plate reconciliation workflows for ENHYPEN (projection mapping live action - onto CAD). -
  • -
  • - - Developed QA systems for AI-generated assets, transforming mid-tier output into - production-ready deliverables. -
  • -
-
- - -
-
-
-

Stinkfilms

- GLOBAL - PRODUCTION STUDIO - SUMMER 2024 -
-

- Led Biohazard VFX team (60+ artists) alongside director Felix Brady to create a brand film - for G-Star Raw. -

-
-

- Project: G-Star Raw Olympics Campaign - -

-

Managed full CG environments in Blender/Houdini and - integrated AI/ML workflows (Stable Diffusion reference gen, Copycat cleanup).

- View Case - Study -
-
- - -
-
-
-

Freelance

- 2D/3D - ARTIST - 2015 - PRESENT -
-

- Compositor for Abyss Digital and major labels (Atlantic, Interscope). Clients: David - Kushner, Opium, Lil Durk, Don Toliver. -

-
-
-
-
- - -
-
-
- - -
-
- /// HIGHLIGHT -

G-Star Raw Olympics

-
- - -
- -
-
-
-
- - -
-
- -
-
-
- VFX - Supervision - AI/ML - Houdini -
-

- Managed full CG environment builds, procedural city generation, and integrated AI-generated - normal maps for relighting in Nuke. -

- - Watch Making Of - -
- - -
-
-
- - -
-
-
-

Technical Arsenal

-

/// SOFTWARE & LANGUAGES

-
- - -
-

- Compositing -

-
- Nuke/NukeX - ComfyUI - After Effects - Photoshop - Deep Compositing - Live Action VFX -
-
- - -
-

- 3D Generalist -

-
- Houdini - Blender - Maya - USD - Solaris/Karma - Unreal Engine - Substance - Procedural Gen -
-
- - -
-

- AI/ML Integration -

-
- Stable - Diffusion - LoRA Training - Dataset Prep - Synthetic Data - Prompt Engineering -
-
- - -
-

- Development -

-
- Python - JavaScript - React - Docker - Linux - Pipeline Dev -
-
-
-
- - - - -
- - - - - - - diff --git a/dev/optimization-guidelines.md b/dev/optimization-guidelines.md deleted file mode 100644 index 63f7667..0000000 --- a/dev/optimization-guidelines.md +++ /dev/null @@ -1,243 +0,0 @@ -# High-Performance Web Code Guidelines -## Lessons from a 100-Year-Old Company with One of the Fastest Websites on the Internet - -This guide distills practical engineering principles observed from a deep inspection of McMaster-Carr’s website - a site that looks old, feels instant, and consistently outperforms modern, framework-heavy builds. None of these techniques are new. All of them are deliberate. - -The takeaway is simple: **perceived speed is a product of ruthless prioritization, not trendy technology**. - ---- - -## Core Philosophy - -- HTML is the product. Everything else is optional. -- Load what is needed, when it is needed, and never sooner. -- Prevent layout shifts at all costs. -- Measure everything. Assume nothing. -- Optimize for real users on real devices, not benchmarks. - ---- - -## 1. Server-Rendered HTML as the Primary Artifact - -### Guideline -Always server-render full HTML responses. - -### Why -Browsers are extremely good at parsing and rendering HTML. Shipping complete markup eliminates client-side bootstrapping delays and avoids blocking the initial render. - -### Practices -- Avoid client-side frameworks for initial rendering. -- Return fully formed HTML from the server. -- Treat JavaScript as an enhancement layer, not a prerequisite. - ---- - -## 2. Aggressive HTML Prefetching on User Intent - -### Guideline -Prefetch HTML on hover or early interaction signals. - -### Why -By the time the user clicks, the page is already downloaded. - -### Practices -- Trigger HTML requests on `mouseover` or focus. -- Cache prefetched responses for immediate swap-in. -- Replace only the page-specific content shell, not global UI. - -### Result -- Page content renders before the URL bar updates. -- Navigation feels instantaneous. - ---- - -## 3. Partial Page Swaps with History API - -### Guideline -Update only what changes between pages. - -### Why -Navigation, carts, headers, and persistent UI should not be reloaded. - -### Practices -- Use `pushState` to manage navigation. -- Replace only the dynamic content region. -- Preserve application state across page transitions. - ---- - -## 4. Multi-Layer Caching Strategy - -### Guideline -Cache HTML everywhere. - -### Layers -- CDN edge caching for pre-rendered HTML. -- Proxy caches (e.g. Squid). -- Browser cache via service workers. - -### Practices -- Inspect response headers to confirm cache hits. -- Use `HIT/MISS` headers to validate effectiveness. -- Serve cached HTML instantly when possible. - ---- - -## 5. Service Workers for HTML, Not Just Assets - -### Guideline -Intercept and serve cached HTML using service workers. - -### Why -HTML caching enables near-zero-latency reloads and offline support. - -### Practices -- Cache primary routes via service worker. -- Serve cached HTML on repeat visits. -- Use this approach to power mobile and iOS applications. - ---- - -## 6. Strategic Resource Preloading - -### Guideline -Tell the browser what it will need before it discovers it. - -### Practices -- Use `` for: - - Logos - - Web fonts - - Critical images -- Use `` for: - - Image domains - - Asset CDNs - -### Why -This collapses waterfall request chains and removes DNS lookup latency during render. - ---- - -## 7. Critical CSS Inlined in HTML - -### Guideline -Inline all above-the-fold CSS directly in the document ``. - -### Why -External CSS blocks rendering and causes layout jank. - -### Practices -- Embed essential layout and typography CSS inline. -- Load non-critical CSS asynchronously after initial render. -- Ensure the browser has all layout rules before parsing body HTML. - -### Result -- No flashes -- No reflows -- No layout instability - ---- - -## 8. Zero Layout Shift Image Strategy - -### Guideline -Always reserve image space before images load. - -### Practices -- Explicitly define width and height for all images. -- Use fixed-size containers for background images. -- Never allow images to resize content after load. - -### Result -- No cumulative layout shift -- Stable rendering pipeline - ---- - -## 9. Sprite-Based Image Bundling - -### Guideline -Minimize image requests by bundling assets into sprites. - -### Why -One request beats many, especially on constrained devices. - -### Practices -- Combine page images into a single sprite. -- Use CSS background positioning to display regions. -- Prefer fewer medium-sized assets over many small ones. - ---- - -## 10. Page-Specific JavaScript Loading - -### Guideline -Only load JavaScript that is required for the current page. - -### Why -Unused JavaScript still blocks parsing, execution, and memory. - -### Practices -- Generate page-level dependency manifests server-side. -- Include only required scripts per route. -- Avoid global JavaScript bundles. - -### Concept -Dependency injection at the page level, not the application level. - ---- - -## 11. JavaScript Is Secondary, Not Sacred - -### Observations -- Legacy libraries like YUI and jQuery are still in use. -- Total JavaScript payload can be large and still feel fast. - -### Why It Works -- JavaScript does not block HTML rendering. -- Execution is deferred until after meaningful paint. -- Performance is measured and monitored constantly. - -### Guideline -Framework choice does not determine performance discipline does. - ---- - -## 12. Instrument Everything - -### Guideline -Measure real user performance continuously. - -### Practices -- Use `window.performance` -- Add custom performance marks. -- Track Largest Contentful Paint and render milestones. - -### Why -You cannot optimize what you do not measure. - ---- - -## 13. Optimize for Real Users, Not Ideal Conditions - -### User Reality -- Old phones -- Dirty screens -- Fat fingers -- Poor connectivity -- Zero patience - -### Design Implication -- Speed is usability. -- Complexity is abandonment. -- Friction leads to phone calls and paper workflows. - ---- - -## Final Takeaways - -- Fast websites are engineered, not themed. -- Old technology can outperform modern stacks when used intentionally. -- HTML-first, cache-everywhere, and measure-constantly beats any framework war. -- Perceived performance matters more than architectural purity. - -This approach is compatible with modern server-rendered frameworks and decades-old stacks alike. The difference is not tooling. The difference is discipline. \ No newline at end of file diff --git a/dev/plan.md b/dev/plan.md deleted file mode 100644 index 4f365cd..0000000 --- a/dev/plan.md +++ /dev/null @@ -1,125 +0,0 @@ -# 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`