← Catalog
Edit Props (live)
IMAGE
TEXT
TEXT
config
config
Source
198 lines// Inspired by hyperframes `app-showcase` (Apache-2.0). The original shows
// three phone mockups in a triptych; we simplify to a single phone on a
// colored gradient stage, with configurable screenshot + headline + CTA.
// Plays well both as a standalone hero and overlaid on a reel.
import React from 'react';
import {
AbsoluteFill,
interpolate,
spring,
useCurrentFrame,
useVideoConfig,
} from 'remotion';
interface Props {
screenshotUrl: string;
headline: string;
ctaText: string;
bgColor: string;
accentColor: string;
}
export default function AppShowcase({
screenshotUrl,
headline,
ctaText,
bgColor,
accentColor,
}: Props) {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
const s = (seconds: number) => seconds * fps;
const phoneEnter = spring({
frame,
fps,
config: { damping: 12, stiffness: 90 },
});
const phoneY = (1 - phoneEnter) * 120;
const headlineIn = interpolate(frame, [s(0.5), s(1.1)], [0, 1], {
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
});
const headlineY = (1 - headlineIn) * 40;
const ctaPulse =
0.96 + 0.04 * Math.sin(((frame - s(1.5)) / fps) * Math.PI * 2);
const ctaOpacity = interpolate(frame, [s(1.3), s(1.7)], [0, 1], {
extrapolateLeft: 'clamp',
extrapolateRight: 'clamp',
});
return (
<AbsoluteFill
style={{
background: `radial-gradient(ellipse at top, ${accentColor}33 0%, ${bgColor} 55%)`,
fontFamily: 'system-ui, sans-serif',
}}
>
{/* Decorative halo behind the phone */}
<div
style={{
position: 'absolute',
top: '25%',
left: '50%',
width: 900,
height: 900,
transform: 'translate(-50%, -50%)',
borderRadius: '50%',
background: `radial-gradient(circle, ${accentColor}55 0%, transparent 60%)`,
filter: 'blur(40px)',
opacity: headlineIn,
}}
/>
{/* Phone frame */}
<div
style={{
position: 'absolute',
top: 260,
left: '50%',
transform: `translate(-50%, ${phoneY}px)`,
opacity: phoneEnter,
width: 540,
height: 1080,
borderRadius: 64,
background: '#0a0a0a',
padding: 16,
boxShadow:
'0 40px 120px rgba(0,0,0,0.6), inset 0 0 0 2px rgba(255,255,255,0.08)',
}}
>
<div
style={{
position: 'relative',
width: '100%',
height: '100%',
borderRadius: 48,
overflow: 'hidden',
background: '#111',
}}
>
{/* Notch */}
<div
style={{
position: 'absolute',
top: 16,
left: '50%',
transform: 'translateX(-50%)',
width: 140,
height: 28,
background: '#000',
borderRadius: 14,
zIndex: 2,
}}
/>
{screenshotUrl ? (
// eslint-disable-next-line @next/next/no-img-element
<img
src={screenshotUrl}
alt=''
style={{
width: '100%',
height: '100%',
objectFit: 'cover',
}}
/>
) : (
<div
style={{
width: '100%',
height: '100%',
background: `linear-gradient(180deg, ${accentColor} 0%, ${bgColor} 100%)`,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: 48,
color: '#fff',
opacity: 0.45,
}}
>
Your App
</div>
)}
</div>
</div>
{/* Headline + CTA stacked above phone */}
<div
style={{
position: 'absolute',
top: 120,
left: 0,
right: 0,
textAlign: 'center',
opacity: headlineIn,
transform: `translateY(${headlineY}px)`,
}}
>
<div
style={{
fontSize: 72,
fontWeight: 800,
color: '#fff',
letterSpacing: '-0.02em',
lineHeight: 1.1,
padding: '0 80px',
}}
>
{headline}
</div>
</div>
{/* CTA pinned near the bottom */}
<div
style={{
position: 'absolute',
bottom: 120,
left: '50%',
transform: `translate(-50%, 0) scale(${ctaPulse})`,
opacity: ctaOpacity,
padding: '22px 56px',
borderRadius: 999,
background: accentColor,
fontSize: 32,
fontWeight: 700,
color: '#fff',
letterSpacing: '0.04em',
boxShadow: `0 12px 40px ${accentColor}99`,
}}
>
{ctaText}
</div>
</AbsoluteFill>
);
}
Schema (Zod)
import { z } from 'zod';
export const Schema = z.object({
screenshotUrl: z.string().describe('$port:image App screenshot').default(''),
headline: z.string().describe('$port:text Hero headline'),
ctaText: z.string().describe('$port:text CTA button label').default('START NOW'),
bgColor: z.string().default('#0a0a1a'),
accentColor: z.string().default('#7c5cff'),
});
App Showcase
app_showcaseSingle-phone hero with configurable screenshot, headline, and CTA. Phone spring-enters; CTA pulses. Simplified from hyperframes multi-phone triptych (Apache-2.0).
Workflow Inputs (3)
- App screenshot
screenshotUrlIMAGE - Hero headline
headlineTEXTRequired - CTA button label
ctaTextTEXT
Config Fields (2)
bgColoraccentColor
Meta
- Updated
- 4/21/2026