A prop-by-prop map from the 0.0.1 API to 1.0.0, and an honest account of why it is a clean break.

Migrating from 0.0.1

A prop-by-prop map from the 0.0.1 API to 1.0.0, and an honest account of why it is a clean break.


Why a clean break

1.0.0 is not a compatible upgrade. DashModelViewer is gone; there is no shim that keeps old code running.

That is a deliberate decision rather than an oversight, and the argument for the other choice was real: the package had roughly 253 downloads a month, and a deprecating wrapper would have cost little. What tipped it was that the parts most in need of changing — hotspots, AR defaults, and the complete absence of output props — could not be fixed while preserving the old surface. A compatibility layer would have frozen the exact shapes that made the component hard to use.

So: rename, and say so loudly.


Side by side

# 0.0.1
from dash_model_viewer import DashModelViewer

DashModelViewer(
    id="viewer",
    src="/assets/shoe.glb",
    alt="A shoe",
    cameraControls=True,
    arModes="webxr scene-viewer quick-look",   # you had to know to set this
    arButtonText="View in your space",
    hotspots=[
        {"slot": "hotspot-1", "position": "0 1 0", "text": "Sole",
         "children_classname": "label"},
    ],
)
# 1.0.0
import dash_model_viewer as dmv
from dash import html

dmv.ModelViewer(
    id="viewer",
    src="/assets/shoe.glb",
    alt="A shoe",
    camera_controls=True,
    # ar_modes now defaults to "webxr scene-viewer quick-look"
    children=[
        dmv.Slot(slot="hotspot-1", position="0 1 0",
                 class_name="label", children="Sole"),
        dmv.Slot(slot="ar-button",
                 children=html.Button("View in your space")),
    ],
)

Prop map

0.0.11.0.0Notes
DashModelViewerModelViewerImport name unchanged; class renamed.
cameraControlscamera_controlsAll props are snake_case now.
touchActiontouch_action
cameraOrbit / cameraTargetcamera_orbit / camera_targetNow also readable via camera.
fieldOfView, minFieldOfView, maxFieldOfViewfield_of_view, …
minCameraOrbit / maxCameraOrbitmin_camera_orbit / max_camera_orbit
interpolationDecayinterpolation_decay
toneMappingtone_mapping
shadowIntensityshadow_intensity
arModesar_modesDefault fixed — see below.
arScalear_scale
variantNamevariant_name
hotspots=[{...}]children=[Slot(...)]Now takes any Dash component.
arButtonText="…"Slot(slot="ar-button", children=…)
customArPrompt=…Slot(slot="ar-prompt", children=…)
customArFailure=…Slot(slot="ar-failure", children=…)
loading_state(none)Not this package's removal — Dash 4 dropped loading_state from components generally. Use dcc.Loading, or model_state for this component's own progress.
id, src, alt (declared required)src, alt enforced0.0.1's generated metadata declared all three required; nothing in 1.0.0 checked until now. src and alt now raise at construction if missing. id stays optional — a viewer with no callbacks needs none.
(none)camera, model_state, model_info, ar_status, ar_tracking, scene_pointThe half that never worked. camera is {"orbit", "target", "field_of_view"} — see below.
(none)attributes, mv_*Full upstream parity.
(none)camera_change_debounceMandatory guard.
(none)pick_on_clickArms scene_point.

Hotspot dictionaries → Slot

Old keyNew
slotSlot(slot=...)
positionSlot(position=...)
normalSlot(normal=...)
textSlot(children="...") — or any component
children_classnameSlot(class_name=...)
orbit / target / fovA callback on Slot.n_clicks writing the camera props

The last row is the significant one. Camera-preset hotspots used to be declared inside the hotspot dict and handled invisibly by the component's JavaScript. They are now an ordinary callback, which means you can log them, animate them, gate them on auth, or compute them — see Camera and views.


Delete your clientside callbacks

If you copied the 0.0.1 examples you will have an assets/model_viewer_clientside.js and a clientside_callback for anything the component could not report. All of it is replaceable:

You were doing this in JSNow
Reading getCameraOrbit() into a dcc.StoreInput("viewer", "camera")
getDimensions() for a bounding boxInput("viewer", "model_info")
availableVariants for a dropdownmodel_info["variants"]
Listening for load / progressInput("viewer", "model_state")
Listening for ar-status / ar-trackingar_status / ar_tracking
positionAndNormalFromPoint() on clickpick_on_click=True → scene_point
Wiring hotspot clicksSlot.n_clicks

The AR default

Worth calling out separately because it changes behaviour silently rather than loudly. 0.0.1 shipped:

arModes = "basic_annotations scene-viewer quick-look"

basic_annotations is not an AR mode — it was a folder name in usage_tests/. webxr was therefore absent, and in-page WebXR AR never ran in a default configuration. If your code explicitly set arModes, you were unaffected; if it did not, you were running without WebXR and had no way to know.

You can now delete any explicit ar_modes="webxr scene-viewer quick-look" — that is the default. See Augmented reality.


Things that no longer exist

camera movement only for user interaction (that is the echo suppression which stops a callback writing camera_orbit from re-triggering itself), so source could only ever hold the single string "user-interaction". A key with one possible value tells a reader nothing, and reading it invited the belief that some other value was reachable. The payload is now {"orbit", "target", "field_of_view"}. The suppression itself is unchanged.

installed metadata.

at 4.3.1. If you relied on the CDN behaviour, dmv.configure(use_cdn=True) restores it.


Source: /migrating

Note for AI agents: This is the static, prerendered view of an interactive Dash application served because we detected a non-JS user agent. Full prose docs: