# screenframe3d

> Composite app screenshots onto 3D device mockups

Latest version **0.1.0** (published 2026-09-13) · MIT license · 0 weekly downloads

## Install

```sh
npm install screenframe3d
pnpm add screenframe3d
yarn add screenframe3d
bun add screenframe3d
```

## Health

**Score 65/100 (B)** — status: active.

Positive: has types; esm support; no vulnerabilities; recently updated; high maintenance score.

Warnings: low downloads; pre 1.0.

## Facts

| | |
|---|---|
| Version | 0.1.0 |
| Published | 2026-09-13 |
| First published | 2026-09-13 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 0 |
| Unpacked size | 2.5 MB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 0 |
| Author | Nick Vander Woude |
| Maintainers | nvande |
| Keywords | 3d, device, mockup, screenshot, three.js |

## Links

- npm: https://www.npmjs.com/package/screenframe3d
- Repository: https://github.com/nvande/Screenframe3D
- Homepage: https://nvande.github.io/Screenframe3D/
- Issues: https://github.com/nvande/Screenframe3D/issues
- npm.io page: https://npm.io/package/screenframe3d

## Alternatives

- [pagerjs](https://npm.io/package/pagerjs.md) — 60 weekly downloads
- [whistle.savefor-mock](https://npm.io/package/whistle.savefor-mock.md) — 4 weekly downloads
- [@lyra-mock-api/core](https://npm.io/package/@lyra-mock-api/core.md) — 0 weekly downloads
- [@swarmica/msw-auto-mock](https://npm.io/package/@swarmica/msw-auto-mock.md) — 0 weekly downloads
- [@mikemajesty/zod-mock-schema](https://npm.io/package/@mikemajesty/zod-mock-schema.md) — 0 weekly downloads

## Recent versions

- 0.1.0 (latest) — 2026-09-13

## README

# Screenframe3D

Composite an app screenshot onto a real 3D phone. [Live demo](https://nvande.github.io/Screenframe3D/).

Phone GLBs are **not** included in the npm package (Sketchfab licenses). You download a model once, drop it in `public/models/`, and Screenframe does the rest. First-party devices are planned.

## Install

```bash
npm install screenframe3d three
```

React apps also need `react` / `react-dom`. Vite apps should add the plugin below so the HDRI (and later, posters) land automatically.

## 1. Get a device model from Sketchfab

`device` is a path. Screenframe loads **`/models/{device}.glb`** from your site.

| Device | `device` id | Put the file at | Sketchfab |
|---|---|---|---|
| iPhone 5s | `apple/iphone-5s` | `public/models/apple/iphone-5s.glb` | [IPhone 5s](https://sketchfab.com/3d-models/iphone-5s-2a8b3bd5333d4f1899a67d5dca6b24ab) by [Eternal Realm](https://sketchfab.com/EternalRealm) (CC-BY-4.0) |
| iPhone 12 Pro | `apple/iphone-12-pro` | `public/models/apple/iphone-12-pro.glb` | [iPhone 12 Pro](https://sketchfab.com/3d-models/iphone-12-pro-05dfc991665e45c68c8b7062136c0c6e) by [DatSketch](https://sketchfab.com/DatSketch) (CC-BY-4.0) |
| iPhone 14 Pro | `apple/iphone-14-pro` | `public/models/apple/iphone-14-pro.glb` | No single listing is embedded in the file. Search [downloadable iPhone 14 Pro models](https://sketchfab.com/search?features=downloadable&q=iphone+14+pro&type=models). You want a **`body_mat`** (or similar) whose **emissive** map includes a bright portrait screen. |
| iPhone 17 Pro | `apple/iphone-17-pro` | `public/models/apple/iphone-17-pro.glb` | [Iphone 17 pro](https://sketchfab.com/3d-models/iphone-17-pro-4aeeeb41f9d14f96bb3f2589edc3edac) by [Ibrahim.Bhl](https://sketchfab.com/Ibrahim.Bhl) (CC-BY-4.0) |

### Download steps

1. Make a free [Sketchfab](https://sketchfab.com) account.
2. Open the model. Confirm it is **downloadable** and that the license fits your project (CC-BY requires credit).
3. **Download 3D model** → **glTF** (or **GLB** if offered).
4. If you get a folder, use the `.glb` (often `scene.glb`). If you only get `scene.gltf` + `scene.bin` + `textures/`, keep that folder structure or convert to a single `.glb`.
5. Rename / move it to the path in the table. The filename must match `device` exactly: `apple/iphone-12-pro` → `models/apple/iphone-12-pro.glb`.

### What Screenframe looks for on the glass

Any downloadable phone can work if Screenframe can find the display:

- A material or mesh named **`screen`**, **`wallpaper`**, **`Screen_BG`**, **`display`**, or **`lcd`**, or
- A material named **`body_mat`** whose **emissive** map has a bright portrait rectangle (atlas).

The four rows above are the combinations this repo is tested against. Catalog in code: `DEVICES` from `screenframe3d`.

## 2. Environment map (glass and metal)

Reflections use `/env/greenwich_park_1k.hdr` by default ([Greenwich Park](https://polyhaven.com/a/greenwich_park), CC0, Poly Haven).

The Vite plugin copies that file into `public/env/` when it is missing. Without the plugin, [download the 1K HDR](https://polyhaven.com/a/greenwich_park) and save it as `public/env/greenwich_park_1k.hdr`.

## 3. Vite plugin (recommended)

```ts
import { defineConfig } from 'vite';
import { screenframe } from 'screenframe3d/vite';

export default defineConfig({
  plugins: [screenframe()],
});
```

That plugin:

- Copies the bundled HDRI into `public/env/`
- Writes extracted device textures to `public/textures/` on first run
- Captures a still (poster) so the next load can show an image before WebGL is ready

It does **not** download Sketchfab models.

## 4. Use it

### Vanilla

```html
<div id="device"></div>
<script type="module">
  import { initDeviceShowcase } from 'screenframe3d';

  initDeviceShowcase({
    container: document.getElementById('device'),
    screenshot: '/screenshot.png',
    device: 'apple/iphone-12-pro',
    publicBase: import.meta.env.BASE_URL,
  });
</script>
```

### React

```tsx
import { DeviceShowcase } from 'screenframe3d/react';

<DeviceShowcase
  screenshot="/screenshot.png"
  device="apple/iphone-12-pro"
  publicBase={import.meta.env.BASE_URL}
/>
```

`publicBase` matters if the app is not served from `/` (GitHub Pages, a Vite `base`, etc.).

## Options

Passed to `initDeviceShowcase()` or `<DeviceShowcase />`:

| Option | Description |
|---|---|
| `container` | DOM node for the canvas (vanilla only) |
| `screenshot` | URL of the image on the glass (not downscaled) |
| `device` | Path id, e.g. `apple/iphone-12-pro` → `/models/apple/iphone-12-pro.glb` |
| `publicBase` | Prefix for models, env, posters, textures |
| `environment` | HDRI URL (default `/env/greenwich_park_1k.hdr`) |
| `fov`, `zoom`, `baseTilt` | Camera / rest pose |
| `tiltEnabled`, `spring`, `scrollTilt` | Pointer and scroll motion |
| `poster` | `false` / omit = no still. `true` / `'auto'` = hashed `/posters/...webp`. Or pass a URL. |
| `cachePoster`, `cacheDeviceTextures` | Persist stills and maps during `vite dev` (needs the plugin) |
| `fallbackCondition`, `fallbackImage` | Opt-in static image instead of WebGL |

## Development (this repo)

```bash
npm install
npm run dev      # landing + playground (models already in public/)
npm run build    # library → dist/
```

Phone GLBs in `public/models/` are for the demo only. They are not published to npm.

## License

MIT for the library code.

Device models you download remain under their Sketchfab licenses; CC-BY models need attribution. The default HDRI is CC0 (Poly Haven).

---
_Source: https://npm.io/package/screenframe3d · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
