Three.js From Zero · Article s15-01
Build Your Three.js Portfolio Site
Build Your Three.js Portfolio Site is Article s15-01 of Three.js From Zero, a MasterAllArts free interactive lesson for artists learning creative 3D on the web.
Season 15 · Article 01 · Portfolio & Career
A real, deployable portfolio. Three.js where it earns its keep, plain HTML where it doesn't. Most "Three.js portfolios" fail because they go all-in on 3D — yours wins by knowing when 2D is the right answer.
What recruiters actually look at
Track your own analytics next time you ship: time on page distributes as something like this:
- 10s — landed, looked at hero. If hero doesn't sell in 10s, they leave.
- 30s — scrolled to projects. Stay or leave on the strength of project thumbnails.
- 2 minutes — clicked into one project. The good case.
- 5 minutes — read your about page. The "we're hiring this person" case.
Build for those four moments specifically.
The structure that works
- Hero (1 screen) — your name, what you do, one visual hook. 3D HERE is fine if it loads in <2s.
- Projects (grid) — 4-8 cards. Thumbnail + name + one-line description. Each clickable.
- About (text) — your story in 200 words. No 3D — focus on the writing.
- Contact (clear) — email link, GitHub, X, Discord. Maybe a form.
Where Three.js belongs
- Hero centerpiece — a 3D logo, your name, an abstract animation. The "wow" moment.
- One project's expanded view — if a project IS a 3D thing, the project page should let users interact with it.
- Cursor effects, micro-interactions — subtle, not the main attraction.
Where it does not belong
- Project thumbnails — use real screenshots. Recruiters scan grids; they don't wait for 8 WebGL contexts to load.
- About page — text is fine.
- Navigation — never make people learn how to navigate your site.
The tech stack
Astro # static, fast, supports MDX for project case studies
@astrojs/react # for the R3F islands
three + R3F # for the hero only
Tailwind # CSS so you can ship
A real font # not the default system stack
Astro renders the HTML shell instantly. The 3D hero hydrates after first paint as a React island. The rest of the site is plain HTML — instant clicks, instant scrolls, perfect Lighthouse scores.
The hero pattern
// /src/pages/index.astro
<BaseLayout>
<section class="h-screen relative">
<HeroCanvas client:idle /> {/* hydrate after page load */}
<div class="absolute inset-0 flex items-end p-12 pointer-events-none">
<h1 class="text-7xl font-bold">Your Name</h1>
</div>
</section>
<Projects />
<About />
<Contact />
</BaseLayout>
client:idle tells Astro to hydrate the hero after the page is interactive — your text shows instantly, the WebGL fires up in the background.
Project case studies
Each project gets its own page at /projects/<slug>. Format:
- Hero image / video at the top
- One paragraph: what was the goal, what you did
- 3-5 specific decisions ("I picked X because Y")
- The result (numbers if possible: "loaded in 1.2s", "60fps on Pixel 6a", "10k MAUs")
- Tech list (small)
- Links: live demo, GitHub, blog post if any
Specifics get you hired. Vagueness gets you ignored.
What to write in About
"I make interactive 3D for the web. Previously I [shipped] [specific thing]
at [where]. I'm interested in [specific niche, e.g., 'product configurators'].
I'm currently [open to work / freelance / building X]. Reach me at [email]."
200 words max. Use specifics. Skip the generic ("passionate about creating amazing experiences"). Recruiters can detect generic copy in two seconds.
Common first-time pitfalls
Exercises
- Ship V1 in a weekend. Astro template, your name, one project, an email link. Get it live. Iterate from there.
- Show, don't tell. For each project, find ONE number that demonstrates impact ("3M views", "shipped in 2 weeks", "k MRR"). Lead with that.
- Get feedback. Show your draft to 3 people. Each picks their #1 confusion. Fix all three before launch.
UP NEXT
S15-02 — Sliding Puzzle in 3D → A classic portfolio piece.