Build a Scrolling 3D Room Tour

Build a 3D room tour where scrolling guides visitors between rooms.

Introduction

30 Second Summary

Scrolling usually moves words or images up the screen. Some websites make the same gesture feel like walking through a place.

In this project, you will transform an open source three.js scene into a scrolling 3D room tour. Your page will guide visitors between rooms through camera movement that follows their scroll.

What You'll Build

When you finish, your live page turns each phone swipe into a smooth camera journey from one named room to the next.

By the end of this project, you'll have:

  • A deployed scroll-controlled tour that carries visitors between named rooms on a laptop or phone.
  • A custom 3D scene with your own sky or texture plus an animated atmospheric layer.
  • A faster first paint after capping the device pixel ratio and compressing the largest texture.
  • Secret Mission: An optional challenge to push your skills further.

Are there any prerequisites?

You'll need Node.js with npm. You'll also need a browser that supports WebGL plus access to a static host.

Before We Start

Your 3D room tour begins as code in an online repository. This step prepares the laptop that will render it.

Git retrieves the project files. Node.js uses npm to install the code that runs the scene.

Visual Studio Code gives you a place to edit the project. Google Chrome exposes Chrome DevTools for visual checks.

A signed-in GitHub account gives you a publishing path through GitHub Pages.

In this step, get ready to:
  • Prepare a code editor plus a browser with DevTools.
  • Verify that Git plus Node.js are available.
  • Sign in to a GitHub account that can publish a public site.
Prepare your editor and browser

The editor is where you will change the scene files. The browser turns those files into the room tour you can see.

Your setup path depends on whether Visual Studio Code plus Google Chrome are already installed.

✔️ Both apps are installed

Your two visual tools are ready. Continue below to open them plus test DevTools.

ⓧ I need one or both apps

Install only the apps missing from your computer. Choose the tab for your operating system.

macOS

  • Download Visual Studio Code from the official download page.
  • Open the downloaded .dmg file.
  • Drag Visual Studio Code.app into the Applications folder.
  • Download Google Chrome from the official installation page.
  • Open googlechrome.dmg.
  • Drag Chrome into the Applications folder.

Windows

  • Download the User Installer from the official Visual Studio Code page.
  • Run the downloaded Visual Studio Code installer.
  • Complete the installer prompts.
  • Download Google Chrome from the official installation page.
  • Run the downloaded Chrome installer.
  • Approve the installation prompt if Windows displays one.
  • Press Cmd+Space on macOS or the Windows key on Windows to open system search.
  • Type Visual Studio Code plus press Enter to open the editor.
  • Return to system search with the same keyboard shortcut.
  • Type Google Chrome plus press Enter to open the browser.

Before you test the browser, do you expect its developer tools to open inside the current window?

  • In Chrome, press Cmd+Option+I on macOS or Ctrl+Shift+I on Windows.

You should see Chrome DevTools docked beside the browser page. This is where you will inspect loading speed plus frame performance later.

DevTools did not open?

Click inside the browser page before trying the shortcut again. Some keyboards also require the function key when using function-key alternatives.

You can also right-click the page. Select Inspect to open the Elements panel.

Help me open Chrome DevTools on my computer.

Verify Git, Node.js and npm

The command line gives you direct access to the tools that retrieve plus run the project. Each version check confirms that your computer can find the corresponding command.

  • Press Cmd+Space on macOS or the Windows key on Windows to open system search.
  • Type Terminal on macOS or PowerShell on Windows. Press Enter.
  • Check whether Git is installed by running this command:
git --version

What should this check show?

The command asks Git to identify its installed version. A working installation returns a line beginning with git version.

✔️ I see a Git version

Git is responding from your terminal. You can use it to retrieve the room tour repository in the next step.

ⓧ Git is not installed

  • Open the official Git installation page.
  • Select your operating system.
  • Download the recommended installer.
  • Complete the installer prompts.
  • Close your current terminal window.
  • Open a fresh terminal through system search.
  • Repeat the Git version check above.

You should now see a line beginning with git version.

  • Check whether Node.js plus npm are installed by running:
node -v
npm -v

What do these checks prove?

  • The node -v command confirms that the Node.js runtime is available.
  • The npm -v command confirms that the package manager is available.

