Skip to content // StreakField — signal simulation
const GRID = 128; // flow potential lattice
let phase = 0; // A→B morph, ~14s per epoch
const curl = (x, y) => {
const dx = sample(x + h, y) - sample(x - h, y);
const dy = sample(x, y + h) - sample(x, y - h);
return [dy * FLOW, -dx * FLOW]; // divergence-free: pure swirl
};
for (let i = 0; i < P; i++) {
const [u, v] = curl(px[i], py[i]);
px[i] += (u + vortex.x + scatter.x) * dt * rush;
py[i] += (v + vortex.y + scatter.y) * dt * rush;
// cursor crush: flash teal, kick outward, spring home
if (d2(ptr, i) < R && ptr.speed > MIN) {
flash[i] = 1;
kick(i, ptr, (1 - d2 / R) * ptr.speed * IMPULSE);
}
charge[i] = Math.max(flash[i] *= COOL, trailGlow(px[i], py[i]));
}
// trails: fade pass 4.5% → filaments persist ~25 frames
fade(fbo, 0.045); draw(points, ADDITIVE); composite(fbo, screen);
// StreakField — signal simulation
const GRID = 128; // flow potential lattice
let phase = 0; // A→B morph, ~14s per epoch
const curl = (x, y) => {
const dx = sample(x + h, y) - sample(x - h, y);
const dy = sample(x, y + h) - sample(x, y - h);
return [dy * FLOW, -dx * FLOW]; // divergence-free: pure swirl
};
for (let i = 0; i < P; i++) {
const [u, v] = curl(px[i], py[i]);
px[i] += (u + vortex.x + scatter.x) * dt * rush;
py[i] += (v + vortex.y + scatter.y) * dt * rush;
// cursor crush: flash teal, kick outward, spring home
if (d2(ptr, i) < R && ptr.speed > MIN) {
flash[i] = 1;
kick(i, ptr, (1 - d2 / R) * ptr.speed * IMPULSE);
}
charge[i] = Math.max(flash[i] *= COOL, trailGlow(px[i], py[i]));
}
// trails: fade pass 4.5% → filaments persist ~25 frames
fade(fbo, 0.045); draw(points, ADDITIVE); composite(fbo, screen);
// StreakField — signal simulation
const GRID = 128; // flow potential lattice
let phase = 0; // A→B morph, ~14s per epoch
const curl = (x, y) => {
const dx = sample(x + h, y) - sample(x - h, y);
const dy = sample(x, y + h) - sample(x, y - h);
return [dy * FLOW, -dx * FLOW]; // divergence-free: pure swirl
};
for (let i = 0; i < P; i++) {
const [u, v] = curl(px[i], py[i]);
px[i] += (u + vortex.x + scatter.x) * dt * rush;
py[i] += (v + vortex.y + scatter.y) * dt * rush;
// cursor crush: flash teal, kick outward, spring home
if (d2(ptr, i) < R && ptr.speed > MIN) {
flash[i] = 1;
kick(i, ptr, (1 - d2 / R) * ptr.speed * IMPULSE);
}
charge[i] = Math.max(flash[i] *= COOL, trailGlow(px[i], py[i]));
}
// trails: fade pass 4.5% → filaments persist ~25 frames
fade(fbo, 0.045); draw(points, ADDITIVE); composite(fbo, screen);
// StreakField — signal simulation
const GRID = 128; // flow potential lattice
let phase = 0; // A→B morph, ~14s per epoch
const curl = (x, y) => {
const dx = sample(x + h, y) - sample(x - h, y);
const dy = sample(x, y + h) - sample(x, y - h);
return [dy * FLOW, -dx * FLOW]; // divergence-free: pure swirl
};
for (let i = 0; i < P; i++) {
const [u, v] = curl(px[i], py[i]);
px[i] += (u + vortex.x + scatter.x) * dt * rush;
py[i] += (v + vortex.y + scatter.y) * dt * rush;
// cursor crush: flash teal, kick outward, spring home
if (d2(ptr, i) < R && ptr.speed > MIN) {
flash[i] = 1;
kick(i, ptr, (1 - d2 / R) * ptr.speed * IMPULSE);
}
charge[i] = Math.max(flash[i] *= COOL, trailGlow(px[i], py[i]));
}
// trails: fade pass 4.5% → filaments persist ~25 frames
fade(fbo, 0.045); draw(points, ADDITIVE); composite(fbo, screen);
// StreakField — signal simulation
const GRID = 128; // flow potential lattice
let phase = 0; // A→B morph, ~14s per epoch
const curl = (x, y) => {
const dx = sample(x + h, y) - sample(x - h, y);
const dy = sample(x, y + h) - sample(x, y - h);
return [dy * FLOW, -dx * FLOW]; // divergence-free: pure swirl
};
for (let i = 0; i < P; i++) {
const [u, v] = curl(px[i], py[i]);
px[i] += (u + vortex.x + scatter.x) * dt * rush;
py[i] += (v + vortex.y + scatter.y) * dt * rush;
// cursor crush: flash teal, kick outward, spring home
if (d2(ptr, i) < R && ptr.speed > MIN) {
flash[i] = 1;
kick(i, ptr, (1 - d2 / R) * ptr.speed * IMPULSE);
}
charge[i] = Math.max(flash[i] *= COOL, trailGlow(px[i], py[i]));
}
// trails: fade pass 4.5% → filaments persist ~25 frames
fade(fbo, 0.045); draw(points, ADDITIVE); composite(fbo, screen);
// StreakField — signal simulation
const GRID = 128; // flow potential lattice
let phase = 0; // A→B morph, ~14s per epoch
const curl = (x, y) => {
const dx = sample(x + h, y) - sample(x - h, y);
const dy = sample(x, y + h) - sample(x, y - h);
return [dy * FLOW, -dx * FLOW]; // divergence-free: pure swirl
};
for (let i = 0; i < P; i++) {
const [u, v] = curl(px[i], py[i]);
px[i] += (u + vortex.x + scatter.x) * dt * rush;
py[i] += (v + vortex.y + scatter.y) * dt * rush;
// cursor crush: flash teal, kick outward, spring home
if (d2(ptr, i) < R && ptr.speed > MIN) {
flash[i] = 1;
kick(i, ptr, (1 - d2 / R) * ptr.speed * IMPULSE);
}
charge[i] = Math.max(flash[i] *= COOL, trailGlow(px[i], py[i]));
}
// trails: fade pass 4.5% → filaments persist ~25 frames
fade(fbo, 0.045); draw(points, ADDITIVE); composite(fbo, screen);
// StreakField — signal simulation
const GRID = 128; // flow potential lattice
let phase = 0; // A→B morph, ~14s per epoch
const curl = (x, y) => {
const dx = sample(x + h, y) - sample(x - h, y);
const dy = sample(x, y + h) - sample(x, y - h);
return [dy * FLOW, -dx * FLOW]; // divergence-free: pure swirl
};
for (let i = 0; i < P; i++) {
const [u, v] = curl(px[i], py[i]);
px[i] += (u + vortex.x + scatter.x) * dt * rush;
py[i] += (v + vortex.y + scatter.y) * dt * rush;
// cursor crush: flash teal, kick outward, spring home
if (d2(ptr, i) < R && ptr.speed > MIN) {
flash[i] = 1;
kick(i, ptr, (1 - d2 / R) * ptr.speed * IMPULSE);
}
charge[i] = Math.max(flash[i] *= COOL, trailGlow(px[i], py[i]));
}
// trails: fade pass 4.5% → filaments persist ~25 frames
fade(fbo, 0.045); draw(points, ADDITIVE); composite(fbo, screen);
// StreakField — signal simulation
const GRID = 128; // flow potential lattice
let phase = 0; // A→B morph, ~14s per epoch
const curl = (x, y) => {
const dx = sample(x + h, y) - sample(x - h, y);
const dy = sample(x, y + h) - sample(x, y - h);
return [dy * FLOW, -dx * FLOW]; // divergence-free: pure swirl
};
for (let i = 0; i < P; i++) {
const [u, v] = curl(px[i], py[i]);
px[i] += (u + vortex.x + scatter.x) * dt * rush;
py[i] += (v + vortex.y + scatter.y) * dt * rush;
// cursor crush: flash teal, kick outward, spring home
if (d2(ptr, i) < R && ptr.speed > MIN) {
flash[i] = 1;
kick(i, ptr, (1 - d2 / R) * ptr.speed * IMPULSE);
}
charge[i] = Math.max(flash[i] *= COOL, trailGlow(px[i], py[i]));
}
// trails: fade pass 4.5% → filaments persist ~25 frames
fade(fbo, 0.045); draw(points, ADDITIVE); composite(fbo, screen);
// StreakField — signal simulation
const GRID = 128; // flow potential lattice
let phase = 0; // A→B morph, ~14s per epoch
const curl = (x, y) => {
const dx = sample(x + h, y) - sample(x - h, y);
const dy = sample(x, y + h) - sample(x, y - h);
return [dy * FLOW, -dx * FLOW]; // divergence-free: pure swirl
};
for (let i = 0; i < P; i++) {
const [u, v] = curl(px[i], py[i]);
px[i] += (u + vortex.x + scatter.x) * dt * rush;
py[i] += (v + vortex.y + scatter.y) * dt * rush;
// cursor crush: flash teal, kick outward, spring home
if (d2(ptr, i) < R && ptr.speed > MIN) {
flash[i] = 1;
kick(i, ptr, (1 - d2 / R) * ptr.speed * IMPULSE);
}
charge[i] = Math.max(flash[i] *= COOL, trailGlow(px[i], py[i]));
}
// trails: fade pass 4.5% → filaments persist ~25 frames
fade(fbo, 0.045); draw(points, ADDITIVE); composite(fbo, screen);
VM
2026
Commitfolio Razvio sam Commitfolio kao full-stack web aplikaciju koja automatski generira profesionalne portfolio web stranice analizirajući GitHub commit povijest i podatke repozitorija developera. Izgradio sam backend API za dohvaćanje i obradu Git podataka, parsiranje detalja projekta i dinamično generiranje portfolio sadržaja, dok sam stvorio responzivno frontend sučelje koje omogućuje korisnicima prilagođavanje generiranih portfolia prije objave. Implementirao sam kompletan korisnički tok od GitHub autentifikacije preko generiranja portfolia do konačnog izvoza, pružajući alat koji pretvara sirovu razvojnu aktivnost u uglađene profesionalne izloge.
Zadatak
Mnogi profesionalci se bore s održavanjem uvida u svoje tekuće obveze dok istovremeno trebaju profesionalno prezentirati svoj rad potencijalnim klijentima. Identificirao sam potrebu za jedinstvenim rješenjem koje može poslužiti i za upravljanje osobnim projektima i za profesionalne izložbene svrhe.
01
Predanost bez odgovornosti propada. Mnogi profesionalci se bore s održavanjem uvida u svoje tekuće obveze dok istovremeno trebaju profesionalno prezentirati svoj rad potencijalnim klijentima. Identificirao sam potrebu za jedinstvenim rješenjem koje može poslužiti i za upravljanje osobnim projektima i za profesionalne izložbene svrhe.
02
Praćenje portfolia susreće društveni dokaz. Arhitekturao sam sustav s dvostrukim sučeljem s privatnom kontrolnom pločom za praćenje predanosti i javno usmjerenim portfolio prikazom. Implementirao sam praćenje napretka u stvarnom vremenu, automatska ažuriranja statusa i prilagodljive predloške prezentacije kako bih premostio jaz između osobne produktivnosti i profesionalne prezentacije.
03
Izgradnja povjerenja kroz transparentnost. Slijedio sam agilan razvojni pristup, počevši s istraživanjem korisnika i wireframingom prije prelaska na full-stack razvoj. Dizajnirao sam shemu baze podataka za podršku i privatnih podataka projekta i javnog portfolio sadržaja, zatim izgradio responzivna sučelja koja mogu besprijekorno prijeći između načina upravljanja i prezentacije.
04
Djela govore glasnije od riječi. Aplikacija je uspješno unaprijedila moj vlastiti tok rada upravljanja projektima dok je pružila profesionalnu platformu izloga koja se prilagođava različitim potrebama klijenata. Stekao sam dragocjeno iskustvo u izgradnji aplikacija dvostruke namjene i naučio kako balansirati složenost značajki s korisničkim iskustvom kroz različite slučajeve upotrebe.
Do Not Touch