Autumn is here!

| In Tech
| 9 minute read |by Constantin Gonzalez
A detail section of this blog’s header image featuring a cartoon illustration black and tan dog with a red bandana on a blue background with falling autumn leaves, rain, sound waves, and letters spelling "KING" on the left side of the image.

Quite literally: this blog is now officially in autumn mode! 🍂

During our summer vacation, while watching over our dog Elvis, I spent some time doing recreational coding on the balcony of our vacation home in Sottomarina, Italy. The result is a seasonal bit of JavaScript/SVG animation for this blog’s header, which you can now enjoy on the main page, constantin.glez.de. But only during the autumn months, of course!

What started as a simple idea to add variety to my header turned into a 903-line journey of learning physics, mastering SVG patterns, and discovering just how much fun coding can be when there are no deadlines or requirements—just curiosity and Claude as my sparring partner. 🎯

Here’s what I learned along the way:

The joy of vacation coding 🏖️

Let me set the scene first: picture a sunny balcony in Italy, a laptop, a chilled-out dog named Elvis, and absolutely zero pressure to deliver anything by any deadline. This is what I call “recreational coding”—and if you’ve never experienced it, you’re missing out on one of programming’s greatest pleasures.

I love doing pet projects because coding for fun feels completely different from coding for work. And you learn so much more! When it’s under your control, it becomes pure freedom of expression and exploration. No compromises, no stakeholder requirements, just “what if I could make leaves fall realistically on my website?” 🤔

The setup was ideal: I’d spend a few hours each day on the balcony while the family was at the beach, Elvis chilling beside me (great company, by the way—he’s very supportive of my coding endeavors). When my wife returned, I’d head to the beach to read and recharge. It’s amazing how productive you can be when you’re genuinely excited about what you’re building.

From simple idea to seasonal system 🌟

After refactoring my blog’s header image, I wanted to add some extra variety that would evolve over time. The seasonal animation idea emerged from thinking about sustainable ways to keep the header interesting—something that changes regularly but doesn’t require constant maintenance.

Four seasons seem like a great balance: enough variety to stay fresh, but only requiring updates every three months. Once I implement all four seasons, I can always add more detail or split seasons into phases. It’s like building an extensible easter-egg system for my blog! 🥚

The autumn header now features:

  • Three kinds of falling leaves in different sizes and 3D-ish distances from the viewer, implemented in layers with size, motion, and blurring adjustments based on depth
  • A physics simulation engine featuring wind, wind gusts, momentum, gravity, leaf rotation in fake 3D, and friction (because why settle for basic when you can have realistic? 💨)
  • Rain effects implemented as SVG patterns for efficiency, again in 3D-ish layers
  • Interactive keyboard controls for toggling wind (“W”), wind gusts (“G”), and rain (“R”), when your mouse is over the header
  • A heads-up display (HUD) that you can toggle using “H” (mouse over header still), featuring help text, status updates, and crude performance metrics
  • Performance optimizations for when the header isn’t visible (because nobody wants their battery drained by invisible animations)
  • Future-ready scaffolding for winter, spring, and summer seasons

As always, you start with something small, then keep adding idea after idea until it becomes quite a big-ish thing—903 lines of JavaScript code, in this case. You can check it out in your browser’s Developer Console, or view the complete code in this GitHub Gist: autumn.js.

Learning with Claude: Your friendly coding companion 🤖

Here’s where things get interesting. I used Claude as my learning accelerator throughout this project, and it completely changed how I approach picking up new skills. Instead of spending hours hunting through Stack Overflow or documentation, I had a knowledgeable sparring partner who could answer questions like:

  • “How can I animate an SVG path element smoothly?”
  • “How does scaling and blurring elements work for depth effects?”
  • “Do these momentum formulas look right for realistic leaf physics?”

