Constructing a private portfolio is without doubt one of the most difficult initiatives for any designer or developer. You’re by no means totally glad with the consequence. Every iteration raises new questions, and the method can simply flip into an countless cycle of rethinking and rebuilding.
This 12 months marked a brand new chapter for me as I turned a contract developer, and it felt like the precise second to revamp my portfolio — my first new launch in six years. The mission gave me the chance to discover new concepts, push my technical boundaries, and rethink how I current my work.
On this case examine, I’ll share insights into the inventive course of, design selections, and technical challenges behind the mission.
A. Idea & Expertise
The principle objective of this portfolio was to create an area to showcase each my initiatives and the WebGL experiments I’ve been creating over the previous few months. From the start, I needed to combine WebGL in a refined method. The thought was to discover a stability between a 2D interface that stays clear and readable, and a 3D surroundings that provides depth and motion.
The mission began with easy sketches in my pocket book, which helped me shortly outline the construction and consumer movement earlier than transferring into the design and growth phases.

B. Inspirations & Design
With a background in design, I challenged myself to create the interface by myself. The method was lengthy and generally demanding. It concerned many iterations and a whole lot of refinement earlier than I reached a route I used to be pleased with.
I’ve all the time been enthusiastic about typography and printed posters. That naturally drew me towards sturdy graphic methods and expressive typographic compositions. The visible route attracts closely from the Swiss Type, with a intentionally restricted coloration palette of orange, white, and black.

