2025-01-12 · Abdellahi

Building a 24KB Testimonial Widget from Scratch (That gets a 100 Lighthouse Score)

When we set out to build Proofi, we promised ourselves one thing: No bloat.

Most widgets are performance nightmares. They load jQuery, 500KB of React, and make 3 blocking API calls before showing a single star. We took a different path.

The Architecture: Speed by Default

1. Preact vs. React

We love React, but shipping 40KB+ of runtime for a simple widget is overkill. We chose Preact.

  • React: ~42KB (gzipped)
  • Preact: ~3KB (gzipped)

This 90% reduction means our widget parses and executes effectively instantly, even on mobile.

// rollup.config.js
import p from 'rollup-plugin-replace';
// Aliasing React to Preact allows us to use standard libraries
alias({
    entries: [
        { find: 'react', replacement: 'preact/compat' },
        { find: 'react-dom/test-utils', replacement: 'preact/test-utils' },
        { find: 'react-dom', replacement: 'preact/compat' },
    ]
});

2. The "Zero-Fetch" Trick

The biggest performance killer is network latency. Standard Widget:

  1. Load Script -> 2. Execute Script -> 3. Fetch Data (Wait 500ms) -> 4. Render. Result: Layout Shift (CLS) and a flash of empty space.

Our Widget:

  1. Server injects data into window.__JTS_DATA__ -> 2. Script loads -> 3. Render immediately. Result: 0ms Time to Interactive.
// widget.jsx
// We check for pre-injected data before making any API calls
const initialData = window[`__JTS_WIDGET_${id}`] || {};
const [reviews, setReviews] = useState(initialData.reviews || []);

3. Scoping CSS without Shadow DOM

Shadow DOM is great for isolation, but terrible for customization. We wanted our widget to inherit some of your site's typography while protecting our layout. We used a strategy of Aggressive Namespacing and all: unset resets on our root containers.

The Results

  • Bundle Size: 24KB (Total)
  • Lighthouse Score: 100/100
  • Cumulative Layout Shift (CLS): 0.000

Why Engineering Matters

We didn't optimize just for fun. We optimized because conversion drops by 4.42% for every second of load time. Your social proof shouldn't slow down your sales.

Ready to upgrade? Get Proofi for free