# What this is, and when to use it

> An asset store with superpowers — every file your product owns, addressed, measured and delivered.

**This is where your product's media lives.** Every image, every video, every
PDF — uploaded by a user or shipped by you — stored once, addressed by content,
measured per tenant, and delivered from a CDN in whatever shape the page needs.

A modern Cloudinary, built agent-first.

## The four jobs

**1 · Store everything, once.**
Content-addressed by SHA-256, so the same bytes are the same asset no matter
who uploaded them or what they called the file. Deduplication is not a feature
you turn on; it is what an address *is*.

**2 · Get bytes off a device, reliably.**
Multipart with resume across a reload, progress per file, compression before
anything leaves the phone. On mobile, a native background session so the upload
survives a locked screen.

**3 · Serve whatever shape the page needs.**
One upload, many outputs: a 256px thumbnail, a 1920px hero, a square crop, a
different format — on demand behind a CDN, not pre-generated by you and not
stored five times.

**4 · Do the video work you do not want to build.**
Poster, web-safe MP4, an adaptive HLS ladder, and a cheap proxy meant for a
model rather than a person.

## Yes, put your logos and hero videos here

Static assets belong here too, and that is the point rather than an exception.

A logo in your bundle is a logo you cannot swap without a deploy. Here it is:

- **addressed** — one URL, every size, every format, from the same SHA;
- **countable** — it shows up in your tenant's storage and file count;
- **swappable** — bind it to a [slot](/examples/react-slots/) and an admin
  changes the hero without touching code;
- **optional to optimise** — ask for `["original"]` and it is stored verbatim,
  byte-for-byte, no re-encode. The superpowers are opt-in, not mandatory.

The last point is worth stating plainly: **you can use this as plain storage.**
A file uploaded with `presets: ["original"]` comes back exactly as you sent it.
Everything else — ladders, transforms, palettes, transcodes — is something you
ask for, per asset.

## What you can measure

```ts
const s = await nt.usage.snapshot();
s.storage.totalBytes   // how much this tenant is holding
s.storage.assetCount   // how many files
s.today, s.last30Days  // what moved
await nt.usage.keys(); // which key did it
```

Per-tenant storage and file count are first-class, which is what makes this
usable as *the* asset store rather than one of several.

## Grouping today: slots and metadata

Being honest about the current state, because "collections" means different
things to different people:

- **Slots** are named bindings — `storefront.cr.hero` — and they list by
  prefix, so `slots.list({ prefix: "storefront.cr." })` is a namespace. That is
  the grouping primitive that exists and it is the one most products need.
- **`patchMetadata(id, {...})`** attaches arbitrary JSON to an asset.
- **A first-class Collection entity does not exist yet.** If you need album-like
  grouping with its own listing and permissions, you build it in your database
  today, keyed by SHA.

## When it is genuinely the wrong tool

Short list, and none of these are about storage:

- **Destructive editing.** Crops, filters and layers that a *user* manipulates
  and re-saves. This transforms on read and keeps one canonical original — it
  is deliberately not an editor.
- **Document intelligence.** PDFs and spreadsheets are stored and served
  intact, but there is no page rendering, no text extraction, no OCR. Store
  them here; if you need to *read inside* them, that is a second system.
- **Sub-100 ms first byte on a brand-new derivative.** The first request for a
  shape nobody has asked for yet pays for its own generation. Every request
  after that is a CDN hit — so this only matters for a cold, one-off shape.

## What it costs you to adopt

1. **A server-side seam.** The upload key cannot live in the browser, so you
   need one route of your own. About fifteen lines.
2. **Deciding presets at first ingest.** A variant you do not ask for on the
   first upload cannot be added later — see
   [Variants and presets](/concepts/variants-and-presets/).
3. **Onboarding is a conversation.** No self-serve signup yet; you get an
   endpoint, a tenant id and keys from us. See
   [Getting your credentials](/start/credentials/).

## The mental model in one line

**The SHA is the asset. Everything else — every size, every format, every URL —
is a function of it.**

Once that lands, the API stops having surprises: `upload()` gives you a SHA, and
every builder takes a SHA and returns a URL.