# Quick start

nanoraster renders GLB files to image bytes from one Rust core, as a native binary on Node.js 22.13 or newer and as WebAssembly in browsers with WebGPU.

Canonical page: https://www.nanoraster.xyz/docs

nanoraster turns a GLB file into image bytes you own. One request always
produces the same pixels, so a render can serve as evidence.

<CodeBlockTabs defaultValue="npm">
  <CodeBlockTabsList>
    <CodeBlockTabsTrigger value="npm">
      npm
    </CodeBlockTabsTrigger>

    <CodeBlockTabsTrigger value="pnpm">
      pnpm
    </CodeBlockTabsTrigger>
  </CodeBlockTabsList>

  <CodeBlockTab value="npm">
    ```bash
    npm install nanoraster
    ```
  </CodeBlockTab>

  <CodeBlockTab value="pnpm">
    ```bash
    pnpm add nanoraster
    ```
  </CodeBlockTab>
</CodeBlockTabs>

Save this as `render.mjs` and run it with `node render.mjs`. The camera angles
are written out so you can drag them; `phi: 60` and `theta: -45` are the
defaults. The live tile renders at 960×720, so its byte count differs, and its
milliseconds drop after the first frame because dragging reuses one renderer;
[Reuse the renderer](https://www.nanoraster.xyz/docs/guides/reuse-the-renderer.mdx) is the same move in your
own code.

```typescript
import { renderImage } from 'nanoraster';

import { readFile, writeFile } from 'node:fs/promises';

const glb = Uint8Array.from(await readFile('model.glb'));

const image = await renderImage(glb, {
  format: 'webp',
  width: 512,
  height: 512,
  phi: 60,
  theta: -45,
});

await writeFile(image.name, image.bytes);
console.log(`wrote ${image.name} (${image.bytes.length} bytes, ${image.mimeType})`);
```

## Expected output [#expected-output]

```console
wrote render.webp (26628 bytes, image/webp)
```

The result is a plain object: `name`, `bytes`, `mimeType`, and the `width` and
`height` the request resolved to. nanoraster never writes to disk, so the bytes
are yours to save, upload or hand to another process. Run the script again and
the bytes are identical: camera, lighting and encoder are fixed for a given
request.

The same call produces PNG, WebP or JPEG (`jpg` is an alias), or the
unencoded frame with `format: 'raw'`; see
[Format and annotate](https://www.nanoraster.xyz/docs/guides/format-and-annotate.mdx) and
[Work with raw pixels](https://www.nanoraster.xyz/docs/guides/work-with-raw-pixels.mdx). Every rejection is a
`RenderError` with a stable machine-readable code; see
[Handle render failures](https://www.nanoraster.xyz/docs/guides/handle-render-failures.mdx).

## What it does not do [#what-it-does-not-do]

Texture-backed materials, animation, or scene graphs beyond static geometry.
The supported profile is factor-only glTF metallic-roughness, and lighting is
the studio preset unless you [supply a rig](https://www.nanoraster.xyz/docs/guides/light-the-subject.mdx). See
[How it works](https://www.nanoraster.xyz/docs/how-it-works.mdx#material-model).