A static Figma design turned into a video showcase the client manages himself: a Bunny Stream library run on one ID per video, controlled playback and a canvas cursor effect.
AdFluent, an Amsterdam performance-marketing agency for DTC e-commerce brands
Role
Webflow developer · motion and video setupagency project via Upwork; static Figma design supplied
Stack
Webflow CMS
Webflow GSAP interactions
Canvas + JavaScript
Bunny Stream
Timeline
Launched September 2026
116
ad videos
8
video case studies
1
ID to add a new video
0
YouTube or Vimeo embeds
Overview
AdFluent creates and runs paid social ads for DTC brands, so its portfolio is video: more than a hundred ads and eight case studies. I received a static Figma design with no motion and no plan for hosting the videos, and built the full site in Webflow. Before development started I proposed the video setup, and I defined all of the site’s motion.
My role
Built the site in Webflow from a static Figma design
Recommended Bunny Stream for video hosting and built the video system around it
Structured the CMS, including format filters, so the client can add and replace videos himself
Built the cursor effect on canvas, with a separate mobile version
Defined and built all motion
Recorded a personalised walkthrough tutorial for the handoff
Challenges & solutions
01
116 ad videos, no YouTube or Vimeo players
Nearly every item on the site is a video. YouTube or Vimeo embeds would have put another platform’s branding and player on every card of an agency’s own portfolio. I raised this with the client before development started and proposed Bunny Stream, which I had used on an earlier project. The client agreed. Each player and its controls are configured in Bunny, so every ad looks and behaves the same across the site.
A library page shows many ads at once, so I added logic that pauses any playing video when another one starts. Visitors can sample ads freely without two soundtracks playing over each other.
adfluent.nl
Starting a second ad pauses the first02
A video library the client runs himself
Videos are managed through the CMS: an Ads collection and a Case Studies collection, plus utility collections for logos, testimonials and FAQs. Each item stores only its Bunny video ID, and the template builds the player from it. Adding an ad means uploading it to Bunny and pasting one ID into Webflow. Each ad also carries a format category, which drives the filters in the creative library, so new ads land in the right place automatically.
adfluent.nl
The creative library: each tile is a Bunny Stream player built from one video ID, filtered by format
adfluent.nl
One ad in the CMS: a Bunny video ID and a format category are all it needs
I walked the client through the workflow and recorded a personalised tutorial covering it. Since launch he has kept the library up to date on his own.
03
Cursor-following squares on canvas
The client sent a reference site with squares that follow the cursor. I studied how the effect worked, then wrote my own version with canvas and JavaScript, using ChatGPT to iterate on it over several rounds. Squares follow the cursor, light up in AdFluent’s brand colour and fade away. Most of the work went into fitting the effect to the design and making it hold up across screen sizes.
adfluent.nl
Squares trail the cursor, light up in the brand colour and fade
On mobile there’s no cursor to follow, so the canvas is switched off and replaced with animated SVG squares in the corners. They keep the visual idea on every screen.
adfluent.nl
On mobile, animated SVG squares take the canvas’s place04
Motion with a light touch
Everything else is restrained micro-interaction: a staggered header entrance, staggered scroll reveals and card hovers, all built with Webflow’s native GSAP interactions. Every animation respects the reduced-motion preference.
adfluent.nl
Staggered entrance, scroll reveals and card hovers
Results
Before dev
Bunny Stream recommended and adopted before the build started, so no ad shows another platform’s branding
1 ID
Adding an ad takes one upload and one pasted ID, and its format category files it in the right filter
Self-serve
The client has kept the library up to date on his own since launch