npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-native-model-viewer-webview

v0.2.0

Published

A WebView-backed GLB and glTF model viewer for React Native and Expo.

Downloads

266

Readme

react-native-model-viewer-webview

A tiny React Native and Expo wrapper around Google's <model-viewer> web component, rendered inside react-native-webview.

It is for simple GLB/glTF previews, not for building a native 3D engine.

Why This Exists

Use this package when your product requirement sounds like:

"Show this .glb in a React Native screen with orbit controls, auto-rotate, lighting, and load/error callbacks."

For that job, setting up Filament, Three.js, React Three Fiber, render loops, lights, cameras, loaders, and Metro asset details can be more machinery than the screen deserves. This package gives you the WebView version of the web <model-viewer> ergonomics.

When To Use It

  • Product cards or vehicle previews.
  • Marketplace listings with one inspectable 3D asset.
  • Expo demos and prototypes where WebView rendering is acceptable.
  • Apps that already use <model-viewer> on the web and want similar mobile behavior.
  • Teams that want a small dependency and do not need full scene control.

When Not To Use It

Use a native 3D stack instead when you need:

  • native GPU rendering as the core experience
  • custom materials, shaders, lights, or post-processing
  • physics, collision, skeletal animation control, or multi-object scenes
  • precise frame timing or heavy interaction
  • AR or game-like rendering

Good alternatives:

Install

Expo:

npx expo install react-native-model-viewer-webview react-native-webview

Bare React Native:

npm install react-native-model-viewer-webview react-native-webview

If your app already has a compatible react-native-webview, install only react-native-model-viewer-webview. Bare React Native apps should follow react-native-webview's native setup instructions.

Quick Start

import { ModelViewerWebView } from "react-native-model-viewer-webview";

export function CarPreview() {
  return (
    <ModelViewerWebView
      modelSource="https://example.com/car.glb"
      style={{ height: 320 }}
      htmlOptions={{
        autoRotate: true,
        cameraControls: true,
        cameraOrbit: "35deg 66deg 6.2m",
        disablePan: true,
        exposure: 1.05,
        shadowIntensity: 0.35,
      }}
      onModelLoaded={(status) => {
        console.log(status.message);
      }}
      onModelError={(status) => {
        console.warn(status.message);
      }}
    />
  );
}

Model Sources

modelSource accepts:

  • a remote URL
  • a data: URI
  • a file: URI
  • a React Native static asset module number from require(...)
  • an object with localUri and/or uri, such as an Expo asset
<ModelViewerWebView
  modelSource={require("./assets/car.glb")}
  style={{ height: 320 }}
/>
import { Asset } from "expo-asset";
import { ModelViewerWebView } from "react-native-model-viewer-webview";

const carModel = Asset.fromModule(require("./assets/car.glb"));
await carModel.downloadAsync();

<ModelViewerWebView modelSource={carModel} style={{ height: 320 }} />;

localUri is preferred over uri when both exist. modelUri is still accepted as a string-only compatibility prop.

Metro Setup For Local GLB Files

If your app imports .glb files, add glb to Metro's asset extensions.

Expo example:

const { getDefaultConfig } = require("expo/metro-config");

const config = getDefaultConfig(__dirname);

config.resolver.assetExts = [
  ...config.resolver.assetExts,
  "glb",
  "gltf",
];

module.exports = config;

Troubleshooting Local Package Development

If you test this package through file:../path, npm link, or a monorepo symlink, make sure Metro resolves peer dependencies from the app, not from this package's local node_modules.

Duplicate React copies can cause this error:

Invalid hook call. Hooks can only be called inside of the body of a function component.

In that setup, alias react, react-native, and react-native-webview to the app's node_modules, and exclude any package-local dev copies of those peers from Metro's file map.

Offline Script Loading

By default, the generated WebView HTML inlines a vendored copy of @google/model-viewer 4.2.0. That means the viewer runtime does not need a CDN request, and local .glb previews can work offline when the model asset is also available locally.

This makes the npm package larger, but keeps runtime behavior deterministic and offline-friendly. The Apache-2.0 license for the bundled runtime is included in vendor/model-viewer/LICENSE, with a summary in THIRD_PARTY_NOTICES.md. The exact source package, file hash, and generated runtime details are recorded in vendor/model-viewer/SOURCE.md.

If you prefer a custom or CDN-hosted runtime, pass your own script URL:

import { MODEL_VIEWER_CDN_SCRIPT_URL } from "react-native-model-viewer-webview";

<ModelViewerWebView
  modelSource="https://example.com/car.glb"
  htmlOptions={{
    modelViewerScriptUrl: MODEL_VIEWER_CDN_SCRIPT_URL,
  }}
/>

Or pass an inline module script if your build already bundles the source:

<ModelViewerWebView
  modelSource="https://example.com/car.glb"
  htmlOptions={{
    modelViewerScript: bundledModelViewerSource,
  }}
/>

Props

ModelViewerWebView accepts all react-native-webview props except source and onMessage, which are managed by the package.

Important props:

| Prop | Type | Description | | --- | --- | --- | | modelSource | string \| number \| { localUri?: string; uri?: string } | Preferred model input. | | modelUri | string | String-only compatibility input. | | htmlOptions | ModelViewerHtmlOptions | Controls <model-viewer> attributes and script loading. | | onStatus | (status, event) => void | Receives every status message from the WebView. | | onModelLoaded | (status, event) => void | Fires when <model-viewer> emits load. | | onModelError | (status, event) => void | Fires when page or model loading fails. | | webViewBaseUrl | string | Base URL used for the generated HTML. Defaults to https://localhost/. |

Useful htmlOptions:

| Option | Description | | --- | --- | | autoRotate | Adds auto-rotate. | | cameraControls | Adds camera-controls; defaults to true. | | cameraOrbit | Sets the initial orbit. | | minCameraOrbit / maxCameraOrbit | Bounds zoom/orbit. | | disablePan | Adds disable-pan. | | exposure / shadowIntensity | Basic visual tuning. | | backgroundColor / posterColor | Controls the WebView and poster background. | | additionalAttributes | Adds extra <model-viewer> attributes. | | modelViewerScriptUrl | Overrides the bundled runtime with a custom <model-viewer> script URL. | | modelViewerScript | Overrides the bundled runtime with a custom inline module script. |

Example

See example/App.tsx for a minimal Expo screen.

More Documentation

AI Agent Support

The package includes agent-facing docs so coding agents can integrate it without guessing:

Claude Code can use the skill after copying it to ~/.claude/skills/react-native-model-viewer-webview/SKILL.md or a project-local .claude/skills/react-native-model-viewer-webview/SKILL.md. Installing from npm does not automatically install a skill into an agent client. See AI agent usage for copy/symlink instructions.

Development

npm test
npm run typecheck
npm run pack:dry-run

The test suite runs against dist because that is the code npm consumers load. When changing src, keep dist in sync before running the package tests.

Tradeoffs

This package renders through WebView, so it inherits WebView tradeoffs:

  • startup cost is higher than a plain native view
  • WebView memory use can matter in long lists
  • native gestures and WebView gestures may need tuning in complex screens
  • rendering behavior follows the platform WebView

The upside is simplicity. For many product preview surfaces, that is the whole point.

Pre-Publish Checklist

Before publishing a release:

  • test a remote .glb on Android
  • test a bundled .glb on Android
  • test at least one iOS physical device if iOS support is claimed
  • test a no-network/offline script setup if documenting offline support
  • run npm pack --dry-run
  • keep the README positioning honest: this is not a Filament/R3F replacement

License

MIT