Add Object Storage to your app
This guide will show you how to add Object Storage to your project and use it to store and serve files. You’ll learn how to set up an Object Storage binding, list and display files from your bucket, upload files to your bucket with proper validation, and handle large file uploads using multipart uploads.
Object Storage for Webflow Cloud is in Beta
To continue with this tutorial, you’ll need access to Object Storage for Webflow Cloud.
Prerequisites
Before you begin, make sure you have:
Set up your project
This tutorial uses a repository with pre-built UI, backend endpoints, and helper utilities for file uploads and management. Follow along with the steps below and reference the code in the example project to see how Object Storage is used in this Webflow Cloud app. You may need to make some code changes to the project to get it working with your Webflow Cloud environment.
Fork and clone the example repository
To start, fork the project on Github so you have your own copy to work with.
Next, clone your fork of the starter repository to your local machine and install dependencies:
The project uses Astro with TypeScript and includes all necessary dependencies for Object Storage operations.
Create a new Webflow Cloud project
Go to the Webflow Cloud dashboard in your site settings and create a new Webflow Cloud project.
- Go to your Webflow Cloud dashboard
- Click “Install Github app” to authorize Webflow Cloud for your fork of this repo - follow the prompts on Github
- Click “Create new project”
- Name your project
- Choose the
webflow-cloud-object-storage
repository - Click “Create project”
Repository linking
Once the project is created, it will automatically deploy when you push changes to the linked GitHub repository.
Create an environment
Create a new environment for the main branch
- In the same modal, choose the
main
branch - Choose a mount path for the environment (for example, /app → mysite.webflow.io/app)
- Click “Create environment”
- Publish your Webflow site to make your environment live
- A new row should appear in the table with your new environment. Click into it to see the environment details
Mount paths
Mount paths are unique to each environment and are used to route traffic to the correct environment. Each mount path must be unique across all environments within a project.
Add environment variables
On your environment page, click the “Environment Variables” tab and add the following environment variable:
Variable Key
: ORIGINVariable Value
: Your Webflow Cloud domain (for example,https://your-site-name.webflow.io
)
Click “Add variable” to save the variable.
Update your project configuration
Now, with your locally cloned project, open it in your preferred code editor and update the following files:
astro.config.mjs
to include the base path for your environment and theassetsPrefix
to match the mount path of your environment.- Create a new
.env
file at the root of the project to include theORIGIN
environment variable.
Add Object Storage binding
Before you can use Object Storage in your Webflow Cloud app, you need to declare a binding in your project’s configuration. This binding tells your app how to connect to the storage resource.
Once the binding is declared, your app can use simple methods like .list()
, .put()
, and .delete()
to read from and write to the Object Storage bucket directly in your code.
Declare a binding in wrangler.json
Open your project’s wrangler.json
file and add an r2_buckets
array to define your Object Storage buckets with the following information:
binding
: The variable name you’ll use to access the bucket in your code. This must be a valid JavaScript variable name.bucket_name
: The name of the bucket wher you’ll store files
Generate type definitions for your binding.
Update your project’s type definitions to enable autocomplete and type safety:
This ensures your code editor recognizes the Object Storage binding.
Deploy your app
Commit and push any local changes to your remote Github repo to automatically deploy your app.
CLI deployments will not apply changes to binding configurations
To create a new binding, you’ll need to commit and push your changes to your linked repository.
Access your binding in your Environment Dashboard
In Webflow, navigate to your site’s settings and click on the “Webflow Cloud” tab. Navigate to your project’s environment dashboard. Once your project is deployed, you’ll see a “Bindings” tab appear in the dashboard.

Click on the “Bindings” tab and you’ll see your Object Storage binding listed.
Add test files to your bucket
Add a couple of test files to your bucket using the Webflow Cloud dashboard. Click on the “Upload” button and select the files you want to upload. Later, you’ll create a route to upload files to your bucket.

You’ll see the file appear in your bucket in the dashboard.
Uploading files to your local bucket
In your local project, you can upload files to a local bucket by running the following command in your terminal:
This will upload the file to your local bucket, which you can then access when developing your project.
List files in your bucket
Get familiar with accessing your Object Storage bucket in your code by creating a new route that lists the files in your bucket. This route will return all files stored in your bucket with their metadata.
Serve files from your bucket
Now that you can list files, create a route to serve individual files from your bucket. This route will handle file requests and return the file content with appropriate headers.
Create a file serving route
In your api
directory, create a new file called asset.ts
. This file will contain the logic for serving individual files from your bucket.
(Optional) View files in your app
If you added assets to your local bucket in your local project, you can view them now.
To see your app locally, run the following command:
This will start the development server and you can view your app at http://localhost:4321/YOUR_BASE_PATH
.
You should see the files you added to your bucket appear in the list of files.