✔️ I see both version numbers

That is the runtime ready. Node.js can now run the project while npm installs its dependencies.

ⓧ One or both commands are missing

Installing the Node.js version labelled LTS also installs npm. The installer may request permission to make changes to your computer.

  • Open the official Node.js download page.
  • Choose the release labelled LTS.
  • Download the installer for your operating system.
  • Run the downloaded installer.
  • Complete the installer prompts.
  • Close your current terminal window.
  • Open a fresh terminal through system search.
  • Repeat both version checks above.

You should now see one version number from Node.js plus another from npm.

Still missing a command?

A terminal opened before installation may keep its old command path. Close every terminal window before opening a fresh one.

If only npm is missing, reinstall the LTS release from the official Node.js download page. The standard installation includes both tools.

Help me diagnose my missing Git, Node.js, or npm command.

Sign in to GitHub and confirm the toolkit

GitHub stores the repository that you will clone. A verified personal account can also publish the finished tour from a public repository with GitHub Pages.

Your next path depends on whether you already have a personal GitHub account.

✔️ I already have an account

Your credentials stay inside GitHub's sign-in flow. This project never asks you to paste them into code.

  • Open the GitHub sign-in page in Chrome.
  • Enter your username or email address.
  • Enter your password.
  • Complete your additional authentication step if GitHub requests one.

You should see your profile image in the upper-right corner. This confirms that GitHub recognizes your signed-in session.

ⓧ I need an account

Account creation involves your email plus a private password. Keep those credentials inside GitHub's sign-up page.

  • Open the GitHub sign-up page in Chrome.
  • Follow the prompts to create a free personal account.
  • Open the verification message sent to your email address.
  • Complete the email verification from that message.
  • Return to GitHub in Chrome.
  • Sign in to your new account.

You should see your profile image in the upper-right corner. Your verified personal account can now create the public repository used for deployment.

Why use GitHub Pages?

GitHub Pages publishes static website files directly from a GitHub repository. GitHub Free supports Pages for public repositories.

That makes it a suitable destination for the browser-based room tour you will deploy later.

Before you run the final check, do you expect all three command-line tools to return version information?

  • Confirm the complete command-line toolkit in one pass by running:
git --version
node -v
npm -v

What does the final check confirm?

  • The first line confirms that Git can retrieve the repository.
  • The second line confirms that Node.js can run the project.
  • The third line confirms that npm can install the project dependencies.

You should see three version results with no missing-command messages. That output confirms the command-line side of your setup.

  • Switch back to Chrome.
  • Return to the signed-in GitHub page.
  • Press Cmd+Option+I on macOS or Ctrl+Shift+I on Windows.

You should see your signed-in GitHub page with Chrome DevTools visible beside it. This proves that your browser plus publishing account are ready.

Your local toolkit plus publishing account are ready. Next, you will clone the seijaku repository plus render its first room on your laptop.

Run the Starter Room Locally

Your room tour needs a working baseline before you change its assets. The starter three.js scene gives you a known-good first room to compare against later.

This step creates a local copy of the seijaku repository. An npm-powered development server then makes the scene available to your browser.

In this step, get ready to:
  • Clone the seijaku repository to your Desktop.
  • Install the npm-backed local server dependency.
  • Run the starter scene until its first room renders.
Clone the seijaku repository

Cloning uses Git to copy the complete GitHub repository onto your computer. Keeping the copy on your Desktop makes the project easy to find throughout the tour.

macOS

  • Press Cmd+Space to open Spotlight.
  • Type Terminal into Spotlight.
  • Press Enter to open Terminal.
  • Create the local seijaku copy on your Desktop by running these commands:
cd ~/Desktop
git clone https://github.com/MengTo/seijaku.git
cd seijaku
ls

What do these commands do?

  • The first command moves your terminal to the Desktop.
  • The second command downloads the starter repository into a new seijaku folder.
  • The third command moves your terminal inside that folder.
  • The final command lists the downloaded project files so you can verify the clone.

Windows

  • Press the Windows key to open Search.
  • Type PowerShell into Search.
  • Press Enter to open PowerShell.
  • Create the local seijaku copy on your Desktop by running these commands:
