Frontend Lead April 9, 2026

Salesforce: AI-Enhanced Scrolly-Telling Experience

When Salesforce’s editorial team wanted to experiment with a new way to publish long-form content—one that didn’t just tell a story but guided readers through it—our team at Fueled stepped in.

The goal was to make dense, technical articles feel alive. To give them motion, rhythm, and a sense of unfolding. My role was to lead the frontend team through creating an interactive “scrolly-telling” post template that could support AI enhancements, video, and animation—while staying lightweight and editor-friendly.


Main Challenges & Constraints

Salesforce’s designs were visually bold but technically demanding. Each section needed to scroll “over” the previous, with subtle parallax and video backgrounds—all inside the limitations of WordPress’s block editor.

We had to balance:

  • Editorial flexibility: Editors needed to reuse the template across different story types.
  • Performance: Each post might include multiple videos, carousels, and AI components.
  • Accessibility: The experience had to meet contrast and motion-reduction standards.

On top of that, the “garage door” animation concept—the sections sliding over one another—clashed with the site’s existing table of contents logic. It was a puzzle of layering, scrolling, and DOM offsets.


Approach & Decision-Making — How IT Was Solved

Because I joined partway through the project, my first move was a deep dive: reviewing design intentions, auditing existing blocks, and mapping technical feasibility. From there, I led a small team of three frontend engineers (including myself) and one backend engineer.

Each sprint, I assigned tickets based on strengths, oversaw code reviews, and coordinated QA and user acceptance testing. Every commit went through myself, a backend review and staging before merge, ensuring the build remained stable across environments.

The “garage door” effect, which was originally brittle, became a hybrid approach using CSS sticking order and controlled parallax to maintain Table of Contents anchor behavior while preserving depth and flow.

In the end, the exciting scrolling features were just standard CSS:

.parallax-container:has(.wp-block-cover) {
  top: calc(1.4rem + var(--wp-admin--admin-bar--height, 0px));
  position: sticky;
}
CSS

For performance, I built a custom FFMPEG preprocessing script that batch-optimized videos. It performs a two-pass VP9 WebM encode at 1080p and 24 fps, using constant-quality mode (CRF 35), removes audio, and scales the video to the target resolution.

I put this in a .sh script that could be executed in a directory full of assets and output the proper files that could then be modified for length or cropped appropriately.

Here is a snippet of the important part of that .sh

if ffmpeg -i "$file" 
  \ -c:v libvpx-vp9 
  \ -crf 35 
  \ -b:v 0 
  \ -pass 1 
  \ -an 
  \ -vf scale=1920:1080 
  \ -r 24 
  \ -f webm 
  \ /dev/null 
  \ -y -loglevel error && 
  \ ffmpeg -i "$file" 
  \ -c:v libvpx-vp9 
  \ -crf 35 
  \ -b:v 0 
  \ -pass 2 
  \ -an 
  \ -vf scale=1920:1080 
  \ -r 24 
  \ "$output" 
  \ -y -loglevel error; 
then 

# Get file sizes for comparison 
original_size=$(du -h "$file" | cut -f1) 
compressed_size=$(du -h "$output" | cut -f1) 

echo "✅ Success: $(basename "$file")" 

echo " Original: $original_size → Compressed: $compressed_size"

Using video.js, each clip loads only when in view via Intersection Observer, pausing when scrolled away to reduce CPU and bandwidth load.

Simplified Example

const player = videojs("my-video");

const observer = new IntersectionObserver(
  (entries) => {
    entries.forEach((entry) => {
      if (entry.isIntersecting) {
        player.play();
      } else {
        player.pause();
      }
    });
  },
    {
      threshold: 0.25, // Play when at least 25% visible
    }
);

Experience & Design Layer — How It Felt

The experience unfolds like a living editorial: sections glide into view, videos breathe with motion, and readers can trigger AI summaries or listen to the full post with a generated audio narration.

  • AI Summary Tool: Summarizes sections on-demand, typing out text with subtle animations.
  • ElevenLabs Integration: Offers natural-sounding read-backs for long articles.
  • Table of Contents: Lets users jump smoothly between sections via scroll-to behavior.
  • Parallax Containers: Add depth without overwhelming motion-sensitive users.
  • Loading States: Soft pulses and typewriter animations make waiting feel intentional.

A simple JavaScript intersection observer was added to ensure we were displaying the AI Summary for the section the user is currently viewing on the screen:

document.addEventListener("DOMContentLoaded", () => {
  const containers = document.querySelectorAll(".parallax-container");

  const observer = new IntersectionObserver((entries) => {
    entries.forEach((entry) => {
      entry.target.classList.toggle("is-active", entry.isIntersecting);
    });
  }, {
    threshold: 0.25 // Adjustable sensitivity: (0.25 = 25% visible)
  });

  containers.forEach((el) => observer.observe(el));
});


We can now utilize that “is-active” class to trigger all the AI synopsis content in an extremely simple way:

document.addEventListener("DOMContentLoaded", () => {
  const button = document.querySelector(".trigger-ai");
  
  button.addEventListener("click", () => {
    const activeSection = document.querySelector(".parallax-container.is-active");
    if (!activeSection) {
      // Fallback function if no active section is found
      activeSection = checkForDefaultSection(); 
      
      if (!activeSection) return;
    }

    const synopsis = activeSection.querySelector(".ai-synopsis");
    if (!synopsis) return;

    // Step 1: Display loading animation for X seconds
    synopsis.style.display = "block";
    synopsis.textContent = getLoadingAnimation();

    setTimeout(() => {
      // Step 2: Replace loading with typing animation
      const text = "Generating AI synopsis..."; // Replace with actual AI-generated text
      synopsis.textContent = "";

      let i = 0;
      const typeInterval = setInterval(() => {
        synopsis.textContent += text[i];
        i++;
        if (i >= text.length) clearInterval(typeInterval);
      }, 50); // typing speed in ms
    }, 2000); // loading time in ms
  });
});

Accessibility guided every design decision: reduced-motion users see simplified transitions, ARIA roles describe expand/collapse actions, and keyboard users can navigate the TOC seamlessly.


Outcome & Impact — What It Achieved

The result was a performant, reusable post template that turned Salesforce’s blog into a playground for immersive editorial experiences.

The pages loaded smoothly despite their media weight, and Salesforce’s team reported satisfaction with how easily they could adapt the template for different story types—from event coverage to AI explainers.

Delivered on time and without regression issues, the project set a precedent internally for how we approach content experiences that blend editorial design and frontend storytelling.


Learnings & Forward Thread — How It Shaped Future Work

This project reinforced something I now carry into every build: complex experiences don’t need complex authoring tools—just thoughtful architecture.

I learned the value of preprocessing media outside the CMS pipeline, how memoization and caching can backfire when tokens matter, and how “experience” is as much about restraint as animation.

If I were to do it again, I’d explore a headless setup for even cleaner decoupling between storytelling logic and editorial workflow. But as it stands, this build captured what I love most about frontend engineering—bridging creativity and performance in service of narrative.