Integrating Three.js with Next.js and TypeScript

Claude Ando
3 min readApr 10, 2023

--

Three.js is a powerful JavaScript library for creating 3D graphics in the browser using WebGL. Next.js is a popular framework for building server-rendered React applications that focus on performance, scalability, and developer experience. Combining the power of Three.js with the versatility of Next.js can result in highly dynamic and interactive web applications with server-side rendering capabilities.

In this article, we will explore how to use the native Three.js library with Next.js and TypeScript, walking you through the process of setting up a basic project and rendering a 3D scene with examples.

Table of Contents:

  1. Setting Up the Next.js and TypeScript Project
  2. Creating a Basic React Functional Component in TypeScript
  3. Integrating Three.js with Next.js and TypeScript
  4. Rendering a 3D Cube with Three.js and Next.js
  5. Adding Interactivity and Animation
  6. Conclusion
  7. Setting Up the Next.js and TypeScript Project:
npx create-next-app next-threejs-typescript-example --ts
cd next-threejs-typescript-example

Next, install the Three.js library:

npm install three

2. Creating a Basic React Functional Component in TypeScript:

In your Next.js project, create a new file named ThreeScene.tsx inside the components folder and set up a basic functional component:

import React, { useRef, useEffect } from 'react';

const ThreeScene: React.FC = () => {
const containerRef = useRef<HTMLDivElement>(null);

useEffect(() => {
if (typeof window !== 'undefined') {
// Initialize Three.js scene here
}
}, []);

return <div ref={containerRef} />;
};

export default ThreeScene;

3. Integrating Three.js with Next.js and TypeScript:

In the ThreeScene component, use the useEffect hook to initialize the Three.js scene, renderer, and camera:

import React, { useRef, useEffect } from 'react';
import * as THREE from 'three';

const ThreeScene: React.FC = () => {
const containerRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (typeof window !== 'undefined') {
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
containerRef.current?.appendChild(renderer.domElement);
camera.position.z = 5;
}
}, []);
return <div ref={containerRef} />;
};
export default ThreeScene;

4. Rendering a 3D Cube with Three.js and Next.js:

Now, let’s add a simple 3D cube to the scene:

// Add this inside the useEffect hook after initializing the renderer
if (typeof window !== 'undefined') {
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

// Render the scene and camera
renderer.render(scene, camera);
}

5. Adding Interactivity and Animation:

To animate the cube, create a renderScene function that updates the cube's rotation and re-renders the scene:

// Add this function inside the useEffect hook
const renderScene = () => {
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
requestAnimationFrame(renderScene);
};

// Call the renderScene function to start the animation loop
renderScene();

To handle window resizing, add an event listener to update the camera aspect ratio and renderer size:

useEffect(() => {
if (typeof window !== 'undefined') {
// Initialize the Three.js scene here (as in the previous example)

const handleResize = () => {
const width = window.innerWidth;
const height = window.innerHeight;

camera.aspect = width / height;
camera.updateProjectionMatrix();

renderer.setSize(width, height);
};

window.addEventListener('resize', handleResize);

// Clean up the event listener when the component is unmounted
return () => {
window.removeEventListener('resize', handleResize);
};
}
}, []);

By wrapping the code that depends on the window object with a check to ensure it's running on the client side, we can prevent errors related to server-side rendering and successfully integrate Three.js with Next.js in a TypeScript project.

In this article, we demonstrated how to use the native Three.js library with Next.js and TypeScript to create a 3D scene in a server-rendered React application. By following the steps outlined above, you can now harness the power of Three.js and WebGL to create interactive, dynamic web applications with the performance benefits of server-side rendering provided by Next.js.

--

--

Claude Ando

Entrepreneur - 6 figure agency business / investment / live in hotels somewhere in 🌏