cd ~/Desktop
git clone https://github.com/MengTo/seijaku.git
cd seijaku
ls

What do these commands do?

  • The first command moves PowerShell to the Desktop.
  • The second command downloads the starter repository into a new seijaku folder.
  • The third command moves PowerShell inside that folder.
  • The final command lists the downloaded project files so you can verify the clone.

You should see project items such as index.html, a, and photos in the file list. You now have the complete starter scene on your computer.

Repository did not download?

Confirm that your internet connection is active. Remove any incomplete seijaku folder before running the clone commands again.

Make sure the terminal is on your Desktop before cloning. This prevents the repository from landing in an unexpected folder.

Help me troubleshoot the seijaku repository clone.

Start the local development server

The browser loads the scene through ES modules and linked assets. The serve package provides the local HTTP server that delivers those files correctly.

The first run may ask npm for permission to download serve. This request installs the supporting server dependency before the process starts.

  • Allow npm to download serve if it asks for confirmation.
  • Start the local development server by running this command:
npx serve

What does this command do?

  • The npx command asks npm to fetch the server package when needed.
  • The serve command publishes the current seijaku folder through a local address.
  • The process keeps the terminal occupied while your local site is available.

Your terminal should display a local address while the server keeps running. You now have a live route from the browser to the starter project.

  • Record the local address shown in your terminal here: your local server URL.

Local address not showing?

Confirm that your terminal is still inside the seijaku folder. The server needs to start from the folder containing index.html.

If npm cannot download the server package, check your internet connection before trying the command again.

Help me start the local seijaku server.

Confirm the first room renders

Your browser uses WebGL to turn the starter scene data into an interactive 3D view. A rendered room proves that the server can deliver the project files and the browser can draw the scene.

Before you check, consider whether the first room will appear immediately or build in as its assets load.

  • Copy your local server URL from your saved value.
  • Switch to your modern browser.
  • Click the browser's Address bar.
  • Paste your local server URL into the address bar.
  • Press Enter to load the starter scene.

You'll see the unmodified starter three.js scene fill the browser with its first room. That's the baseline working: your local room tour is rendering from the cloned repository.

Seeing a blank scene?

Keep the terminal process running while the browser is open. Closing the terminal stops the local server.

Confirm that your browser supports WebGL. Check your internet connection because the starter scene loads some runtime libraries online.

Help me diagnose the blank three.js scene.

Your starter room now runs from your own local copy. Next, you will replace the scene's sky and one texture with your own files.

Personalize the Scene Assets

Your starter three.js room tour is already running locally. You now have a stable scene for your own visual direction.

The original sky still carries the starter project's atmosphere. The painted room surface also carries the starter artwork. This step replaces both visuals with your files.

In this step, get ready to:
  • Store two custom image assets in the project.
  • Point the scene registry at your replacement files.
  • Reload the tour to confirm both visual changes.
Add your custom assets

A texture is an image that supplies color or artwork to a 3D surface. The browser loads each texture from a path stored in the project.

  • Return to the code editor from earlier.
  • Expand the a/ folder in the file tree.
  • Use Finder (macOS) or File Explorer (Windows) to locate your custom sky image.
  • Drag your custom sky image into the a/ folder.

You should see the custom sky file listed beside the starter assets in a/.

  • Record the complete sky filename here: your custom sky filename.
  • Use Finder (macOS) or File Explorer (Windows) to locate your custom room texture.
  • Drag your custom room texture into the a/ folder.

You should now see both replacement files inside a/.

  • Record the complete room texture filename here: your custom room texture filename.

Make Each Change Obvious

A sky with a noticeably different color palette makes the first check easier. A room texture with a clear pattern makes the surface swap easy to spot.

Update the scene asset references

The asset registry in index.html maps each visual role to an image path. Updating a registry value makes three.js load your file during the next page load.

  • Press Cmd+F (macOS) or Ctrl+F (Windows) in index.html to open the Find control.
  • Search for a/assets-sky.8512d95535.webp.
  • Replace the matching path with a/ followed by your custom sky filename.
  • Save index.html.
  • Return to the browser tab from earlier.
  • Reload the page from the browser toolbar.

