Skip to content

Storage & File Uploads

Rebase provides built-in file upload support in collection forms:

  • Drag-and-drop file upload fields
  • Image previews in forms and table cells
  • Multiple file uploads via array properties
  • MIME type filtering and size limits
  • Custom filenames via callback functions

To add file uploads to a collection, use the storage config on a string property:

properties: {
image: {
type: "string",
name: "Product Image",
storage: {
storagePath: "products", // Subdirectory in storage
acceptedFiles: ["image/*"], // MIME type filter
maxSize: 5 * 1024 * 1024, // 5MB max
fileName: (context) => { // Custom filename
return context.entityId + "_" + context.file.name;
}
}
}
}
Property Type Description
storagePath string Subdirectory within the storage backend
storageSource string Named storage source — routes uploads to a specific backend (e.g., "firebase", "media"). See Multi-Backend Storage.
public boolean Store files under the public/ prefix and serve them via stable, token-less, permanent, CDN-cacheable URLs (safe to persist and hotlink). Defaults to false (private files use short-lived signed URLs).
acceptedFiles string[] Allowed MIME types (e.g., ["image/*"], ["application/pdf"])
maxSize number Maximum file size in bytes
fileName function Custom filename generator
metadata object Additional metadata to store with the file
storeUrl boolean Store the full URL instead of the relative path

Wrap the storage property in an array for multiple file uploads:

photos: {
type: "array",
name: "Photos",
of: {
type: "string",
storage: {
storagePath: "photos",
acceptedFiles: ["image/*"]
}
}
}

Upload non-image files like PDFs:

documents: {
type: "array",
name: "Documents",
of: {
type: "string",
storage: {
storagePath: "documents",
acceptedFiles: ["application/pdf", "image/*"]
}
}
}

When your backend has multiple storage backends configured (e.g., local + S3 + GCS), you can route individual properties to specific backends using storageSource:

image: {
type: "string",
name: "Product Image",
storage: {
storageSource: "firebase", // Routes to the "firebase" backend
storagePath: "products/{entityId}",
acceptedFiles: ["image/*"],
}
}

For direct storage backends (e.g., Firebase Storage where the browser uploads straight to the cloud), register them via the storageSources prop on <Rebase>:

import type { RebaseStorageSource } from "@rebasepro/app";
<Rebase
client={rebaseClient}
storageSources={[
{ key: "firebase", engine: "firebase", transport: "direct", source: firebaseStorageSource }
]}
>
{/* your app */}
</Rebase>
Property Type Description
key string Unique identifier — must match storageSource in property configs
engine string Storage engine name (e.g., "firebase", "gcs", "s3")
transport "server" | "direct" "server" proxies through the backend; "direct" uploads from the browser
source StorageSource Client-side StorageSource implementation (required for "direct" transport)

The system automatically resolves the correct source per-property — collection properties with storageSource: "firebase" will use the matching direct source, while properties without storageSource (or with transport: "server") will proxy through the Rebase backend.

For programmatic file operations outside of collection forms:

import { useStorageSource } from "@rebasepro/app";
// Returns the default storage source
const storageSource = useStorageSource();
// Upload a file — the object is addressed by `key`
const result = await storageSource.putObject({
file,
key: "documents/my-file.pdf"
});
// Get a download URL
const { url } = await storageSource.getSignedUrl(result.key);