Study
05

Roman Mtchedlishvili
A candle-lit archive built around Roman's handmade world.
Roman MTC was personal from the start: I was building for a friend and for an artist I genuinely believe in. The challenge was to preserve Roman's voice while making the portfolio feel like an archive you discover, not another image feed. The candlelight cursor, paper atmosphere, chapter pacing, and custom font made from Roman's handwriting all serve that world.
Creative Direction
The idea was mine: turn Roman's handmade world into a candle-lit editorial archive rather than a normal portfolio grid. I designed the visual language, pacing, art direction, paper atmosphere, and story sequence around his work.
Experience Engineering
I built the single-page Next.js experience with a candlelight cursor, drifting spotlight, dust canvas, scroll progress, parallax chapters, click-to-enter boot state, and typewriter writing system.
Custom Typography
I converted Roman's calligraphy into a deployable Romeo web font using an online handwriting-to-font workflow, then shipped it as OTF/TTF with @font-face so the archive reads in his own hand.
The cursor became
the light source.
The pointer is part of the scene. I built an interactive candle system that follows fine pointer movement, drifts when idle, changes spotlight size and glow with flame-like oscillation, and disables pointer tracking on touch so mobile feels theatrical instead of flashlight-like.
const CANDLE = {
FAST_INFLUENCE: 0.18,
BREATHE_INFLUENCE: 0.82,
POINTER_FOLLOW: 0.125,
IDLE_FOLLOW: 0.046,
};
function setSpotlightVars({ x, y, dim, glow, core, falloff, flare }) {
rootStyle.setProperty("--spot-x", `${((x / innerWidth) * 100).toFixed(3)}%`);
rootStyle.setProperty("--spot-y", `${((y / innerHeight) * 100).toFixed(3)}%`);
rootStyle.setProperty("--spot-dim", dim.toFixed(3));
rootStyle.setProperty("--spot-glow", glow.toFixed(3));
rootStyle.setProperty("--spot-core-size", `${core.toFixed(1)}px`);
rootStyle.setProperty("--spot-falloff-size", `${falloff.toFixed(1)}px`);
}
on(window, "pointermove", (event) => {
if (event.pointerType === "touch") return;
pointerX = event.clientX;
pointerY = event.clientY;
lastPointerAt = performance.now();
}, { passive: true });Roman's own hand
I turned Roman's calligraphy into the site's voice. The workflow uses the same principle as tools like Calligraphr: draw glyphs into a template, digitize and clean the letterforms, then export a standard OpenType/TrueType font. In the build, that becomes Romeo-Regular.otf loaded through @font-face.
@font-face {
font-family: "Romeo";
src: url("/fonts/Romeo-Regular.otf") format("opentype"),
url("/fonts/Romeo-Regular.ttf") format("truetype");
font-weight: 400;
font-style: normal;
font-display: block;
}
The first click is part of the experience.
The welcome screen asks users to click before entering so the scribble sound starts from an intentional user gesture. That is both a correct browser UX choice and a storytelling decision: no surprise autoplay, no broken audio promise, and the archive opens like something being written by hand.

