A mobile screenshot floats inside a realistic 3D phone mockup. The phone rotates with the cursor and the screen pulses with subtle app glow. Perfect for app launch pages.
import HeroPhoneMockup from '@crazygl/hero-phone-mockup';
export default function App() {
return (
<HeroPhoneMockup
heading="Built for thumbs."
subheading="Your app, beautifully framed."
screenshot="/screens/my-app.png"
bodyTint="#ffffff"
/>
);
}screenshot (the vertical app image; 9:19.5 crops cleanest) and screenBrightness (how strongly the screen self-illuminates).useGlbMaterials keeps the GLB's authored PBR finish; bodyTint multiplies over it for color variants. Turn the toggle off to fully override phoneColor / frameMetalness / frameRoughness. phoneScale sizes the phone.pointerRotation (how strongly the phone follows the cursor) and appGlowPulse (subtle screen brightness pulse).transparentBackground, or a radial gradient via bgColor1 / bgColor2.keyColor / fillColor / backColor of the studio rig plus envIntensity for the procedural HDRI reflection.contentAlign, phoneOffsetX / phoneOffsetY, padding.npm install @crazygl/hero-phone-mockupThe component takes the same props you see in the live customizer on the right — every default ships poster-quality.
import VerticalPhoneScreenshotWith3DDepth from '@crazygl/hero-phone-mockup';
export default function Landing() {
return (
<VerticalPhoneScreenshotWith3DDepth />
);
}The wrapper renders static HTML on the server and only initialises the canvas after hydration, so search engines see your copy.
// app/page.tsx — works in SSR-first frameworks (Next, Remix, Astro, etc.)
'use client';
import VerticalPhoneScreenshotWith3DDepth from '@crazygl/hero-phone-mockup';
export default function Page() {
return (
<section>
<VerticalPhoneScreenshotWith3DDepth
heading="Say hi."
subheading="Your new hero."
/>
<article>
<h2>Welcome</h2>
<p>Your content keeps its own voice below the hero.</p>
</article>
</section>
);
}