Storage overview
Storage keeps files in buckets that belong to your project. A bucket is public, so anyone with a file’s URL can read it, or private, so files are read through signed URLs that expire. Storage policies decide who may upload, read, change and delete files in each bucket.
Upload
Section titled “Upload”Use upload() from @vaifstudio/client/storage. It sends a small file in one request, and switches to a multipart upload for files of 5 MiB or more, sending the parts in parallel:
import { createVaifClient } from "@vaifstudio/client";import { upload } from "@vaifstudio/client/storage";
const vaif = createVaifClient({ baseUrl: "https://api.vaif.studio", projectId: process.env.VAIF_PROJECT_ID, apiKey: process.env.VAIF_PUBLISHABLE_KEY,});
const result = await upload(vaif, "avatars", "users/42/avatar.png", file, { contentType: "image/png", onProgress: (e) => console.log(`${Math.round(e.fraction * 100)}%`),});
console.log(result.key, result.sizeBytes, result.multipart);The arguments are the client, the bucket name, the file’s key in the bucket, and a Blob or File. The key needs the storage scope, which a project’s publishable key has. See Uploads in depth for canceling an upload, resuming after a crash, and tuning part size and concurrency.
Read a file
Section titled “Read a file”// Private bucket: a signed URL that expires (in seconds; the default is 3600)const signed = await vaif.storage.createSignedUrl("users/42/avatar.png", 600, { bucket: "avatars" });
// Public bucket: a plain URL, no signingconst publicUrl = vaif.storage.getPublicUrl("users/42/avatar.png", { bucket: "avatars" });
// Or download the bytesconst bytes = await vaif.storage.download("users/42/avatar.png", { bucket: "avatars" });console.log(signed, publicUrl, bytes.size);Browser helpers
Section titled “Browser helpers”@vaifstudio/client/storage/browser uploads straight from a file input or a drop zone:
import { uploadFromInput, createDropZone } from "@vaifstudio/client/storage/browser";
const input = document.querySelector<HTMLInputElement>("#avatar")!;input.addEventListener("change", async () => { const results = await uploadFromInput(vaif, input, { bucket: "avatars", keyTemplate: "users/42/${name}" }); console.log(results.map((r) => r.key));});
const zone = createDropZone(vaif, document.getElementById("drop")!, { bucket: "inbox", onResult: (result, dropped) => console.log(dropped.name, "->", result.key), onError: (error, dropped) => console.error(dropped.name, error),});
// When the component unmounts:zone.destroy();keyTemplate replaces ${name} with the file’s name. These helpers keep resume state in the browser’s local storage by default; pass resume: null to turn that off.
List and delete files
Section titled “List and delete files”Listing, deleting, copying and moving files, and managing buckets, are console operations: they need a project developer’s console access token, not the publishable key. Run them from your own server or scripts:
import { createVaifClient } from "@vaifstudio/client";
const admin = createVaifClient({ baseUrl: "https://api.vaif.studio", projectId: process.env.VAIF_PROJECT_ID, accessToken: process.env.VAIF_ACCESS_TOKEN, // a console access token, server only});
const { files, hasMore, nextCursor } = await admin.storage.list({ bucket: "avatars", prefix: "users/42/" });console.log(files.length, hasMore, nextCursor);
await admin.storage.delete("users/42/old.png", { bucket: "avatars" });
const { deleted, errors } = await admin.storage.deleteMany(["a.png", "b.png"], { bucket: "avatars" });console.log(deleted, errors);You can also browse, upload and delete files on the Storage page in the console.
Limits
Section titled “Limits”How much storage a project can hold depends on its plan. See Plans.