- Published on
ValoMono: A Typeface for Creative Code
- Authors
- Name
- Emir Mujcevic
- @em____97
Introduction
This project started as part of my design studies. The assignment was to create a custom typeface, and I decided to explore what a programming font could look like if it was designed with creativity in mind, not just legibility.
The result was VALOMONO
a monospaced typeface that draws inspiration from modernist systems and experimental alphabets. While it could work as a functional programming font, my idea was to take it further: what if this typeface could also live inside the world of creative coding? What if the font wasn’t just something you use, but also something you could generate, manipulate, and play with through code?

Why Creative Code?
Traditional programming fonts are built around clarity and efficiency. They’re neutral, stable, and predictable, which is exactly what makes them good for writing code. But creative coding thrives on the opposite: unpredictability, experimentation, and play.
That contrast made me curious. Could a typeface carry the discipline of coding but still open doors to visual experimentation?
This is where p5.js came in. Using Claude as a coding partner, I began creating sketches that didn’t just render the typeface as static text, but treated it as raw material for generative visuals.
Experiments in p5.js
Dancing Letters (1/4)
For this experiment, I wanted to see how the typeface could behave when combined with generative code. Using p5.js, I broke the word VALOMONO
into individual particles, each represented as tiny rotating squares. These particles aren’t static, they move, interact with the mouse, and always try to return to their original letter shapes.
The idea was to explore how a typeface can exist beyond print or static screens, and instead come alive through motion and interaction. This sketch turns typography into a kind of living system, where the letters themselves react and play with the user.

let valoMono;
let textContent = "VALOMONO";
let particles = [];
let fontSize = 80;
let isFontLoaded = false;
function preload() {
valoMono = loadFont('valoMono-Regular.otf');
}
function setup() {
createCanvas(800, 800);
textFont(valoMono);
textSize(fontSize);
createTextParticles();
isFontLoaded = true;
}
function draw() {
background(0);
if (!isFontLoaded) return;
// Update and display square particles
for (let p of particles) {
p.update();
p.display();
}
// Interaction when mouse is pressed
if (mouseIsPressed) {
let force = createVector(random(-1, 1), random(-1, 1));
for (let p of particles) {
p.applyForce(force);
}
}
// Return particles to original position
for (let p of particles) {
p.returnHome();
}
}
function createTextParticles() {
particles = [];
let points = valoMono.textToPoints(textContent,
width/2 - textWidth(textContent)/2,
height/2 - fontSize/2,
fontSize, {
sampleFactor: 1
});
for (let pt of points) {
let homePos = createVector(pt.x, pt.y);
let currentPos = createVector(pt.x, pt.y);
// Create particle with random square size and slight color variation
let squareSize = 1;
let col = color(
500, // R
500, // G
500 // B
);
particles.push(new SquareParticle(homePos, currentPos, col, squareSize));
}
}
class SquareParticle {
constructor(homePos, currentPos, col, size) {
this.homePos = homePos.copy();
this.pos = currentPos.copy();
this.vel = createVector(0, 0);
this.acc = createVector(0, 0);
this.maxSpeed = 3;
this.col = col;
this.size = size;
this.angle = 0;
this.rotationSpeed = random(-1, 1);
}
update() {
this.vel.add(this.acc);
this.vel.limit(this.maxSpeed);
this.pos.add(this.vel);
this.acc.mult(0);
this.angle += this.rotationSpeed;
}
display() {
noStroke();
fill(this.col);
push();
translate(this.pos.x, this.pos.y);
rotate(this.angle);
rectMode(CENTER);
square(0, 0, this.size);
pop();
}
applyForce(force) {
this.acc.add(force);
// Add some extra rotation when force is applied
this.rotationSpeed = random(-0.1, 0.1);
}
returnHome() {
let force = p5.Vector.sub(this.homePos, this.pos);
force.mult(0.05);
this.applyForce(force);
// Slow down rotation when returning home
this.rotationSpeed *= 0.95;
}
}
function mouseMoved() {
for (let p of particles) {
let mousePos = createVector(mouseX, mouseY);
let d = p5.Vector.dist(mousePos, p.pos);
if (d < 100) {
let force = p5.Vector.sub(p.pos, mousePos);
force.normalize();
force.mult(2);
p.applyForce(force);
}
}
}
Modular Letter Grid (2/4)
Another direction I explored was to treat the typeface not just as text, but as building blocks in a dynamic grid. Each cell in the grid rotates independently, while cycling through different letter variations from the typeface. The result is a looping, ever-changing typographic pattern, almost like a modular logo system made out of letters.

