DEV Community

Cover image for I built a small ambient animation extension for the VS Code Explorer sidebar
Mh.Farzin
Mh.Farzin

Posted on

I built a small ambient animation extension for the VS Code Explorer sidebar

I spend a lot of time in VS Code. At some point I realized the Explorer sidebar felt a bit empty and static, so I decided to build something small that could make it feel a little more alive β€” without being distracting.

The result is VS Code Scene, a lightweight extension that adds a subtle animated scene to the bottom of the Explorer panel.

🎬 Preview

✈️ SkyPilot

SkyPilot

🐠 Aquarium

Aquarium

🌟 Stars

Stars

What it does

It currently includes three scenes:

  • SkyPilot β€” colorful airplanes (blue, green, red, and yellow) flying through soft, procedurally generated clouds with spinning propellers
  • Aquarium β€” six cartoon fish swimming around with animated wagging tails, blowing bubbles, with a tiled background and gentle shimmering caustics
  • Stars β€” a peaceful starfield with 115 twinkling stars (90 tiny background stars + 25 vivid five-pointed stars) slowly drifting upward

You can switch between them instantly from the status-bar icon (a color wheel in the bottom-right) or the command palette.

How to use

  1. Open the Explorer view β€” the Scene panel appears at the bottom automatically.
  2. Use the Command Palette (Ctrl+Shift+P) or click the color-wheel icon in the status bar to switch scenes.
Command Description
VS Code Scene: Start Opens the Explorer and shows the Scene panel
VS Code Scene: Stop Closes the Explorer and hides the Scene
VS Code Scene: Select Scene Opens the scene picker

Scenes update live β€” no reload, no restart. The currently active scene is marked with a checkmark in the picker.

Technical approach

Pure Canvas2D, zero dependencies

Everything is rendered with the native Canvas2D API. There are no external rendering libraries β€” no Three.js, no Pixi.js, no WebGL. The webview bundle is very small (~25 KB gzipped), and it's the only JavaScript your editor has to load.

A strict Content Security Policy

The webview runs under a strict CSP with a per-view nonce:

  • default-src 'none' β€” everything not listed is blocked by default
  • script-src / style-src only allow the extension's own inline scripts/styles bearing the nonce
  • img-src allows extension assets plus data: URIs (needed for the Aquarium's sprite-splitting via canvas.toDataURL())

No tracking, no analytics, no external requests β€” ever.

Animations pause when hidden

All animation is driven by the requestAnimationFrame loop, so when the Explorer view is hidden or the window is minimized, the animation automatically pauses β€” keeping resource usage near zero when you're not looking at it.

Timing driven by rAF, not timers

One subtle bug I hit early on: using setTimeout / setInterval for spawn timers inside a screen caused a burst of objects to appear all at once when restoring a minimized window (timers keep firing in the background while rAF is paused). Every spawn/cooldown timer is now driven from update(deltaTime) with an accumulated counter, and each frame's delta is clamped to ~250 ms so a giant frame can never fire queued spawns.

One bundle, no CSP violations

The webpack config forces everything into a single bundle (splitChunks: false + dynamicImportMode: 'eager'). Async chunks would be injected as <script> tags without the CSP nonce and get blocked β€” causing a black screen. Keeping one bundle keeps both the CSP happy and the load fast.

Live scene switching

Scene switching is fully automatic through a chain:

  1. The selectScene command updates the vscode-scene.screen setting.
  2. The host's ScenePanel.ts listens for configuration changes and posts the new scene type to the webview.
  3. The webview disposes the old screen, creates a brand-new canvas element, and instantiates the new screen.

Replacing the whole canvas element guarantees zero leftover renderer state between switches.

Tips for VS Code WebViews

Building this taught me a few WebView-specific gotchas worth sharing:

  • Prefer Canvas2D over WebGL. WebGL support in VS Code WebViews can be limited or unreliable depending on the environment, so pure Canvas2D is the safer and more compatible choice.
  • Assets need webview URIs. A screen can't use a plain filesystem path; every PNG is loaded through window.__ASSETS_BASE_URI__ (the host converts the extension's assets/ folder into a webview URI).
  • Async start() handling. BaseScreen.start() can return void or a Promise; callers must check instanceof Promise before chaining .catch().
  • Guard async loading against disposal. Every screen checks a disposed flag after each await so a screen that's been replaced mid-load never touches the canvas.

Installation

Install it from the VS Code Marketplace:

ext install mh-farzin.vscode-scene
Enter fullscreen mode Exit fullscreen mode

Or search VS Code Scene in the Extensions view (Ctrl+Shift+X).

Why I built it

I mainly built it for myself. I wanted something calm and subtle running in the background while coding β€” just a bit of quiet motion to make the sidebar feel less empty.

The whole thing is free and open source (MIT). A big thank-you to Kenney and Freepik for the game assets and graphics used in the scenes.

Links


I’d love to hear your thoughts:

  • Would you keep something like this enabled while coding?
  • Which scene do you like most?
  • What kind of scene would you want to see next?

Any feedback is welcome β€” even if it’s just β€œnot for me.”

Top comments (0)