But here’s the key thing: I didn’t just copy-paste Claude’s suggestions. Every piece of code became a learning opportunity. I’d go through each line, understand the logic, then often push back with questions like “Why do we need this variable?” or “Isn’t this approach unnecessarily complex?” This back-and-forth refinement process felt like pair programming with a patient, knowledgeable colleague who never gets frustrated with your questions.

Sometimes Claude’s initial solutions were overly complex, so I’d challenge them, gradually optimizing and simplifying until we found elegant approaches. This collaborative debugging and refinement process taught me more about JavaScript and SVG than months of solo coding, or textbook study probably would have.

If you’re not using AI as a learning partner yet, you’re missing out on a game-changing approach to skill development! 🚀

Technical deep dives: what I discovered 🔧

SVG: more powerful than I expected

Initially, I thought SVG would just be good for simple 2D graphics. Boy, was I wrong! SVG turned out to be a surprisingly powerful rendering engine with features that rival more complex graphics systems:

Paths are incredibly versatile. A handful of quadratic Bézier splines can create surprisingly complex shapes. I used tools like SvgPathEditor to design three different leaf types that look good enough for my standards. Here’s the code that defines them:

const leafPaths = [
  "M 0 0.21 Q 0.09 0.48 0.36 0.5 Q 0.35 0.3 0.23 0.21 Q 0.47 0.11 0.54 -0.14 Q 0.29 -0.11 0.15 0.04 Q 0.17 -0.26 0 -0.5 Q -0.17 -0.26 -0.15 0.04 Q -0.29 -0.11 -0.54 -0.14 Q -0.47 0.11 -0.23 0.21 Q -0.35 0.3 -0.36 0.5 Q -0.09 0.48 0 0.21 Q 0.01 0.35 0.02 0.5 Q 0.015 0.5 0.01 0.5 Q -0.02 0.35 0 0.21", // Acorn-ish
  "M 0 0.33 Q -0.42 0.07 0 -0.5 Q 0.42 0.07 0 0.33 M 0.02 0.5 Q -0.02 0.33 0 -0.5", // Oak-ish
  "M 0 -0.5 Q -0.14 -0.5 -0.14 -0.25 Q -0.42 -0.32 -0.17 -0.07 Q -0.45 -0.09 -0.16 0.19 Q -0.34 0.31 0 0.4 Q 0.34 0.31 0.17 0.19 Q 0.45 -0.09 0.17 -0.07 Q 0.42 -0.32 0.14 -0.25 Q 0.14 -0.5 0 -0.5 Q -0.03 0.5 0.03 0.5", // Poplar-ish leaf
];

(You can copy-paste these strings into SvgPathEditor to see them in action. I’m not a botanist, so the naming might be botanically incorrect—but they do look like leaves! 🍃)

Efficient rain through patterns. The rain uses layers of pre-rendered <pattern> elements that fill <rect> elements covering the whole banner. Patterns can be transformed to create smooth motion effects without individual raindrop management—much more efficient than managing hundreds of individual rain elements.

GPU-accelerated transforms. CSS transforms on SVG elements (rotation, scale, blur) are handled by the device’s GPU, making complex effects surprisingly performant. This is why the leaves can rotate in 3D space without killing the frame rate.

Coordinate system flexibility. Understanding viewBox, screen coordinates, and pattern coordinates takes some mental effort, but they offer powerful techniques for creating resolution-independent animations that work across different screen sizes and pixel densities.

Scene graph advantages. Since SVG integrates with the DOM and supports <g> grouping elements, implementing z-depth layers becomes straightforward. Each depth layer gets its own group with appropriate transforms and effects.

Physics simulation: making things feel real

Getting physics right turned out to be quite complex, but absolutely worth it for the realistic movement. I started with basic x += speed * deltaTime for the leaves, but that looked too mechanical and fake.

Here’s what made the difference:

Momentum-based movement creates smooth acceleration and deceleration that feels natural. Instead of instant speed changes, leaves gradually respond to forces:

applyMomentum(deltaTime) {
  const speedFactor = 1 + (1 - this.zFactor) * zFactorSpread;
  this.x += this.xMomentum * deltaTime * speedFactor;
  this.y += this.yMomentum * deltaTime * speedFactor;
  this.rotateX = (this.rotateX + this.rotateMomentumX * deltaTime) % 360;
  this.rotateY = (this.rotateY + this.rotateMomentumY * deltaTime) % 360;
  this.rotateZ = (this.rotateZ + this.rotateMomentumZ * deltaTime) % 360;
}

applyGravity(deltaTime) {
  this.yMomentum += deltaTime * gravity;
}

applyFriction(deltaTime) {
  const frictionFactor = Math.pow(1 - friction, deltaTime);
  this.xMomentum *= frictionFactor;
  this.yMomentum *= frictionFactor;
  this.rotateMomentumX *= frictionFactor;
  this.rotateMomentumY *= frictionFactor;
  this.rotateMomentumZ *= frictionFactor;
}

Surface area affects wind resistance. I wanted leaves to rotate based on wind, which led me to implement Math.cos(angleX) * Math.cos(angleY) calculations for surface area effects, plus Math.sin(2 * angle) for lift efficiency. The result? Some leaves actually rise against gravity when the wind conditions are just right—just like in nature! 🌬️

Frame-rate independence through deltaTime. You never know what device your code will run on, so assuming consistent frame rates is dangerous. All animation calculations use deltaTime (time since last frame) to ensure smooth movement regardless of whether you’re getting 30fps or 120fps.

User experience: progressive discovery

What started as a simple animation evolved into keyboard controls, which raised the question of discoverability. How do users learn about these hidden features without overwhelming them?

The solution was progressive disclosure: the interface stays completely out of the way initially, but gradually reveals itself to interested users. A subtle hint appears when you hover over the header, suggesting the HUD toggle. Once you discover the HUD, you learn about all the other controls. It’s like an onion of features—each layer reveals more depth for those who want to explore. 🧅

setTimeout gotchas and animation loops. I learned that chaining setTimeout calls for periodic animations can be tricky—any missed call breaks the chain. The better approach is keeping the chain running continuously and filtering actions inside it, rather than trying to manage the chain itself. This makes pause/resume functionality much more reliable.

The learning journey continues 📚

The best lessons weren’t really about JavaScript or SVG—they were about the trade-offs that every developer faces:

  • “Good enough” vs. “perfect” - Knowing when to stop refining and ship something people can enjoy
  • Balancing complexity against diminishing returns - Each additional feature adds value, but at an increasing cost
  • Keeping user experience above everything else - All the fancy physics don’t matter if the animation annoys people

As always, the process is the goal, not just the result. I’m thrilled with my new header feature, but I’m most excited about the hours spent tweaking, experimenting, and learning alongside Claude. The collaborative debugging sessions, the “what if we tried…” moments, the gradual refinement of ideas—that’s where the real value lies.

And of course, I’m never really done. I could spend countless more hours adding features: leaf pooling for better performance, rain that follows wind intensity, pumpkins and other autumn elements, more sophisticated physics… But that’s the beauty of pet projects—they grow organically based on your curiosity and available time. 🎨

Your turn! 🚀

If this post has inspired you even a little bit, here’s my challenge: pick something small on your own website, app, or project that could use a creative touch. Start simple, then let your curiosity drive the complexity. And definitely try using Claude (or your AI assistant of choice) as a learning accelerator—ask questions, challenge suggestions, and turn every code snippet into a learning opportunity.

The combination of recreational coding, AI-assisted learning, and creative freedom is incredibly powerful. You might just surprise yourself with what you can build when there are no constraints except your own imagination.

I’m looking forward to building the next seasonal animation for winter! ❄️ Who knows what physics challenges snow and ice will bring to the party?

What creative projects are you working on? I’d love to hear about your own recreational coding adventures! 💬