Most of my inspiration got here from offline experiences. I spent a whole lot of time in bookstores, looking design, portray, and images books and learning their layouts and typographic methods. I like taking the time to take a look at grids, margins, and kind decisions, after which translating these concepts into the net. These references helped form a transparent and constant visible id. I additionally explored references on Pinterest, the place I often search for inspiration.
On the similar time, I needed to introduce a 3D dimension utilizing WebGL, a area I’ve been exploring for a number of months. One of many most important challenges was to search out the precise stability between this experimental strategy and a extra structured, editorial aesthetic.
For the homepage, this translated into an overarching 3D geometry that comes with previews of all my initiatives. The method concerned many iterations, experimenting with totally different layouts and interactions earlier than arriving on the ultimate model. Right here’s a glimpse of the assorted iterations I examined:
C. Improvement Overview
From the beginning, I needed full management over the event course of, so I made a decision to keep away from frameworks and construct the portfolio utilizing solely vanilla JavaScript. This saved the stack light-weight and helped me higher perceive each a part of the codebase. I additionally carried out a easy PJAX routing system to allow easy, animated web page transitions.
For styling, I relied on SCSS with the BEM methodology, conserving the code modular and maintainable. All web page information is saved in JSON, offering flexibility with out the necessity for a CMS or static web site generator.
For the WebGL elements, I used Three.js mixed with GLSL, enabling 3D geometries and interactive visualizations. GSAP dealt with all of the animations throughout the portfolio, whereas Lenis ensured a easy scrolling expertise.
Undertaking Construction
The portfolio is organized to remain modular and simple to keep up. Web page information is saved in JSON, whereas WebGL elements, reusable JavaScript modules, and SCSS types are clearly separated into devoted directories. This construction makes it simpler to iterate and lengthen the mission over time.
Right here’s an outline of the mission construction:
src/
├── information/ # JSON information for every web page
│ ├── about.json
│ ├── archive.json
│ └── ...
├── glsl/ # GLSL shaders
│ ├── archive/
│ │ ├── fragment.glsl
│ │ └── vertex.glsl
│ ├── modules/ # Reusable GLSL modules (noise, utils)
│ ├── work/
│ └── ...
├── js/ # Consumer-side JavaScript
│ ├── index.js # Principal app entry level
│ ├── animations/ # GSAP web page transitions & preloader
│ ├── elements/ # Reusable UI elements
│ │ ├── Availability.js # Availability standing badge
│ │ ├── Cross.js # Interactive cross cursor
│ │ ├── Dimensions.js # Viewport dimensions tracker
│ │ ├── GridHelper.js # Dev grid overlay
│ │ ├── GridRules.js # Grid rule traces
│ │ ├── LocaleTime.js # Native time show
│ │ ├── ScrollIndicator.js # Scroll progress indicator
│ │ ├── ViewSwitcher.js # Listing/Overview view toggle
│ │ └── ...
│ ├── pages/ # Web page controllers
│ │ ├── About.js
│ │ ├── Archive.js
│ │ └── ...
│ ├── utils/ # Helpers (Lerp, Easings, Routing…)
│ └── webgl/ # WebGL renders
│ ├── Canvas.js
│ ├── archive/
│ ├── index/
│ ├── overview/
│ └── work/
└── scss/ # SCSS types
D. Animations & Movement
On this part, I’ll stroll by way of a number of the movement ideas I used within the mission.
Grid guidelines
To bolster the editorial and pixel-perfect aesthetic of the interface, I launched a small interactive easter egg. When the consumer clicks the central cross, a set of grid guidelines dynamically body the principle web page title.
Right here’s a preview:
The thought is straightforward: I retrieve the place of parts marked with data-rules utilizing getBoundingClientRect(), then dynamically generate 4 traces, one for all sides, positioned with transforms to border the aspect.
Implementation
The script calculates the aspect’s bounding field and creates horizontal and vertical guides positioned relative to the viewport.
class App {
constructor() {
// DOM
this.DOM = {
button: doc.querySelector("button"),
title: doc.querySelector("h1"),
guidesContainer: doc.querySelector(".grid-rules"),
}
// States
this.isActive = false
// Listeners
this.createGuides()
}
/**
* Guides
*/
createGuides() {
this.DOM.guidesContainer.innerHTML = ""
const rect = this.DOM.title.getBoundingClientRect()
const positions = [
{ type: "horizontal", pos: rect.top },
{ type: "horizontal", pos: rect.bottom },
{ type: "vertical", pos: rect.left },
{ type: "vertical", pos: rect.right },
]
positions.forEach(({ sort, pos }) => {
const information = doc.createElement("div")
information.className = `grid-rules__guide grid-rules__guide--${sort}`
gsap.set(information, {
x: sort === "vertical" ? pos : 0,
y: sort === "horizontal" ? pos : 0,
opacity: this.isActive ? 1 : 0,
});
this.DOM.guidesContainer.appendChild(information)
})
}
}
Every information is a 1px line that spans the total width (horizontal) or peak (vertical) of the viewport. The container is fastened to the viewport whereas guides are completely positioned inside it:
.grid-rules {
place: fastened;
inset: 0;
pointer-events: none;
}
.grid-rules__guide {
place: absolute;
prime: 0;
left: 0;
background-color: purple;
&--horizontal {
width: 100%;
peak: 1px;
}
&--vertical {
width: 1px;
peak: 100%;
}
}
Interplay & Animation
The visibility of the guides is toggled on button click on utilizing GSAP, which easily fades the traces out and in.
addEventListeners() {
this.DOM.button.addEventListener("click on", this.handleClick);
}
handleClick(occasion) {
occasion.preventDefault();
this.isActive = !this.isActive;
gsap.to(".grid-rules__guide", {
opacity: this.isActive ? 1 : 0,
length: 0.5,
});
}
This can be a simplified model of the system carried out within the ultimate mission, which you’ll discover right here:
Navigation Switcher
Micro-interactions usually play a key position in shaping the general consumer expertise. For the principle navigation, I carried out a dynamic masks switcher that follows the cursor and adapts to the width of the hovered hyperlink.
When the consumer hovers a navigation merchandise, the masks easily resizes and repositions itself to match the hyperlink’s dimensions, creating extra responsive and tactile suggestions.
Right here’s a preview:
Idea
The interplay depends on monitoring the hovered aspect’s bounding field and updating the masks’s dimension and place accordingly. As an alternative of utilizing static hover states, the masks behaves as a shared visible indicator that transitions between hyperlinks.
This creates:
- A stronger visible hierarchy.
- Smoother navigation suggestions.
- A extra dynamic and editorial navigation expertise.
Implementation
The system listens for hover occasions on navigation hyperlinks, retrieves their dimensions utilizing getBoundingClientRect(), and updates the masks’s rework and dimension to match the energetic aspect.
The transition between states is interpolated to maintain the movement fluid and attentive to cursor motion.
updateMaskPosition(goal, length = 0) {
const targetRect = goal.getBoundingClientRect()
const navRect = this.DOM.navigation.getBoundingClientRect()
const x = targetRect.left - navRect.left
const y = targetRect.prime - navRect.prime
const { width, peak } = targetRect
gsap.to(this.DOM.navigationMask, {
x,
y,
width,
peak,
length,
ease: "power3.out",
})
}
Outcome
This strategy creates a steady movement expertise the place the navigation feels reactive quite than state-based, reinforcing the general movement language of the portfolio.
Try this simplified model I made for my portfolio:
E. Closing Contact
Closing touches are sometimes probably the most difficult a part of a mission. Even after refining the design, animations, and interactions, I nonetheless felt one thing was lacking, one thing that might assist the mission stand out from different developer and designer portfolios.
To push the grid guidelines system additional, I launched an interactive ruler function impressed by Figma. Customers can place their very own markers immediately on the interface and place them wherever they need. This function reinforces the general editorial route of the web site whereas turning the structure itself into an interactive expertise.
To increase this concept even additional, I additionally added the power to toggle the structure grid used all through the location with a keyboard shortcut (Choice + G), permitting customers to disclose the underlying construction of the design. It’s a software I personally use in each mission to make sure alignment and precision, and I believed it will be enjoyable to make it accessible to customers as effectively.
These refined however playful options helped give the portfolio a stronger id. They bridge the hole between design tooling and consumer expertise, and spotlight how necessary construction, precision, and experimentation are on this mission.
F. Conclusion & Learnings
This portfolio is a crucial milestone in my journey as a designer and developer. It gave me the prospect to discover new concepts, apply the editorial design strategy I’m enthusiastic about, and push my WebGL experiments additional.
Alongside the best way, I needed to always stability experimentation and value, and consider carefully about what makes an interplay really feel significant quite than simply ornamental.
Relatively than a completed product, this portfolio is an evolving playground, an area for steady exploration, experimentation, and development.
I hope you loved this case examine. When you have any questions or suggestions, be happy to achieve out!








