What resolves
Assets that resolve:
.png .jpg .jpeg .gif .webp .svg, .ogg .mp3 .wav, .mp4 .webm, .bbmodel .gltf .glb .obj, .ttf .woff .woff2.
What does not
- absolute paths
import()andrequire()with anything but a literal path, because everything is resolved before your code runssdk/anything-else: onlysdkandsdk/uiexist
TypeScript and JSX
The app compiles.ts, .tsx, .jsx and .js on load. Types are stripped without being checked, which is what makes loading fast; run tsc in your editor for checking. JSX uses the automatic runtime, so there is no need to import React to write JSX.
Compiled output keeps your line numbers, so a stack trace and an error card point at the line you wrote.
How modules behave
- Each module runs once; its exports are cached for everyone importing it.
- Circular imports behave as in Node: the module still running exposes its partial exports.
- Output is cached by content hash, so a reload only recompiles files that changed.
CSS
button { … } styles your buttons and not the app’s. @media, @supports, @container and @layer are scoped inside too. @keyframes names are prefixed so two expansions can both animate spin, and animation declarations are rewritten to match. :root, html and body mean your own wrapper.
@import is dropped: it would fetch a URL at runtime.
.module.css additionally hashes class names and gives you the map as the default export, so two files can both use .title.
Assets
data: URL string, usable anywhere a URL goes: <img src={logo} />, new Audio(sound), a CSS url() you build yourself. Assets are inlined at load, so large files cost memory; keep a 3D model or a long audio file out of the import graph if you do not need it.