Showcase

ML/AI engineer portfolio website, built by MiMo-V2.6-Flash

Hostedvia OpenCodeOpenRouter
Running live in your browserNew tab
Show the code the model wrote
HTML18,385 characters
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="color-scheme" content="dark">
<meta name="description" content="Mira Kovač — Senior Machine Learning Engineer in Berlin. Ranking, fraud detection, and visual search in production.">
<title>Mira Kovač — Senior Machine Learning Engineer</title>
<style>
  /* ---------------------------------------------------------------
     one family, one green, one spacing rhythm (4px micro / 8px macro)
     --------------------------------------------------------------- */
  :root{
    --bg:      #0a0c0b;
    --fg:      #d9dfdb;
    --fg-soft: #aeb8b2;
    --dim:     #79837d;
    --line:    #202622;
    --green:   #00e676;

    --s-1: 4px;   /* micro step   */
    --s-2: 8px;   /* inline gap   */
    --s-3: 16px;  /* block gap    */
    --s-4: 24px;  /* field gap    */
    --s-5: 40px;  /* entry gap    */
    --s-6: 64px;  /* section gap  */
    --s-7: 96px;  /* page gap     */

    --rail: 24px;  /* text inset from the timeline rail */
    --year-col: 8ch;
    --maxw: 54rem;
  }

  *,*::before,*::after{ box-sizing:border-box; }

  html{ -webkit-text-size-adjust:100%; }

  body{
    margin:0;
    background:var(--bg);
    color:var(--fg);
    font-family:ui-monospace, "SF Mono", SFMono-Regular, "JetBrains Mono", "IBM Plex Mono",
                 Menlo, Consolas, "Liberation Mono", monospace;
    font-size:15px;
    line-height:1.65;
    -webkit-font-smoothing:antialiased;
    text-rendering:optimizeLegibility;
    overflow-wrap:break-word;
  }

  #rain{
    position:fixed;
    inset:0;
    width:100%;
    height:100%;
    opacity:.14;
    pointer-events:none;
    z-index:0;
  }

  .wrap{
    position:relative;
    z-index:1;
    max-width:var(--maxw);
    margin:0 auto;
    padding:var(--s-6) var(--s-4) var(--s-7);
  }

  a{
    color:var(--green);
    text-decoration:underline;
    text-decoration-thickness:1px;
    text-underline-offset:3px;
    text-decoration-color:var(--line);
    transition:text-decoration-color .15s, color .15s;
  }
  a:hover, a:focus-visible{ text-decoration-color:var(--green); }
  a:focus-visible{ outline:1px solid var(--green); outline-offset:3px; }

  h1,h2,h3,p,ul,ol,figure{ margin:0; }
  ul,ol{ padding:0; list-style:none; }

  /* ------------------------------------------------ header ------ */
  .prompt{ font-size:13px; color:var(--dim); }
  .prompt .user{ color:var(--green); }

  .cursor{
    display:inline-block;
    width:.62ch;
    height:1em;
    background:var(--green);
    vertical-align:-.14em;
    margin-left:.35ch;
    animation:blink 1.1s steps(1) infinite;
  }
  @keyframes blink{ 0%,50%{opacity:1} 50.01%,100%{opacity:0} }

  header .name{
    margin-top:var(--s-3);
    font-size:clamp(30px, 7vw, 44px);
    line-height:1.1;
    font-weight:600;
    letter-spacing:-.01em;
    color:#fff;
  }

  header .role{
    margin-top:var(--s-2);
    font-size:15px;
    color:var(--green);
  }
  header .role .sep{ color:var(--line); padding:0 var(--s-2); }

  header .lede{
    margin-top:var(--s-4);
    max-width:64ch;
    color:var(--fg-soft);
  }
  header .lede strong{ color:var(--fg); font-weight:500; }

  .contact{
    margin-top:var(--s-4);
    display:flex;
    flex-wrap:wrap;
    gap:var(--s-2) var(--s-4);
    font-size:13px;
    border-top:1px solid var(--line);
    border-bottom:1px solid var(--line);
    padding:var(--s-3) 0;
  }
  .contact .k{ color:var(--dim); }
  .contact .v{ color:var(--fg); }
  .contact a{ color:var(--green); }

  /* ------------------------------------------- section head ----- */
  .section{ margin-top:var(--s-6); }
  .sec-head{
    display:flex;
    align-items:center;
    gap:var(--s-3);
    margin-bottom:var(--s-4);
  }
  .sec-head .id{ color:var(--green); font-size:12px; letter-spacing:.14em; }
  .sec-head h2{
    font-size:12px;
    font-weight:500;
    letter-spacing:.14em;
    text-transform:uppercase;
    color:var(--fg-soft);
  }
  .sec-head .rule{ flex:1; height:1px; background:var(--line); }

  /* ------------------------------------------------- skills ----- */
  .chips{ display:flex; flex-wrap:wrap; gap:var(--s-2); }
  .chip{
    border:1px solid var(--line);
    padding:7px var(--s-3);
    font-size:13px;
    color:var(--fg-soft);
    transition:border-color .15s, color .15s;
  }
  .chip:hover{ border-color:var(--green); color:var(--green); }

  /* ---------------------------------------------- experience ---- */
  .timeline{ display:flex; flex-direction:column; gap:var(--s-5); }

  .tl-entry{
    position:relative;
    display:grid;
    grid-template-columns:var(--year-col) minmax(0,1fr);
    column-gap:var(--s-4);
    align-items:start;
  }
  .tl-year{
    text-align:right;
    padding-top:4px;
    font-size:13px;
    color:var(--green);
    letter-spacing:.04em;
    line-height:1.4;
  }
  .tl-year .to{ display:block; color:var(--dim); font-size:12px; }

  .tl-body{
    position:relative;
    padding-left:var(--rail);
    border-left:1px solid var(--line);
  }
  /* rail continues through the gap between entries */
  .tl-body::after{
    content:"";
    position:absolute;
    left:-1px;
    top:100%;
    bottom:calc(-1 * var(--s-5));
    width:1px;
    background:var(--line);
  }
  .tl-entry:last-child .tl-body::after{ display:none; }
  /* marker on the rail */
  .tl-body::before{
    content:"";
    position:absolute;
    left:-4px;
    top:9px;
    width:7px;
    height:7px;
    background:var(--green);
  }

  .role{ font-size:16px; font-weight:600; color:#fff; line-height:1.35; }
  .org{ margin-top:var(--s-1); font-size:13px; color:var(--dim); }
  .org b{ color:var(--fg-soft); font-weight:500; }

  .bullets{ margin-top:var(--s-3); display:flex; flex-direction:column; gap:12px; }
  .bullets li{ position:relative; padding-left:var(--s-4); color:var(--fg-soft); }
  .bullets li::before{
    content:"›";
    position:absolute;
    left:0;
    top:0;
    color:var(--dim);
  }
  .bullets b{ color:var(--green); font-weight:500; }
  .bullets i{ color:var(--fg); font-style:normal; }

  /* ------------------------------------------------- projects ---- */
  .projects{ display:flex; flex-direction:column; gap:var(--s-3); }
  .project{ display:grid; grid-template-columns:15ch 1fr; gap:var(--s-3); align-items:baseline; }
  .project .cmd{ color:var(--green); font-size:14px; }
  .project .cmd::before{ content:"$ "; color:var(--dim); }
  .project p{ color:var(--fg-soft); font-size:14px; }

  /* ----------------------------------------------- publication ---- */
  .pub{ border:1px solid var(--line); padding:var(--s-4); }
  .pub .year{ font-size:12px; color:var(--green); letter-spacing:.1em; }
  .pub h3{ margin-top:var(--s-2); font-size:15px; font-weight:500; color:#fff; line-height:1.5; }
  .pub .cite{ margin-top:var(--s-2); font-size:13px; color:var(--dim); }

  /* --------------------------------------------------- footer ---- */
  footer{
    margin-top:var(--s-7);
    padding-top:var(--s-3);
    border-top:1px solid var(--line);
    display:flex;
    flex-wrap:wrap;
    justify-content:space-between;
    gap:var(--s-2) var(--s-3);
    font-size:12px;
    color:var(--dim);
  }

  /* ---------------------------------------------- breakpoints ---- */
  @media (max-width:680px){
    :root{ --rail:0px; }
    .wrap{ padding:var(--s-5) var(--s-3) var(--s-6); }

    .tl-entry{
      display:block;
      padding-left:var(--s-4);
      border-left:1px solid var(--line);
    }
    .tl-entry::before{
      content:"";
      position:absolute;
      left:-4px;
      top:6px;
      width:7px;
      height:7px;
      background:var(--green);
    }
    .tl-entry::after{
      content:"";
      position:absolute;
      left:-1px;
      top:100%;
      bottom:calc(-1 * var(--s-5));
      width:1px;
      background:var(--line);
    }
    .tl-entry:last-child::after{ display:none; }

    .tl-year{ text-align:left; display:flex; gap:var(--s-2); align-items:baseline; padding-top:0; }
    .tl-year .to{ display:inline; }
    .tl-body{ padding-left:0; border-left:0; margin-top:var(--s-2); }
    .tl-body::before,.tl-body::after{ display:none; }

    .project{ grid-template-columns:1fr; gap:var(--s-1); }
    .section{ margin-top:var(--s-6); }
  }

  @media (prefers-reduced-motion:reduce){
    *{ animation:none !important; transition:none !important; }
  }

  /* ---------------------------------------------------- print ---- */
  @media print{
    :root{ --bg:#fff; --fg:#111; --fg-soft:#222; --dim:#555; --line:#ccc; --green:#00693a; }
    body{ background:#fff; color:#111; font-size:11pt; }
    #rain{ display:none; }
    .wrap{ max-width:none; padding:0; }
    header .name, .role, .bullets b, .project .cmd, .contact a, .tl-year{ color:#00693a; }
    header .name{ color:#000; }
    .role{ color:#00693a; }
    .role .sep{ color:#ccc; }
    .pub h3, .role{ color:#000; }
    .section{ margin-top:28pt; break-inside:avoid; }
    .tl-entry{ break-inside:avoid; }
    a{ text-decoration:none; }
    .cursor{ display:none; }
  }
</style>
</head>
<body>

<canvas id="rain" aria-hidden="true"></canvas>

<div class="wrap">

  <header>
    <p class="prompt"><span class="user">mira@berlin</span>:~$ whoami<span class="cursor" aria-hidden="true"></span></p>

    <h1 class="name">Mira Kovač</h1>

    <p class="role">Senior Machine Learning Engineer<span class="sep">/</span>Berlin, DE<span class="sep">/</span>open to staff roles</p>

    <p class="lede">
      Eight years of models that <strong>ship and stay shipped</strong>: ranking on Spotify's home
      surface, fraud scoring at N26, visual search at Zalando. I like the unglamorous half of the
      job — feature parity, calibration under label delay, latency budgets, and experiments that
      survive contact with a real control group.
    </p>

    <div class="contact">
      <span><span class="k">email</span> <a href="mailto:mira@kovac.dev">mira@kovac.dev</a></span>
      <span><span class="k">github</span> <a href="https://github.com/mirakovac">github.com/mirakovac</a></span>
      <span><span class="k">linkedin</span> <a href="https://www.linkedin.com/in/mirakovac">in/mirakovac</a></span>
      <span><span class="k">tz</span> <span class="v">CET · remote-friendly</span></span>
    </div>
  </header>

  <main>

    <!-- 01 ---------------------------------------------------------- -->
    <section class="section" aria-labelledby="skills-h">
      <div class="sec-head">
        <span class="id">01</span>
        <h2 id="skills-h">skills</h2>
        <span class="rule"></span>
      </div>
      <ul class="chips">
        <li class="chip">PyTorch</li>
        <li class="chip">Ranking &amp; retrieval</li>
        <li class="chip">Real-time serving — Go, gRPC</li>
        <li class="chip">Distributed training — Ray</li>
        <li class="chip">MLOps — Kubernetes, MLflow</li>
        <li class="chip">CUDA, ONNX, Triton</li>
        <li class="chip">SQL, dbt, Airflow</li>
        <li class="chip">Experiment design &amp; A/B</li>
      </ul>
    </section>

    <!-- 02 ---------------------------------------------------------- -->
    <section class="section" aria-labelledby="exp-h">
      <div class="sec-head">
        <span class="id">02</span>
        <h2 id="exp-h">experience</h2>
        <span class="rule"></span>
      </div>

      <ol class="timeline">

        <li class="tl-entry">
          <div class="tl-year">2022<span class="to">→ present</span></div>
          <div class="tl-body">
            <h3 class="role">Senior Machine Learning Engineer</h3>
            <p class="org"><b>Spotify</b> · Berlin · Home &amp; Discovery ranking</p>
            <ul class="bullets">
              <li>Replaced the nightly batch ranker on Home with two-tower retrieval plus a
                gradient-boosted rerank on streaming features: staleness <b>24h → 12min</b>,
                <b>+4.1%</b> 7-day artist follows across a three-arm A/B.</li>
              <li>Wrote the training/serving feature-parity contract that has caught
                <b>38 schema-drift bugs</b> before deploy — ranking regressions on Home halved
                over two quarters.</li>
              <li>Cut personalization API p99 from <b>45ms → 26ms</b> by distilling the reranker
                into a quantized ONNX graph batched on Triton; mentor four engineers on the
                team.</li>
            </ul>
          </div>
        </li>

        <li class="tl-entry">
          <div class="tl-year">2019<span class="to">→ 2022</span></div>
          <div class="tl-body">
            <h3 class="role">Machine Learning Engineer</h3>
            <p class="org"><b>N26</b> · Berlin · Fraud &amp; Risk</p>
            <ul class="bullets">
              <li>Owned the real-time card-fraud scorer end to end: <b>200+ Flink-computed
                features</b>, p99 under 40ms at ~1.4M transactions/day across six markets.</li>
              <li>Moved fraud detection off static thresholds to cost-sensitive weekly retraining
                on delayed label windows — <b>false declines −31%</b> at flat recall.</li>
              <li>Built the shadow-eval harness and PSI drift alerts that give every model change
                a week of offline evidence before it touches a live control group.</li>
            </ul>
          </div>
        </li>

        <li class="tl-entry">
          <div class="tl-year">2017<span class="to">→ 2019</span></div>
          <div class="tl-body">
            <h3 class="role">Machine Learning Engineer</h3>
            <p class="org"><b>Zalando</b> · Berlin · Search &amp; Visual Relevance</p>
            <ul class="bullets">
              <li>Fine-tuned a ResNet-50 for garment attribute extraction over 40M product images
                (neckline, silhouette, sole): <b>mAP 0.71 → 0.84</b>, feeding search facets and
                the style filter.</li>
              <li>Trained a LambdaMART reranker on click logs that cut the zero-result rate from
                <b>6.2% → 4.8%</b> across DE/AT/CH.</li>
              <li>Moved nightly training onto Airflow + Kubernetes — <b>4h → 51min</b> wall time,
                and it stopped waking anyone up.</li>
            </ul>
          </div>
        </li>

      </ol>
    </section>

    <!-- 03 ---------------------------------------------------------- -->
    <section class="section" aria-labelledby="side-h">
      <div class="sec-head">
        <span class="id">03</span>
        <h2 id="side-h">side projects</h2>
        <span class="rule"></span>
      </div>
      <ul class="projects">
        <li class="project">
          <span class="cmd">ckptdiff</span>
          <p>Prints weight drift and sparsity between two PyTorch checkpoints as an ASCII heatmap — no tracking server required.</p>
        </li>
        <li class="project">
          <span class="cmd">lagwatch</span>
          <p>A 60-line CLI that pages you the moment feature-pipeline Kafka lag crosses your SLO.</p>
        </li>
        <li class="project">
          <span class="cmd">flatline</span>
          <p>Braille-drawn terminal charts that replay any training CSV, so you can watch curves from inside tmux.</p>
        </li>
      </ul>
    </section>

    <!-- 04 ---------------------------------------------------------- -->
    <section class="section" aria-labelledby="pub-h">
      <div class="sec-head">
        <span class="id">04</span>
        <h2 id="pub-h">publication</h2>
        <span class="rule"></span>
      </div>
      <article class="pub">
        <p class="year">2023</p>
        <h3>“Calibrating Under Delay: Label Latency in Real-Time Fraud Detection”</h3>
        <p class="cite">Kovač, M., Hofmann, L., Petrov, A. — Workshop on Deployable ML Systems, NeurIPS 2023</p>
      </article>
    </section>

  </main>

  <footer>
    <span><span style="color:var(--green)">mira@berlin</span>:~$<span class="cursor" aria-hidden="true"></span></span>
    <span>EOF · one font, one green, no trackers</span>
  </footer>

</div>

<script>
(function(){
  var canvas = document.getElementById('rain');
  var ctx = canvas && canvas.getContext && canvas.getContext('2d');
  if(!ctx) return;

  var reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
  var glyphs = '0101001101abcdef01<>[]{}/\\|';
  var cols = 0, drops = [], size = 14, w = 0, h = 0, dpr = 1, raf = 0, visible = true;

  function measure(){
    dpr = Math.min(window.devicePixelRatio || 1, 2);
    w = window.innerWidth;
    h = window.innerHeight;
    canvas.width  = Math.round(w * dpr);
    canvas.height = Math.round(h * dpr);
    ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
    size = w < 680 ? 12 : 14;
    cols = Math.ceil(w / size) + 1;
    drops = [];
    for(var i = 0; i < cols; i++){
      drops[i] = -Math.floor(Math.random() * 70);
    }
  }

  function draw(){
    ctx.clearRect(0, 0, w, h);
    ctx.font = size + 'px ui-monospace, SFMono-Regular, Menlo, Consolas, monospace';
    ctx.textAlign = 'center';
    for(var i = 0; i < cols; i++){
      var trail = 7 + ((i * 7) % 11);
      var headY = drops[i] * size;
      for(var t = 0; t < trail; t++){
        var y = headY - t * size;
        if(y < -size || y > h + size) continue;
        var a = (1 - t / trail);
        a = t === 0 ? a * 0.95 : a * 0.42;
        ctx.fillStyle = 'rgba(0,230,118,' + a.toFixed(3) + ')';
        var ch = glyphs.charAt(((i * 31 + t * 7 + (t === 0 ? Math.floor(Math.random() * 8) : 0)) % glyphs.length));
        ctx.fillText(ch, i * size + size / 2, y);
      }
      drops[i] += 0.32 + ((i % 5) * 0.11);
      if(headY - trail * size > h){
        drops[i] = -Math.floor(Math.random() * 40);
      }
    }
  }

  function loop(){
    draw();
    raf = window.requestAnimationFrame(loop);
  }

  function start(){ if(!raf && visible && !reduce) raf = window.requestAnimationFrame(loop); }
  function stop(){ if(raf){ window.cancelAnimationFrame(raf); raf = 0; } }

  var rt;
  window.addEventListener('resize', function(){
    window.clearTimeout(rt);
    rt = window.setTimeout(function(){ measure(); if(reduce) draw(); }, 150);
  });
  document.addEventListener('visibilitychange', function(){
    visible = document.visibilityState === 'visible';
    if(visible) start(); else stop();
  });

  measure();
  if(reduce) draw(); else start();
})();
</script>

</body>
</html>

Same prompt, other models

8 more
Compare side by side

One email when a new model lands on the board or in the showcase. Unsubscribe anytime.