Deploy your app
To deploy your app to Webflow Cloud, commit and push your changes to your GitHub repository.
Go to your environment in Webflow Cloud to see your app deployed. Once deployed, you can access your app at https://<YOUR_DOMAIN>/<YOUR_BASE_PATH>
and see the files you uploaded via the Webflow Cloud dashboard.
To upload files from the App, you’ll create a new upload route in the next step.
Upload files to your bucket
Next you’ll walk through the route to handle file uploads from your frontend. This route will process form data, validate files, and store them in your bucket. This approach is best for smaller files less than 1MB. For larger files, see the multipart upload route in the next section.
File uploads should be executed on the domain of your worker
To avoid size upload limits, file upload endpoints should be executed on the domain of your worker using the ASSETS_PREFIX
environment variable, and not your custom Webflow Cloud domain. Because of this, you’ll need to handle CORS requests for this route.
Create an upload route
In your api
directory, step into the file called upload.ts
. This file will contain the logic for uploading files to your bucket.
Test your upload route
The frontend is already set up to use the upload route. You can test it by navigating to the file uploader page and uploading a file in your development environment. You should see the file appear in the list of files.
Deploy your app
Deploy your app to Webflow Cloud to start uploading files from the frontend. Commit and push your changes to your GitHub repository to start a deployment.
Once your app is deployed, navigate to the file uploader page and upload a file. You should see the file appear in the list of files.

You may see a 413 Content Too Large
error if you attempt to upload large files. For these cases, see the multipart upload route in the next section.
Handle large files with multipart uploads
Webflow Cloud apps have a 500MB request body limit and require requests to complete within 30 seconds. The direct upload approach from the previous section is good for small files. For larger files, use the multipart upload approach shown below.
Multipart uploads break large files into smaller chunks that can be uploaded concurrently, improving upload performance and reliability. This approach allows browsers to upload multiple parts simultaneously and resume interrupted uploads. To achieve this, you’ll need to set up logic on both the server and the browser to handle the multipart upload process.
Create the server endpoints
The server handles three main operations:
- Create - Initialize upload session and get upload ID from the bucket
- Upload Parts - Accept individual file chunks
- Complete - Combine all parts into final file and return the file metadata
We’ll walk through the following POST and PUT endpoints on the src/pages/api/multipart-upload.ts
file to handle these operations.
Create the browser logic
The browser handles the chunking of the file and the uploading of the parts to the server. To do this, the client-side logic will need to:
- Initiate - Get an
uploadId
from the server - Upload Parts - Send file chunks with the
uploadId
- Complete - Tell the server to combine all parts
The example repository already implements this logic, however below is a walk through of the code to understand how it works.
Test your multipart upload route
Now that your routes are setup, you can test your multipart upload route by uploading a large file.
Start your development server
Start your development server by running the following command:
Your server should be running at http://localhost:4321/YOUR_BASE_PATH
.
Upload a large file
Navigate to the file uploader page and upload a large file. You should see the file appear in the list of files.

FAQs
How do I handle CORS requests for the upload route?
Since upload requests are made directly to the worker domain (not your Webflow Cloud domain), you need to handle CORS properly. Add these headers to your response:
If you’re looking to upload files from an authenticated user with session credentials, you’ll need to generate temporary upload URLs with embedded authentication tokens. Since CORS prevents passing session cookies directly, you can create a secure token that contains user information and embed it in the upload URL.
This approach involves:
- Generating a temporary upload URL with an embedded authentication token
- Validating the token on the upload endpoint
- Using the worker domain for the actual file upload
For a complete implementation example, see the authentication upload example in the upload branch, which demonstrates how to handle authenticated file uploads with proper CORS and security.
What's the difference between the BASE_URL
and ASSETS_PREFIX
environment variables?
What's the difference between the BASE_URL
and ASSETS_PREFIX
environment variables?
Both the BASE_URL
and ASSETS_PREFIX
environment variables are automatically set by Webflow Cloud to help with routing logic in your app. You can access these variables as you would any other environment variable in your app.
BASE_URL
is automatically set to the mount path of your environment (for example,/app
). This is useful for setting up redirects and other routing logic in your app.ASSETS_PREFIX
is set to the domain of the Worker your app is deployed to (for example,https://YOUR_ENV_HASH.wf-app-prod.cosmic.webflow.services
). This link is essential for uploading large files to your bucket, and serving files directly from your app. Because this link will always be a different domain than your app’s domain, you’ll need to handle CORS requests for the upload route.
Learn more about built in environment variables in Webflow Cloud.
Can I create presigned URLs to upload directly to my bucket?
No, presigned URLs require credentials that aren’t available in Webflow Cloud’s secure environment. Instead, use the multipart upload endpoints to upload files through your app’s API routes.
Can I expose a public bucket to the web?
No, public buckets aren’t supported in Webflow Cloud. All bucket access must go through your app’s API routes, which gives you control over access permissions and allows you to implement proper authentication and authorization.
Why do I get a 413 Content Too Large error when uploading to my bucket?
Likely the file being uploaded is hitting current Webflow Cloud request limits. You should upload these larger files through the multipart upload strategy.