You should see your custom sky surrounding the rendered scene. This confirms the first replacement path resolves correctly.

Still Seeing the Starter Sky?

  • Check that the new path begins with a/.
  • Match every capital letter in the filename to the file shown in the project tree.
  • Reload the page again after saving index.html.

Ask for help with the asset path if the sky still stays unchanged: Help me find why my custom sky image is not loading from the a folder in this three.js project.

The painted bedroom screen uses a separate entry in the same registry. Swapping that entry applies your second image to a visible interior surface.

  • Press Cmd+F (macOS) or Ctrl+F (Windows) in index.html to return to the Find control.
  • Search for a/a75777defa9d3db19efc.webp.
  • Replace the matching path with a/ followed by your custom room texture filename.
  • Save index.html.
  • Reload the page from the browser toolbar.
  • Scroll through the tour until the bedroom fills the scene.

You should see your custom image across the painted bedroom surface. The room now carries your chosen visual style.

Room Texture Missing?

  • Confirm that the replacement file appears inside a/.
  • Check that the replacement path contains the complete filename extension.
  • Search for wall_fusuma to confirm you edited the bedroom surface entry.

Ask for help if the painted screen remains unchanged: Help me troubleshoot why my custom wall_fusuma texture is not appearing in the seijaku bedroom.

Verify the personalized scene

Both registry entries now point to your replacement assets. A fresh page load checks the complete path from the browser to each local file.

Before you reload, which two parts of the tour do you expect to look different?

  • Reload the page from the browser toolbar.

You should see your custom sky in the opening view.

  • Scroll through the tour until the bedroom fills the scene.

You should see your custom texture on the painted room surface. That completes the visual swap. Your local tour now carries your own atmosphere. It also carries your chosen room finish.

Your personalized assets are now part of the rendered scene. Next, you will connect scroll progress to the camera path between the rooms.

Connect Scroll to the Camera Path

Your custom sky now gives the scene its own atmosphere. Your custom room texture gives the interior its own identity.

The tour now needs a navigation rule that turns page movement into a predictable journey. Normalized scroll progress lets the Three.js camera follow the same route across different screen heights.

In this step, get ready to:
  • Name two checkpoints on the existing camera route.
  • Trace the normalized scroll mapping into the camera path.
  • Verify the complete journey from Room One to Room Two.
Name the two room checkpoints

The starter route stores its camera poses in KEYS. The CHAPTERS table gives each section of that route a readable label.

  • In your code editor, open index.html from the local seijaku repository.
  • Press Cmd+F (macOS) or Ctrl+F (Windows) to open the search panel.
  • Search for const CHAPTERS.
  • Change the label value The Genkan to Room One.
  • Save index.html.
  • Switch back to the browser preview from earlier.
  • Scroll until the chapter title changes.

You should see ROOM ONE while the camera moves through the first named checkpoint.

  • Switch back to index.html in your code editor.
  • Change the label value The Corridor to Room Two.
  • Save index.html.
  • Return to the browser preview.
  • Scroll beyond the first checkpoint.

You should see ROOM TWO as the next camera position takes over. Your route now has two named destinations.

Trace the normalized scroll mapping

