An immersive portfolio website built with Next.js, React Three Fiber, and Three.js that uses scroll position to drive 3D camera animations and tell a visual story.
- 🎨 Scroll-driven 3D Animation: Camera smoothly moves along a predefined path as you scroll
- 🌐 Modern Web Stack: Built with Next.js 15, TypeScript, and React Three Fiber
- 📱 Responsive Design: Optimized for both desktop and mobile devices
- ♿ Accessibility: Respects
prefers-reduced-motionand provides fallback experience - 🎭 GLB/GLTF Support: Load your own 3D models with automatic fallback
- ⚡ Performance Optimized: Adaptive rendering, mobile-specific optimizations, and shadow baking
- 🎪 Beautiful UI: HTML overlay sections with glassmorphic design
- Node.js 18+ and npm
- A 3D model in GLB/GLTF format (optional - includes fallback)
- Clone or navigate to the project directory:
cd port- Install dependencies:
npm install-
Add your 3D model (optional):
- Place your
.glbfile atpublic/models/hero.glb - See
public/models/README.mdfor model specifications and optimization tips - If no model is provided, a beautiful animated fallback will be displayed
- Place your
-
Run the development server:
npm run dev- Open http://localhost:3000 in your browser
port/
├── app/
│ ├── page.tsx # Main page with Canvas and scroll sections
│ ├── layout.tsx # Root layout with metadata
│ └── globals.css # Global styles and section styling
├── components/
│ └── canvas/
│ ├── Scene.tsx # Main 3D scene with lighting and camera control
│ ├── Model.tsx # GLB model loader with existence check
│ ├── FallbackModel.tsx # Fallback 3D object when no model exists
│ └── ReducedMotionFallback.tsx # Static fallback for reduced motion
├── lib/
│ └── cameraPath.ts # Camera path curve and target definitions
└── public/
└── models/
└── README.md # Model specifications and optimization guide
Edit lib/cameraPath.ts to change the camera movement:
export const cameraCurve = new THREE.CatmullRomCurve3([
new THREE.Vector3(x1, y1, z1), // Start position
new THREE.Vector3(x2, y2, z2), // Middle waypoints...
new THREE.Vector3(x3, y3, z3),
new THREE.Vector3(x4, y4, z4), // End position
])
export const lookAtTarget = new THREE.Vector3(0, 1.1, 0) // Where camera looksModify sections in app/page.tsx:
<section className="section s1">
<h1>Your Title</h1>
<p>Your description</p>
</section>Adjust the number of pages in ScrollControls to match your sections:
<ScrollControls pages={4} damping={0.18}>Edit components/canvas/Scene.tsx to adjust:
- Light positions and intensities
- Shadow quality
- Environment preset (options:
"sunset","dawn","night","warehouse","forest","apartment","studio","city","park","lobby")
Update app/globals.css for:
- Section layouts (
.s1,.s2,.s3,.s4) - Typography and spacing
- Colors and effects
- Compress your GLB:
npx gltf-transform optimize input.glb output.glb --compress draco- Reduce polycount in Blender or your 3D software
- Use texture compression (JPEG for color, optimized PNGs)
- Consider lazy loading for multiple models
The app automatically:
- Uses baked shadows on mobile (faster)
- Reduces animation intensity
- Adapts pixel ratio (
dpr={[1, 2]}) - Lowers shadow map resolution
npm run build
npm start- Push your code to GitHub
- Import the project in Vercel
- Deploy with one click
Or use the Vercel CLI:
npm i -g vercel
vercelThe app works on any Node.js hosting platform that supports Next.js:
- Netlify
- Railway
- Render
- DigitalOcean App Platform
- Next.js 15 - React framework
- React Three Fiber - React renderer for Three.js
- Drei - Useful helpers for R3F
- Three.js - 3D library
- TypeScript - Type safety
- Tailwind CSS - Utility-first CSS
- React Three Fiber Documentation
- Drei Helpers Documentation
- Three.js Examples
- glTF Viewer - Test your models
- Poly Haven - Free 3D assets and HDRIs
This project is open source and available under the MIT License.
- Add more scroll sections with different camera angles
- Implement click interactions on 3D objects
- Add postprocessing effects (bloom, vignette, etc.)
- Create project detail pages with individual scenes
- Add sound design triggered by scroll position
- Implement particle systems or shaders for more visual flair
Built with ❤️ using React Three Fiber