539b251287e5f2585ee5b8307da1968a45ebd45c
* feat: random light pulse along threads + box outlines A blurred light pulse glides along one of the 5 wave threads (wave1/2/3, thread1/2) every 2.5-7s. Color matches the active theme (cyan on home/portfolio/about, pink/magenta on contact). Pulse also follows the outline of designated boxes marked with data-trail-box: - Home: 'Looking for inspiration?' + 'Ready to collaborate?' - Contact: 'Waiting to hear from you' card Boxes are rebuilt on every pulse so they stay aligned during scroll and respect viewport (off-screen boxes are skipped). Pulse uses requestAnimationFrame + path.getPointAtLength for native smoothness, fade-in 15% / hold 70% / fade-out 15%, screen blend mode so it blends with the dark background. * feat(pulse): slower, brighter, comet-shaped pulse along paths Slower (9-13s per glide vs 4.5-6.5s), three-layer comet shape (soft halo + mid glow + bright core), rotated to path tangent, ease-in-out timing, mix-blend-mode screen. Fixes: pulse not tracking path was a parallax-offset coordinate mismatch. Cleaned up via getSpeedKey() helper. * fix(pulse): tone down white core so theme color dominates Core was pure white (#ffffff) which washed out the theme color. Now tinted (#fdf4ff for purple, #f0fdfa for cyan) and smaller (10x3 vs 14x4) with 75% opacity so the purple/pink and cyan glow layers come through more visibly. * feat(pulse): double the glide duration Threads: 18-26s (was 9-13s). Boxes: 14-18s (was 7-9s). * feat(pulse): split into two halves around boxes When a thread-pulse hits a data-trail-box bound, it splits: one half glides along the top of the box outline, the other along the bottom. They re-merge on the far side and continue as one along the rest of the thread. Implementation: - Two pulse-blob groups (blob-1, blob-2) in SVG - Box-intersection scan samples path every 4px to find entry + exit points - Phase 1: blob-1 glides from start to entry - Phase 2: blob-1 follows top-half of box outline, blob-2 follows bottom-half (both spawned dynamically) - Phase 3: blob-1 continues from exit to end, blob-2 hides - Velocity kept constant across phases so split makes the animation longer rather than faster
Images by Olofsson
A modern, responsive photography portfolio website built with Astro, Tailwind CSS, and advanced animations.
Features
Modern design with minimalist aesthetics and focus on imagery. Advanced animations including wave effects, 3D scroll transforms, and smoke particles. Fully responsive across all devices with optimized performance.
Quick Start
Prerequisites
Node.js 18.0 or higher
Installation
git clone https://github.com/Images-by-Olofsson/homepage.git
cd homepage
npm install
Development
npm run dev
Build
npm run build
npm run preview
Project Structure
src/
├── assets/
├── components/
│ ├── WaveBackground.astro
│ ├── ThreeDScroll.astro
│ ├── FloatingOrbs.astro
│ └── Welcome.astro
├── layouts/
│ ├── MainLayout.astro
│ └── Layout.astro
├── pages/
│ ├── index.astro
│ ├── portfolio.astro
│ ├── about.astro
│ └── contact.astro
└── styles/
└── global.css
Technologies
Astro, Tailwind CSS, TypeScript, Exifr
License
MIT License - see LICENSE file for details
Built by Linus Olofsson
Languages
Astro
65.4%
TypeScript
24.4%
JavaScript
4.4%
Shell
3.1%
Vim Snippet
2.2%
Other
0.4%