The page converts its scroll distance into a value between 0 and 1. That value becomes a position on the camera path.

  • Switch back to index.html in your code editor.
  • Search for const maxScroll.
  • Confirm that maxScroll() calculates the available page distance.
  • Search for addEventListener('scroll'.
  • Confirm that tTarget uses scrollY divided by maxScroll().

The resulting ratio stays between 0 and 1. Multiplying it by T converts page progress into the route timeline.

  • Search for function interp.
  • Confirm that interp() samples neighbouring entries from KEYS.
  • Search for film.sample.
  • Confirm that the render loop copies the sampled pose into the camera.

Why normalized progress?

Raw pixel offsets tie camera timing to one page height. A shorter viewport changes when each room is reached.

Normalized progress measures the visitor's share of the full journey. Room One remains the start checkpoint. Room Two remains the next checkpoint.

Verify the complete camera journey

The labels now identify the route. The final check proves that scroll progress drives the camera through both positions.

Before you scroll, do you expect the camera to reach both room checkpoints in one continuous movement?

  • Drag the browser scrollbar to the top of the page.
  • Scroll slowly until ROOM ONE is shown.
  • Continue scrolling until ROOM TWO is shown.
  • Keep scrolling until the camera has passed Room Two.

You should see the camera travel continuously through Room One. You should then see it arrive at Room Two without a sudden jump.

  • Resize the browser window to a noticeably shorter height.
  • Repeat the complete scroll journey.

The camera should reach the same named checkpoints after the resize. This confirms that page progress controls the route consistently.

Camera stays still?

Check that the KEYS entries remain inside their original array. A missing comma or bracket can stop the scene script.

Make sure the development server from earlier is still running. Reload the browser after saving index.html.

Help me diagnose why scrolling does not move the camera in my local seijaku project.

You made the page itself steer the tour. Next, you will add sky rays or falling leaves while protecting the frame rate.

Add Atmospheric Motion

Your camera journey now carries visitors from Room One to Room Two. The scene can still feel frozen whenever the visitor pauses their scroll.

Atmospheric motion gives your three.js scene its own pulse while scrolling remains in control. In this step, you will add animated sky rays before checking their effect on frame rate.

In this step, get ready to:
  • Record a frame-rate baseline for the existing camera journey.
  • Add animated sky rays to the existing scene.
  • Compare the updated tour with your baseline.
Record a smoothness baseline

Continuous visual effects consume rendering time on every frame. A baseline shows whether the new layer changes the experience.

  • Return to the local room tour from earlier.
  • Open your browser's DevTools.
  • Start a recording in the performance profiler.
  • Scroll from Room One to Room Two at a steady pace.
  • Stop the recording after Room Two fills the viewport.
  • Keep the recording available as your baseline.

You should see a frame-rate graph covering the complete camera journey. Its steadier sections become your comparison point.

Add animated sky rays

Sky rays are a post-processing effect that samples bright sky toward the projected sun position. Scene silhouettes shape the result into visible shafts.

What should the ray pass include?

  • The pass uses the renderer already powering your room tour.
  • The pass uses the camera already following your scroll path.
  • An open-sky mask lets room geometry interrupt the light.
  • The projected sun position controls where each shaft begins.
  • The existing animation time keeps the effect moving.
  • The ray result is composited before the final tone mapping.
  • Switch back to the code file from earlier that contains the scene plus render loop.
  • Open the official 3D Sky Rays guide in your browser.
  • Implement the guide's occlusion-aware sky-ray pass inside the existing post-processing chain.
  • Save the scene file.
  • Return to the local room tour from earlier.
  • Reload the page.

You should see warm shafts moving through the sky. Roof edges plus room silhouettes should interrupt the light.

Don't see the sky rays?

Confirm that the ray pass sits inside the active post-processing chain. Check that open sky remains distinguishable from opaque geometry.

Confirm that the existing animation time reaches the ray effect. A fixed time value produces a static result.

Help me debug sky rays that are missing or static in my three.js room tour.

Compare the frame rate

A smooth atmospheric layer supports the camera journey without competing with it. The second recording reveals the cost of the new pass.

Before you profile the new version, make a quick prediction about whether the rays will stay smooth across both rooms.

  • Start a new recording in the DevTools performance profiler.
  • Scroll from Room One to Room Two at the same pace as your baseline.
  • Stop the recording after Room Two fills the viewport.
  • Compare the new frame-rate graph with your baseline.

You should see the animated rays throughout the journey. The frame-rate graph should remain close to your baseline without a noticeable drop.

Seeing a frame-rate drop?

Lower the ray sample count if the new recording shows sustained slow frames. Use a lower-resolution ray buffer if the drop remains noticeable.

Reduce the ray intensity if surfaces lose contrast. Fade the source when the sun moves off-screen if the effect flashes near the viewport edge.

Help me tune my animated sky rays for smoother rendering.

That is a strong visual win. Your sky rays now animate through both rooms without disrupting the scroll journey.

Your tour now has movement in the sky as well as movement through space. Next, you will improve its first paint time while protecting that smooth animation.

Optimize Scene Performance

Your three.js room tour now carries visitors from Room One to Room Two. Animated sky rays keep the scene moving around them.

Dense displays can make the renderer draw more pixels than the tour needs. A large sky image can also delay first paint.

In this step, you cap the device pixel ratio at 2. Browser DevTools measures the effect after you compress the custom sky image.

In this step, get ready to:
  • Capture a first-paint baseline in browser DevTools.
  • Limit dense-screen rendering to a device pixel ratio of 2.
  • Compare first-paint timing after compressing the custom sky texture.
Measure the current first paint

A baseline records the scene before optimization. Using the same loading conditions later makes the comparison meaningful.

  • Switch back to the local room tour in your browser.
  • Open your browser's developer tools.
  • Set the page-load recorder to bypass cached files.
  • Start a page-load recording.
  • Reload the local room tour.
  • Stop the recording when Room One is visible.
  • Find the first-paint timing in the completed recording.
  • Record the baseline here: first-paint time before optimization.

You have a clean baseline now. The current scene has a first-paint number to beat.

Cannot Find the First-Paint Timing?

  • Use the developer tools view that records page-loading performance.
  • Repeat the recording while reloading the whole page.
  • Wait for Room One to render before stopping the recording.

Help me locate first-paint timing in my browser's developer tools.

Tune dense-screen rendering

Device pixel ratio controls how many physical pixels the renderer draws for each displayed pixel. Dense displays can create a larger drawing buffer than the scene needs.

Why Cap the Ratio at 2?

A cap of 2 limits drawing-buffer growth on dense displays. The scene keeps high-density detail while avoiding extra rendering work above that limit.

The camera path remains unchanged. The optimization only controls the resolution used to render each frame.

  • Switch back to the code editor from earlier.
  • Use the editor's project search to locate the code that creates the renderer.
  • Edit the renderer setup so it uses the device's current pixel ratio up to a maximum of 2.
  • Save the source file that initializes the renderer.

Before you reload, do you expect the scene composition to change when the rendering resolution is capped?

  • Return to the local room tour in your browser.
  • Reload the page.

You should still see the custom sky texture. Room One should appear with the custom room surface.

  • Inspect the WebGL canvas with your browser's developer tools.
  • Compare the canvas's internal dimensions with its displayed dimensions.

Neither internal dimension should exceed twice its displayed counterpart. This confirms the renderer respects the device-pixel-ratio cap.

Scene Rendering Changed?

  • Confirm the ratio limit was added to the renderer setup.
  • Check that the maximum value is the number 2.
  • Restore the previous pixel-ratio setting if the canvas becomes blank.

Help me diagnose the device-pixel-ratio cap in my three.js renderer.

Compress the sky texture and compare

The browser downloads the sky image before it can render that part of the scene. Reducing the file size lowers the amount of asset data needed during the first load.

Compression takes a little judgement because smooth sky gradients reveal artifacts quickly. A visual preview helps you preserve the atmosphere while shrinking the file.

  • Use the editor's project search to locate the existing custom sky asset reference.
  • Follow that reference to the custom sky image in the project.
  • Compare the files in that asset folder to confirm the custom sky image is the largest texture.
  • Record its current file size here: sky texture size before compression.
  • Compress the custom sky image with an image compression tool that supports its current file format.
  • Adjust the compression until the preview still shows clean sky gradients.

The preview should preserve the sky's main colours. Large bands or blocky patches indicate excessive compression.

  • Export the compressed image into the same asset folder under a new filename.
  • Record the new asset path here: compressed sky asset path.
  • Compare the compressed file size with sky texture size before compression.

The compressed file should be smaller than the original. Its preview should still look suitable for the room tour.

  • Update the existing sky asset reference to point to compressed sky asset path.
  • Save the source file containing the sky asset reference.

Before you record the optimized load, do you expect the first room to paint sooner while the tour keeps the same movement?

  • Return to the local room tour in your browser.
  • Return to the page-load recorder in developer tools.
  • Confirm the recorder still bypasses cached files.
  • Start a new page-load recording.
  • Reload the local room tour.
  • Stop the recording when Room One is visible.
  • Find the new first-paint timing.
  • Record the optimized result here: first-paint time after optimization.

You should see the compressed custom sky in the scene. The first-paint timing should be lower than first-paint time before optimization.

  • Scroll from Room One to Room Two.
  • Watch the animated sky rays during the camera movement.

The camera should complete the same room-to-room journey. The sky rays should keep animating smoothly.

First Paint Did Not Improve?

  • Confirm the compressed sky file is smaller than the original file.
  • Check that the scene references the compressed sky asset.
  • Repeat the recording with the same cache conditions as the baseline.

Help me compare first-paint performance before and after compressing my sky texture.

That is the performance pass complete. Your room tour now loads a compressed sky texture with rendering capped at device pixel ratio 2. Next up, you will publish the optimized tour as a live site.

Deploy Your Room Tour

Your three.js room tour now carries visitors between Room One and Room Two with animated sky rays. Your texture compression plus device-pixel-ratio cap have already improved its first paint.

A local scene can only be viewed from your laptop. In this step, you will package the scene as a production build. GitHub Pages will give it a live URL you can test on a phone.

In this step, get ready to:
  • Create a static production build of your room tour.
  • Publish the production files with GitHub Pages.
  • Verify the live camera journey on a phone.
Build the production site

A production build packages your scene into static files for hosting. This is the copy that visitors download when they open your live URL.

  • Switch back to the terminal panel running your development server.
  • Press Ctrl+C to stop the development server.

Before you run the build, do you expect the custom textures plus camera path to be included in the production files?

  • Create the production build by running this command:
npm run build

What Does This Command Do?

The npm command reads the build script from package.json.

That script packages the room tour into static files that a web host can serve.

  • Find the final terminal line that names the generated output folder.
  • Record the folder name here: your build output folder.
  • In your editor's Explorer sidebar, expand your build output folder.

You should see index.html at the top level of the generated folder. The terminal should show a successful build summary.

Build Stopped Before Finishing?

  • Start with the first file path reported by the build.
  • Check that every custom texture path points to a file inside the seijaku folder.

Ask for help with the build output.

That is the deployable copy ready. Your optimized room tour now exists as static production files.

Publish the build with GitHub Pages

GitHub Pages can publish static files from a repository branch. A separate repository gives your production build a branch root where index.html can sit at the top level.

  • Return to GitHub in your browser.
  • Select the creation menu in the upper-right corner.
  • Click New repository.
  • Choose your personal account from the Owner dropdown.
  • Enter scrolling-room-tour in the Repository name field.
  • Select Public under Choose visibility.
  • Turn Add README on.
  • Click Create repository.

Your new repository opens on the main branch. It is now ready to receive the production files.

GitHub Pages looks for index.html at the top level of its publishing source. Upload the contents of the generated folder so that entry file stays at the top level.

  • Click Add file above the repository file list.
  • Click Upload files.
  • Open your build output folder in Finder on macOS or File Explorer on Windows.
  • Select every item inside your build output folder.
  • Drag the selected items into the GitHub upload area.
  • Enter Deploy production room tour in the Commit message field.
  • Click Commit changes.

The repository file list should now show index.html at the top level. Your production assets should appear beside it or inside their generated folders.

  • Click Settings under the repository name.
  • Select Pages in the sidebar.
  • Select Deploy from a branch from the Source dropdown under Build and deployment.
  • Select main from the Branch dropdown.
  • Select /(root) from the folder dropdown.
  • Click Save.

Publishing can take up to 10 minutes after the commit.

  • Click Visit site when it appears in the GitHub Pages settings.
  • Copy the address from your browser's address bar.
  • Record the address here: https://your-username.github.io/scrolling-room-tour/.

The live page should open in Room One with your custom compressed sky. Your custom room texture should appear on its edited surface.

The sky rays should animate over the deployed scene.

Live Page Missing Scene Assets?

  • Confirm that index.html appears at the top level of main.
  • In Pages settings, confirm that Deploy from a branch is selected.
  • Confirm that the publishing folder is /(root).

Help me diagnose missing assets on my deployed room tour.

Test the live tour on your phone

A phone test checks the deployed files through a separate browser. It also proves that touch scrolling can drive the camera journey on a smaller screen.

Before you load the site, do you expect the camera path plus sky rays to behave the same way on your phone?

  • Open a browser on your phone.
  • Enter https://your-username.github.io/scrolling-room-tour/ in the address bar.
  • Wait for the first room to finish loading.
  • Swipe upward until the camera reaches Room Two.
  • Swipe downward until the camera returns to Room One.

Your custom compressed sky should load. The custom room surface should stay textured.

The sky rays should keep moving. Scrolling should move the camera between Room One and Room Two without a blank frame.

The deployed renderer also carries the device-pixel-ratio cap of 2 from your optimized build.

That is the final proof: your room tour now works from a shareable URL on a phone.

Secret mission

Run a Cross-Device Tour QA Pass

Your deployed tour already works on a phone. In this mission, you will compare the camera journey across a laptop plus both phone orientations to find the viewport that needs the most attention.

Clean Up Your Resources

Clean Up Your Resources

Choose whether to keep your room tour available, pause local work, or remove it. Your static site runs on GitHub Pages with no ongoing project costs.

Resources you used:

  • Your local seijaku repository with its production build.
  • Your GitHub repository that publishes the room tour.
  • Your GitHub Pages deployment at your live project URL.
  • Any uncompressed source texture copies still stored inside the local seijaku repository.

Keep everything running

No action is needed for your GitHub Pages site or GitHub repository. Choose this option if you want the live room tour available for sharing or future edits.

  • Leave the GitHub repository that publishes your room tour online.
  • Keep the local seijaku repository on your computer.
  • Search the local seijaku repository for any uncompressed source texture files you retained.
  • Confirm that your editor finds no references to each uncompressed source texture file.
  • Delete each unreferenced uncompressed source texture file from the local seijaku repository.
  • Open your live project URL in a browser.

You'll see the room tour load with its compressed textures. Scrolling should still move the camera between Room One and Room Two while the sky rays animate.

Pause - I'll come back to this later

Pause local work while preserving every project artifact. Your GitHub Pages deployment can remain published because this project has no ongoing project costs.

  • Stop any local development server process that is still running.
  • Close browser DevTools.
  • Leave the GitHub Pages site published at your live project URL.
  • Keep the GitHub repository that publishes your room tour.
  • Keep the local seijaku repository on your computer.

Your source code remains ready for another editing session. The deployed tour stays available on your live project URL.

Delete - I don't want to use this again

Remove the published site plus both copies of your project. Use this option only when you no longer need the room tour or its source files.

Deletion is permanent

Deleting the local repository removes your editable source. Deleting the remote repository removes the published project.

GitHub asks for confirmation before deleting the repository.

  • Copy any project files you want to preserve to a location outside the local seijaku repository.
  • Open the GitHub repository that publishes your live project URL.
  • Navigate to that repository's settings page.
  • Find the repository deletion controls near the bottom of the settings page.
  • Follow the confirmation prompt to delete the repository.
  • Open your live project URL after the repository deletion completes.

The room tour should no longer load from the live project URL. This confirms that the GitHub Pages deployment is gone.

macOS

  • Press Cmd+Space to open macOS search.
  • Type Finder and press Enter.
  • Locate the local seijaku repository folder.
  • Delete the local seijaku repository folder from Finder.
  • Confirm that the seijaku folder no longer appears in Finder.

Windows

  • Press the Windows key to open Windows search.
  • Type File Explorer and press Enter.
  • Locate the local seijaku repository folder.
  • Delete the local seijaku repository folder from File Explorer.
  • Confirm that the seijaku folder no longer appears in File Explorer.

Deleting the local seijaku folder also removes its production build. Any uncompressed source texture copies inside that folder are removed with it.

Nice Work!

Nice Work!

You did it! Your scrolling 3D room tour now guides visitors from Room One to Room Two on a live site powered by three.js.

You've learned how to:

  • Build a custom 3D scene with your own room texture. Add a compressed sky texture with animated sky rays.
  • Create a scroll-driven camera path using normalized progress. Visitors can travel smoothly between named rooms across different screen heights.
  • Improve browser performance by capping the device pixel ratio at 2. Measure first-paint performance with browser DevTools. Publish the production build with GitHub Pages. Confirm the live tour works on a phone.
  • Secret Mission: Extend your room tour through an optional challenge that pushes your 3D scene skills further.

Ready to quiz yourself?