let valoMonoFont;
let gridSize = 4;
let cellSize;
let rotationAngles = [];
let letterVariations = [];
let currentFrame = 0;
function preload() {
valoMonoFont = loadFont('valoMono-Regular.otf');
}
function setup() {
createCanvas(800, 800);
// Calculate cell size based on canvas and grid
cellSize = width / gridSize;
// Initialize rotation angles for each cell
for (let i = 0; i < gridSize * gridSize; i++) {
rotationAngles[i] = 0;
}
// Define letter variations (A transformations)
letterVariations = [
'v',
'a',
'l',
'O',
'M',
'O',
'N',
'O'
];
}
function draw() {
background(220);
// Apply easing and cycling for rotation and letter variation
currentFrame++;
// Draw 4x4 grid
for (let row = 0; row < gridSize; row++) {
for (let col = 0; col < gridSize; col++) {
let index = row * gridSize + col;
// Calculate cell position
let x = col * cellSize;
let y = row * cellSize;
// Push matrix to apply transformations
push();
translate(x + cellSize/2, y + cellSize/2);
// Rotate cell
let rotationSpeed = 0.02;
rotationAngles[index] += rotationSpeed;
rotate(sin(rotationAngles[index]) * PI/4);
// Draw cell border
noFill();
stroke(0);
rect(-cellSize/2, -cellSize/2, cellSize, cellSize);
// Draw letter
textFont(valoMonoFont);
textSize(cellSize * 0.7);
textAlign(CENTER, CENTER);
fill(0);
// Cycle through letter variations
let variationIndex = floor(currentFrame / 20) % letterVariations.length;
text(letterVariations[variationIndex], 0, 0);
pop();
}
}
}
Shuffling Cards (3/4)
This sketch uses a standard 52-card deck, but instead of clicking or pressing keys, the cards flip automatically in an endless shuffle.
Each card is drawn with the typeface for the values and suits, while a minimal white-on-black design keeps the focus on motion. The animation smoothly flips each card, revealing its face or back, creating a continuous rhythm of chance and order like watching typography deal itself into a game.

ASCII Glitch (4/4)
One of my favorite outcomes from this project was turning ValoMono into the backbone of a generative ASCII animation. Instead of just typing with the font, I used the web editor to treat each character like a pixel in a living grid.
The sketch builds a wall of shifting symbols, glitching and reacting to mouse movement. Around the cursor, the letters disappear, leaving an empty void that constantly reshapes as you move across the screen.

Conclusion
These sketches show just a few ways the VALOMONO
typeface can move beyond static text and come alive in code-based experiments. Whether it’s glitching ASCII, particle-driven typography, or even a shuffling deck of cards, the font adapts to playful and unexpected contexts.
I’ve also made the collection available on p5.js Web Editor, a free space where you can explore, remix, and create your own variations with ValoMono.
Thank you for reading.
Yours truly,
Emir
Next Steps
- Fork and Remix: Open any sketch in the collection, duplicate it, and start tweaking values like grid size, animation speed, or colors.
- Experiment with Letters: Replace
VALOMONO
with your own text or symbols to see how the typeface transforms in different contexts. - Design Your Own: Use the examples as a starting point for building new generative artworks, interactive installations, or even custom visual identities powered by code.
- Share Back: Publish your remixes or projects online and tag them, the idea is to keep this space open and collaborative.