Modern Web

Building a Dynamic WebXR AR Portfolio with A-Frame and Three.js

Step-by-step tutorial to building a mobile-friendly browser-native Augmented Reality portfolio. Code spatial cards and interactive 3D components using A-Frame.

Sachin Sharma
Sachin SharmaCreator
Jun 1, 2026
4 min read
Building a Dynamic WebXR AR Portfolio with A-Frame and Three.js
Featured Resource
Quick Overview

Step-by-step tutorial to building a mobile-friendly browser-native Augmented Reality portfolio. Code spatial cards and interactive 3D components using A-Frame.

Building a Dynamic WebXR AR Portfolio with A-Frame and Three.js

As spatial computing devices become mainstream, the web is transitioning from flat 2D layouts to immersive 3D spaces. A personal portfolio is the perfect playground to showcase your expertise in this new paradigm.

Imagine a recruiter visiting your website on their phone, tapping a button, and seeing your key projects and system architectures projected directly onto their desk in Augmented Reality (AR).

In this guide, we'll build a fully interactive, mobile-friendly WebXR AR Portfolio using A-Frame (an HTML-based declarative WebXR framework) and Three.js under the hood.


⚡ 1. The WebXR AR Architecture

WebXR is the browser-native standard that unlocks both Virtual Reality (VR) and Augmented Reality (AR) headsets and mobile devices directly through web APIs.

To render AR elements, the browser must:

  1. 2.
    Establish a camera stream.
  2. 4.
    Run native SLAM (Simultaneous Localization and Mapping) algorithms to detect flat planes in the user's real-world environment.
  3. 6.
    Composite 3D graphics on top of the detected planes in real-time, synchronized with the camera's gyroscope and accelerometer.

A-Frame abstracts this complex mathematical rendering pipeline behind clean, semantic HTML-like tags, allowing us to declare 3D models, lighting, and physics easily.

[User Camera Stream] ──> [SLAM Device Tracking]
                                │
[A-Frame / Three.js 3D Objects] ┴─> [WebXR Compositor] ──> [AR Screen Output]

🏗️ 2. Setting Up the AR Scene

Let's write a standard HTML layout to boot our WebXR experience. A-Frame loads WebXR capability immediately when configured.

html
<!DOCTYPE html> <html> <head> <title>Sachin Sharma | Spatial AR Portfolio</title> <!-- Load A-Frame and the specialized WebXR AR subsystem --> <script src="https://aframe.io/releases/1.5.0/aframe.min.js"></script> <script src="https://raw.githack.com/AR-js-org/AR.js/master/aframe/build/aframe-ar.js"></script> </head> <body style="margin: 0px; overflow: hidden;"> <!-- 1. Define the A-Frame Scene with AR capabilities --> <a-scene embedded arjs="sourceType: webcam; debugUIEnabled: false;"> <!-- 2. Preload assets (3D GLTF models, textures) --> <a-assets> <a-asset-item id="avatar-model" src="/assets/sachin_holographic_avatar.gltf"></a-asset-item> </a-assets> <!-- 3. Add a marker-based holographic card container --> <a-marker preset="hiro"> <!-- Rotating Holographic Avatar --> <a-entity gltf-model="#avatar-model" position="0 0.5 0" scale="0.2 0.2 0.2" animation="property: rotation; to: 0 360 0; loop: true; dur: 8000; easing: linear"> </a-entity> <!-- Project Title Panel (Glassmorphic CSS Card in 3D) --> <a-plane position="0 1.2 0" rotation="-30 0 0" width="1.8" height="0.6" color="#0d1117" material="opacity: 0.85; transparent: true; roughness: 0.1"> <a-text value="SACHIN SHARMA Software Developer" align="center" color="#00f2fe" width="4" font="monoid"> </a-text> </a-plane> <!-- Interactive Spatial Buttons (Tap Targets) --> <a-box id="btn-projects" position="-0.6 0 0.5" scale="0.4 0.1 0.4" color="#ff007f" class="clickable"> <a-text value="PROJECTS" align="center" position="0 0.06 0" rotation="-90 0 0" scale="0.3 0.3 0.3" color="#ffffff"></a-text> </a-box> <a-box id="btn-hire" position="0.6 0 0.5" scale="0.4 0.1 0.4" color="#00f2fe" class="clickable"> <a-text value="HIRE ME" align="center" position="0 0.06 0" rotation="-90 0 0" scale="0.3 0.3 0.3" color="#ffffff"></a-text> </a-box> </a-marker> <!-- 4. Setup the camera with raycaster support for tapping elements --> <a-entity camera cursor="rayOrigin: mouse;" raycaster="objects: .clickable;"></a-entity> </a-scene> </body> </html>

💻 3. Creating Spatial Interactivity in JavaScript

To make the portfolio truly dynamic, we can capture 3D raycasting pointer events in JavaScript, letting viewers toggle project screens or trigger contact hooks when they click 3D buttons.

javascript
AFRAME.registerComponent('ar-portfolio-controller', { init: function () { const el = this.el; const btnProjects = document.querySelector('#btn-projects'); const btnHire = document.querySelector('#btn-hire'); // Tap/Click Animations on 3D Box targets btnProjects.addEventListener('mouseenter', function () { // Simulate hover glow effect btnProjects.setAttribute('material', 'emissive', '#ff007f'); }); btnProjects.addEventListener('mouseleave', function () { btnProjects.setAttribute('material', 'emissive', '#000000'); }); btnProjects.addEventListener('click', function () { // Scale animation btnProjects.setAttribute('animation', { property: 'scale', to: '0.4 0.02 0.4', dur: 100, dir: 'alternate', loop: 1 }); console.log("🌐 Navigating to projects segment..."); window.parent.postMessage({ action: 'NAVIGATE_PROJECTS' }, '*'); }); btnHire.addEventListener('click', function () { console.log("📨 Opening contact panel..."); window.parent.postMessage({ action: 'OPEN_HIRE_MODAL' }, '*'); }); } }); // Attach controller to the scene document.querySelector('a-scene').setAttribute('ar-portfolio-controller', '');

🚀 4. Performance & mobile Optimization

Rendering mobile-native AR inside a web browser requires aggressive frame optimization strategies to maintain a clean 60 FPS:

  1. 2.
    Low-Poly Models: Keep your GLTF avatars and assets under 15,000 polygons. Use textures instead of raw geometry to convey depth.
  2. 4.
    Texture Compression: Convert all standard PNG textures to KTX2 (Basis Universal) formats. This reduces GPU memory overhead by up to 75%.
  3. 6.
    Dynamic Rendering Cull: Disable calculations for shadows and post-processing filters on mobile viewports. Mobile GPUs are highly fill-rate limited.

🏁 5. Conclusion: Spatial Web is Already Here

WebXR bridges the virtual gap between standard flat portfolios and spatial computing. By embedding marker or plane-detected AR models inside your homepage, you demonstrate cutting-edge mastery over next-generation web platforms.

Sachin Sharma

Sachin Sharma

Software Developer

Building digital experiences at the intersection of design and code. Sharing weekly insights on engineering, productivity, and the future of tech.