I Built a React Component That Turns Any Portfolio Into a 3D Minecraft World
Every developer portfolio looks the same. Dark mode. Sans-serif font. "Hi, I'm X, a passionate developer." Scroll. Skills section with floating icons. Scroll. Projects in a grid. Scroll. Contact form nobody will fill.
Sound familiar?
I've reviewed hundreds of developer portfolios — as a peer, during hackathons, while hiring. They all blur into one. The content might differ, but the experience is identical.
So I asked myself a stupid question:
What if your portfolio was a playable Minecraft world instead?
And then I actually built it.
Introducing CraftFolio
CraftFolio is an open-source React component library that transforms your developer portfolio into a live, interactive 3D voxel environment.
Your projects become structures you can walk up to. Your skills become minable ores. Your experience becomes terrain you traverse. No two portfolios look alike because the world is generated from your data.
One component. One config object. A portfolio nobody forgets.
import { CraftFolio } from 'craftfolio';
function App() {
return (
<CraftFolio
name="Shivansh Goel"
role="Full Stack Developer"
skills={['TypeScript', 'React', 'Python', 'FastAPI', 'Three.js']}
projects={[
{ name: 'Forkcast', url: 'https://github.com/...', block: 'diamond' },
{ name: 'GhostRelay', url: 'https://github.com/...', block: 'obsidian' },
{ name: 'ZipLink', url: 'https://github.com/...', block: 'emerald' },
]}
theme="overworld"
/>
);
}
That's the entire integration. Drop it in, customize the config, deploy.
Why I Built This
Let me give you a number: 4.7 million.
That's how many repositories come up when you search "developer portfolio" on GitHub. Nearly five million variations of the same three-column layout with a hero section.
When a recruiter reviews 200 portfolios in a week, yours needs to be the one they remember at dinner.
"Honey, I saw this kid's portfolio today — it was literally Minecraft."
That's the unfair advantage CraftFolio gives you.
What You Actually Get
When you drop CraftFolio into your React app, it renders:
- A 3D voxel world — real-time Three.js rendering with a Minecraft aesthetic
- Walkable terrain — procedurally generated from your data
- Project structures — your repos become buildings you can approach and click
- Skill ores — your tech stack appears as glowing blocks scattered through the world
- Day/night cycle — dynamic lighting that shifts over time
- Keyboard navigation — WASD movement, mouse to look, click to interact
- Mobile touch controls — virtual joystick + tap interaction
- Responsive fallback — gracefully degrades to a styled 2D view on very old devices
The Technical Deep-Dive
Architecture
CraftFolio/
├── src/
│ ├── components/
│ │ ├── VoxelWorld.tsx — Three.js scene, camera, renderer
│ │ ├── Terrain.tsx — Procedural world generation
│ │ ├── PlayerControls.tsx — First-person camera + WASD movement
│ │ ├── ProjectStructure.tsx — Interactive project buildings
│ │ ├── SkillOre.tsx — Floating/glowing skill blocks
│ │ └── HUD.tsx — Overlay UI (name, minimap, controls hint)
│ ├── shaders/
│ │ ├── voxel.vert — Vertex shader for block geometry
│ │ └── voxel.frag — Fragment shader with pixelated lighting
│ ├── systems/
│ │ ├── WorldGenerator.ts — Perlin noise terrain + structure placement
│ │ ├── PhysicsEngine.ts — Simple AABB collision detection
│ │ └── InteractionManager.ts — Raycasting for click detection
│ ├── config/
│ │ └── themes.ts — Overworld, Nether, End color palettes
│ └── index.ts — Public API export
Performance: 10,000+ Voxels at 60fps
The naive approach to rendering voxels is one mesh per block. At 10,000 blocks, that's 10,000 draw calls per frame. Your GPU melts.
CraftFolio uses instanced rendering — a single geometry is drawn thousands of times in one draw call, with per-instance transforms stored in a buffer:
const blockGeometry = new THREE.BoxGeometry(1, 1, 1);
const blockMaterial = new THREE.MeshLambertMaterial({ map: textureAtlas });
const instancedMesh = new THREE.InstancedMesh(
blockGeometry,
blockMaterial,
MAX_BLOCKS
);
// Set position for each block instance
blocks.forEach((block, i) => {
const matrix = new THREE.Matrix4();
matrix.setPosition(block.x, block.y, block.z);
instancedMesh.setMatrixAt(i, matrix);
});
// One draw call for ALL blocks
scene.add(instancedMesh);
Additional optimizations:
- Frustum culling — don't render blocks behind the camera
- Face culling — don't render faces between two adjacent solid blocks
- LOD (Level of Detail) — distant blocks render as flat colored planes
- Texture atlas — all block textures in one spritesheet = one texture bind
Result: Smooth 60fps on desktop, 30fps+ on mid-range mobile.
Terrain Generation with Perlin Noise
The world isn't random — it uses layered Perlin noise to create natural-looking hills and valleys:
function generateTerrain(width: number, depth: number): BlockData[] {
const blocks: BlockData[] = [];
for (let x = 0; x < width; x++) {
for (let z = 0; z < depth; z++) {
const baseHeight = perlin2D(x * 0.05, z * 0.05) * 8;
const hills = perlin2D(x * 0.02, z * 0.02) * 12;
const detail = perlin2D(x * 0.1, z * 0.1) * 2;
const height = Math.floor(baseHeight + hills + detail) + 10;
for (let y = 0; y <= height; y++) {
blocks.push({
x, y, z,
type: y === height ? 'grass' : y > height - 3 ? 'dirt' : 'stone'
});
}
}
}
return blocks;
}
Project structures are placed at terrain peaks — naturally visible from anywhere in the world.
The React + Three.js Marriage
Reconciling React's declarative model with Three.js's imperative scene graph is painful. Here's how CraftFolio solves it:
- The scene lives in a ref — Three.js objects are created once and mutated, not re-rendered
- React controls state — UI, config changes, and user data flow through React state
-
A bridge hook syncs them —
useWorldSync()watches React state and imperatively updates the scene
function useWorldSync(config: CraftFolioConfig, sceneRef: RefObject<THREE.Scene>) {
useEffect(() => {
if (!sceneRef.current) return;
rebuildProjectStructures(sceneRef.current, config.projects);
rebuildSkillOres(sceneRef.current, config.skills);
applyTheme(sceneRef.current, config.theme);
}, [config.projects, config.skills, config.theme]);
}
This avoids the "React re-renders destroy my 3D scene" problem while keeping the developer API fully declarative.
Three Hard Lessons I Learned
1. Mobile Performance Is a Different Beast
On desktop with a discrete GPU, you can afford expensive shaders. On a 2020 mid-range Android phone? You're fighting for every millisecond.
I had to:
- Reduce world size from 100x100 to 40x40 on mobile
- Disable shadows on low-end devices
- Implement a quality auto-scaler that drops render resolution if FPS dips below 24
2. Accessibility in a 3D World Is Hard (But Possible)
A recruiter using a screen reader can't "walk through" a 3D world. So CraftFolio includes:
- An
aria-liveregion that narrates: "You are near the Forkcast project. Press Enter to view details." - Keyboard-only navigation mode (arrow keys + tab)
- A
reduceMotionmode that shows a 2D card layout instead (respectsprefers-reduced-motion) - All interactive elements in the tab order with proper labels
3. Bundle Size Wars
Three.js is ~150KB gzipped. For a portfolio component, that's heavy. My approach:
- Three.js is a peer dependency — if you're already using it, no extra cost
- Tree-shakeable imports — only pulling in what's needed
- CraftFolio-specific code is ~45KB gzipped
- Lazy loading — the 3D world only initializes when entering the viewport
Themes: Choose Your Dimension
CraftFolio ships with three themes:
| Theme | Vibe | Best For |
|---|---|---|
| Overworld | Green grass, blue sky, warm lighting | Friendly, approachable portfolios |
| Nether | Dark red, lava lakes, dramatic shadows | Edgy/gaming-focused developers |
| End | Purple void, floating islands, ethereal glow | Creative/artistic portfolios |
<CraftFolio theme="nether" />
You can also pass a custom theme object for full control over colors, skybox, and block textures.
Who Is This For?
Use CraftFolio if you're:
- A junior dev who needs to stand out in a brutal job market
- An experienced dev who wants something memorable for their personal brand
- A game dev who wants their portfolio to demonstrate their passion
- A content creator who needs a unique landing page
- Anyone tired of the same Tailwind/Next.js portfolio template
Don't use CraftFolio if:
- Your target audience is strictly corporate/enterprise
- You need perfect Lighthouse accessibility scores
- You're applying to a company that blocks WebGL
Get Started in 60 Seconds
Install
npm install craftfolio three @types/three
Basic Usage
import { CraftFolio } from 'craftfolio';
export default function Portfolio() {
return (
<CraftFolio
name="Your Name"
role="Your Title"
skills={['React', 'Node.js', 'Python']}
projects={[
{
name: 'My Cool Project',
description: 'A brief description',
url: 'https://github.com/you/project',
block: 'diamond',
},
]}
theme="overworld"
controls="wasd"
onProjectClick={(project) => window.open(project.url)}
/>
);
}
Deploy
Works with any React hosting:
vercel deploynetlify deploy- GitHub Pages
- Any static host
What's on the Roadmap
- Multiplayer mode — Visitors see each other as pixelated avatars
- Custom block textures — Upload your own pixel art
-
NPM CLI scaffolder —
npx create-craftfolio - Weather system — Rain, snow, or sunshine based on location
- Sound effects — Footsteps, ambient music, interaction clicks
- Analytics integration — Track which projects visitors interact with most
The Source
- GitHub: github.com/Tech-aficionado/CraftFolio---Open-Sourced-Minecraft-Portfolio-Library
- License: MIT
- Stack: TypeScript (83.8%) + HTML (8.0%) + CSS (5.7%) + JavaScript (2.5%)
- Bundle: ~45KB gzipped (Three.js peer dependency)
Final Thought
The best portfolio isn't the one with the most impressive project list. It's the one the recruiter remembers.
Five million portfolios on GitHub. Five million dark-mode hero sections. Five million "passionate developer" taglines.
Or... one Minecraft world that someone actually played for two minutes.
Which one do you think gets the callback?
Star it if you'd use it. Fork it if you'd improve it. And drop a comment with YOUR most creative portfolio idea — I want to see what this community comes up with.
Built by Shivansh Goel — AI & Full Stack Developer building intelligent web platforms.
Top comments (0)