# Product Showcase Template

3-act structure: Hook → Features → CTA

## Structure (15 seconds / 450 frames at 30fps)

| Scene | Frames | Duration | Content |
|-------|--------|----------|---------|
| Hook | 0-90 | 3s | Bold headline + product hero shot |
| Features | 90-330 | 8s | 2-3 key features with visuals |
| CTA | 330-450 | 4s | Logo + call-to-action + price |

## Implementation

```tsx
import {AbsoluteFill, Sequence, Img, interpolate, useCurrentFrame, staticFile} from 'remotion';

interface ProductShowcaseProps {
  productName: string;
  headline: string;
  features: string[];
  price: string;
  ctaText: string;
  brandColor: string;
  logoUrl: string;
  productImageUrl: string;
}

export const ProductShowcase: React.FC<ProductShowcaseProps> = ({
  productName,
  headline,
  features,
  price,
  ctaText,
  brandColor,
  logoUrl,
  productImageUrl,
}) => {
  return (
    <AbsoluteFill style={{backgroundColor: '#ffffff'}}>
      {/* Scene 1: Hook */}
      <Sequence from={0} durationInFrames={90}>
        <HookScene 
          headline={headline} 
          productImageUrl={productImageUrl}
          brandColor={brandColor}
        />
      </Sequence>

      {/* Scene 2: Features */}
      <Sequence from={90} durationInFrames={240}>
        <FeaturesScene features={features} brandColor={brandColor} />
      </Sequence>

      {/* Scene 3: CTA */}
      <Sequence from={330} durationInFrames={120}>
        <CTAScene 
          logoUrl={logoUrl}
          ctaText={ctaText}
          price={price}
          brandColor={brandColor}
        />
      </Sequence>
    </AbsoluteFill>
  );
};

const HookScene: React.FC<{headline: string; productImageUrl: string; brandColor: string}> = ({
  headline,
  productImageUrl,
  brandColor,
}) => {
  const frame = useCurrentFrame();
  const opacity = interpolate(frame, [0, 20], [0, 1], {extrapolateRight: 'clamp'});
  const scale = interpolate(frame, [0, 30], [0.8, 1], {extrapolateRight: 'clamp'});

  return (
    <AbsoluteFill style={{
      justifyContent: 'center',
      alignItems: 'center',
      padding: 60,
    }}>
      <div style={{
        opacity,
        transform: `scale(${scale})`,
        textAlign: 'center',
      }}>
        <h1 style={{
          fontSize: 72,
          fontWeight: 800,
          color: brandColor,
          marginBottom: 40,
          lineHeight: 1.1,
        }}>
          {headline}
        </h1>
        <Img 
          src={productImageUrl} 
          style={{maxWidth: '80%', maxHeight: 600}}
        />
      </div>
    </AbsoluteFill>
  );
};

const FeaturesScene: React.FC<{features: string[]; brandColor: string}> = ({
  features,
  brandColor,
}) => {
  const frame = useCurrentFrame();

  return (
    <AbsoluteFill style={{
      justifyContent: 'center',
      alignItems: 'center',
      padding: 80,
    }}>
      {features.map((feature, i) => {
        const delay = i * 60; // Stagger each feature by 2 seconds
        const opacity = interpolate(frame - delay, [0, 20], [0, 1], {extrapolateRight: 'clamp'});
        const x = interpolate(frame - delay, [0, 20], [-50, 0], {extrapolateRight: 'clamp'});

        return (
          <div
            key={i}
            style={{
              opacity,
              transform: `translateX(${x}px)`,
              fontSize: 48,
              fontWeight: 600,
              color: brandColor,
              marginBottom: 40,
              display: 'flex',
              alignItems: 'center',
              gap: 20,
            }}
          >
            <span style={{
              width: 40,
              height: 40,
              borderRadius: 20,
              backgroundColor: brandColor,
              color: 'white',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              fontSize: 24,
            }}>
              ✓
            </span>
            {feature}
          </div>
        );
      })}
    </AbsoluteFill>
  );
};

const CTAScene: React.FC<{
  logoUrl: string;
  ctaText: string;
  price: string;
  brandColor: string;
}> = ({logoUrl, ctaText, price, brandColor}) => {
  const frame = useCurrentFrame();
  const scale = interpolate(frame, [0, 15, 20], [0, 1.1, 1], {extrapolateRight: 'clamp'});

  return (
    <AbsoluteFill style={{
      justifyContent: 'center',
      alignItems: 'center',
      backgroundColor: brandColor,
    }}>
      <div style={{
        transform: `scale(${scale})`,
        textAlign: 'center',
      }}>
        <Img src={logoUrl} style={{height: 80, marginBottom: 40}} />
        <div style={{
          fontSize: 64,
          fontWeight: 800,
          color: 'white',
          marginBottom: 20,
        }}>
          {price}
        </div>
        <div style={{
          fontSize: 48,
          fontWeight: 600,
          color: 'white',
          padding: '20px 60px',
          backgroundColor: 'rgba(255,255,255,0.2)',
          borderRadius: 40,
        }}>
          {ctaText}
        </div>
      </div>
    </AbsoluteFill>
  );
};
```

## Composition Registration

```tsx
<Composition
  id="ProductShowcase"
  component={ProductShowcase}
  durationInFrames={450}
  fps={30}
  width={1080}
  height={1920}
  defaultProps={{
    productName: 'Amazing Product',
    headline: 'Transform Your Life',
    features: ['Feature One', 'Feature Two', 'Feature Three'],
    price: '₱999',
    ctaText: 'Shop Now',
    brandColor: '#2563eb',
    logoUrl: staticFile('logo.png'),
    productImageUrl: staticFile('product.png'),
  }}
/>
```
