body::before { content: ""; position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; pointer-events: none; background: repeating-radial-gradient(circle at 0 0, rgba(255,255,255,0.02) 0, rgba(0,0,0,0.02) 1px); opacity: 0.1; z-index: 9999; mix-blend-mode: overlay; animation: noiseMove 1s infinite; } @keyframes noiseMove { 0% { transform: translate(0,0); } 100% { transform: translate(-1%, 1%); } }

Wetter.de

Wetter.de

Wetter.de

I led animation for a mascot-driven campaign that turned wetter.de forecasts from pure data into character, making daily weather feel human and playful.

Role: Motion Lead

Forecasts with personality

Forecasts with personality

Wetter.de is one of Germany’s top weather platforms.
I helped reimagine weather from data to character by leading animation for a mascot-driven campaign that made daily forecasts feel human and playful.

Delivered two 30-second films that introduced a cast of weather personalities and a light, narrative tone.

“Einsatzorte”

“Einsatzorte”

“Monatsbester”

“Monatsbester”

Image
Image
Image
Image
Image
Image
Image

What it sparked

What it sparked

• Shifted Wetter.de from utilitarian to personable, strengthening brand recall and likability in a crowded category.


• Earned trade recognition (Monatsbeste) and PR pickup on RTL channels, sparking social conversation around the new brand voice.


• Established a reusable mascot platform adopted in subsequent communications, signaling enduring engagement value.



Client: Wetter.de

Role: Art Direction, Animation, and Composition.

Art Department at Liga01:

Gabriel Menezes
Johannes Muller
Daniel Rizea 
Renato Klieger

Visualizing a global education for the 21st century

body::before { content: ""; position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; pointer-events: none; background: repeating-radial-gradient(circle at 0 0, rgba(255,255,255,0.02) 0, rgba(0,0,0,0.02) 1px); opacity: 0.1; z-index: 9999; mix-blend-mode: overlay; animation: noiseMove 1s infinite; } @keyframes noiseMove { 0% { transform: translate(0,0); } 100% { transform: translate(-1%, 1%); } }