Filestack integrates with Bolt.new using the Filestack JavaScript SDK — a drop-in file upload widget that handles the entire upload UX including source selection (Google Drive, Dropbox, Instagram), image editing, and progress tracking. Embed the Filestack Picker widget in your React component with your API key, configure accepted file types and transformations, and get back a CDN URL for every uploaded file. The picker widget works directly in Bolt's WebContainer preview.
Filestack in Bolt.new: Drop-In File Upload Widget with CDN Delivery
Filestack takes a different approach to file uploads than S3 or raw cloud storage: instead of providing storage infrastructure, it provides the upload experience — a polished, production-ready picker widget that handles file selection, image editing, progress tracking, cloud source authorization (Google Drive, Dropbox, Instagram, Flickr), and CDN upload in a single embeddable component. The typical Filestack integration is 10–20 lines of code. Building the same UX from scratch with S3 and your own UI would take days.
For Bolt.new developers, Filestack is particularly appealing because the entire upload flow works in the WebContainer preview without any backend setup. The Filestack JavaScript SDK communicates directly from the browser to Filestack's servers over HTTPS — no API route, no server, no TCP connection required during development. Add your Filestack API key, embed the Picker component, and users can upload files immediately. This makes Filestack one of the fastest integrations to ship in Bolt.
After upload, every file gets a permanent Filestack CDN URL that you store in your database. The real power comes from Filestack's transformation API: you can resize, crop, optimize, watermark, and convert files by appending parameters to the CDN URL — no additional processing pipeline, no AWS Lambda, no image processing library. For example, appending /resize=width:300,height:200,fit:crop/ to any image URL returns a cropped thumbnail version. This makes Filestack especially useful for user avatar uploads, product photos, and any image-heavy feature.
Integration method
Filestack's JavaScript SDK works directly in the browser — the Picker widget handles uploads from the user's device or cloud sources (Google Drive, Dropbox, Instagram, Facebook) and uploads them directly to Filestack's CDN without a server. Your Bolt app embeds the Picker as a React component using your Filestack API key. For secure operations (generating signed upload policies, server-side transformations), use a Next.js API route with your Filestack App Secret. The Picker widget works in Bolt's WebContainer preview immediately after adding your API key.
Prerequisites
- A Filestack account at filestack.com — free plan includes 5GB storage and 500 transformations/month
- Your Filestack API key from the Filestack dashboard (Dashboard → API Key)
- A Bolt.new project — Vite + React or Next.js both work; Next.js is needed only if you use server-side signed policies
- Optional: Filestack App Secret (from the dashboard) only if you implement security policies for restricted uploads
Step-by-step guide
Get Your Filestack API Key and Set Up Environment Variable
Get Your Filestack API Key and Set Up Environment Variable
Filestack uses a simple API key for client-side authentication. Unlike OAuth-based services, there is no multi-step authentication flow for basic uploads — just include your API key in the Picker initialization. Sign up at filestack.com, log into the dashboard, and your API key is displayed prominently on the main dashboard page. For security, Filestack's API key is a public key (it identifies your application, not a secret credential). You can safely expose it in client-side code with the VITE_ prefix for Vite projects. The API key grants upload permissions to your Filestack account — rate limiting and storage limits are enforced server-side by Filestack. If you need to restrict who can upload (prevent unauthorized uploads to your account), implement Filestack Security Policies using your App Secret — covered in step 4. The free Filestack plan (Starter) includes 5GB storage, 1,000 uploads per month, 500 transformations, and access to all cloud source connectors (Google Drive, Dropbox, Instagram). This is sufficient for development and low-traffic production apps. Paid plans (Growth $35/mo, Scale $149/mo) increase storage and transformation limits and add features like workflow automations.
Create a .env file with VITE_FILESTACK_API_KEY=your_filestack_api_key_here. For Next.js projects, add NEXT_PUBLIC_FILESTACK_API_KEY=your_key and FILESTACK_APP_SECRET=your_app_secret_here (only if using security policies — leave blank for basic uploads). Show me where to find these values in the Filestack dashboard.
Paste this in Bolt.new chat
1# .env2VITE_FILESTACK_API_KEY=your_filestack_api_key_here34# For Next.js projects:5NEXT_PUBLIC_FILESTACK_API_KEY=your_filestack_api_key_here67# Only needed for security policies (optional):8FILESTACK_APP_SECRET=your_app_secret_here910# Note: API key is a PUBLIC identifier, safe to expose client-side with VITE_ prefix.11# App Secret must NEVER be in client-side code — server-only.Pro tip: Filestack's free plan requires no credit card. The free tier gives you enough for development and low-traffic production. Upgrade only when you exceed 1,000 uploads per month or 5GB storage.
Expected result: Filestack API key is in your .env as VITE_FILESTACK_API_KEY. You can reference it in Vite components as import.meta.env.VITE_FILESTACK_API_KEY.
Install @filestack/react and Embed the Picker Widget
Install @filestack/react and Embed the Picker Widget
Filestack's React package (@filestack/react) provides pre-built components for the most common upload patterns. The two main components are PickerOverlay (opens as a modal overlay when triggered) and PickerInline (renders inline in your page layout). For most upload flows, PickerOverlay is the right choice — it opens on a button click and closes after upload completes. The Picker configuration object (options prop) controls all aspects of the upload experience. Key options: accept (array of MIME types or extensions), maxFiles (max number of files per upload session), maxSize (max file size in bytes), sources (which upload sources to show — local_file_system, googledrive, dropbox, instagram, facebook, url, imagesearch), imageMin / imageMax (pixel dimension constraints), transformations (built-in image editor features — crop, circle, rotate, filter). The onSuccess callback receives a PickerResponse object containing filesUploaded (array of PickerFileMetadata objects, each with handle, url, filename, mimetype, size, and more). The handle is the unique identifier for the file — store this in your database. The url is the full CDN URL. Both are permanent. Important WebContainer note: the Picker widget opens as a modal and communicates with Filestack's servers over HTTPS — this works perfectly in Bolt's WebContainer preview. The widget handles file selection UI, progress tracking, and upload entirely client-side. No server-side route is needed for basic uploads.
Install @filestack/react. Create a FilestackUploader React component that uses PickerOverlay from @filestack/react. Show an 'Upload Files' button that sets a boolean state to true to open the picker. Configure the Picker with: apikey from import.meta.env.VITE_FILESTACK_API_KEY, options: { accept: ['image/*', 'application/pdf'], maxFiles: 5, storeTo: { location: 'gcs', path: '/uploads/' } }, onSuccess callback that receives PickerResponse and calls an onUploadComplete prop with an array of {handle: string, url: string, filename: string, mimetype: string, size: number} objects extracted from filesUploaded, onError callback that shows an error toast with the error message. Style the trigger button with Tailwind: bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700.
Paste this in Bolt.new chat
1// components/FilestackUploader.tsx2import { useState } from 'react';3import { PickerOverlay } from '@filestack/react';45interface UploadedFile {6 handle: string;7 url: string;8 filename: string;9 mimetype: string;10 size: number;11}1213interface FilestackUploaderProps {14 onUploadComplete: (files: UploadedFile[]) => void;15 accept?: string[];16 maxFiles?: number;17 label?: string;18}1920export function FilestackUploader({21 onUploadComplete,22 accept = ['image/*', 'application/pdf'],23 maxFiles = 5,24 label = 'Upload Files',25}: FilestackUploaderProps) {26 const [isOpen, setIsOpen] = useState(false);27 const apikey = import.meta.env.VITE_FILESTACK_API_KEY;2829 return (30 <div>31 <button32 onClick={() => setIsOpen(true)}33 className="bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors"34 >35 {label}36 </button>3738 {isOpen && (39 <PickerOverlay40 apikey={apikey}41 onSuccess={(res) => {42 const files: UploadedFile[] = res.filesUploaded.map((f) => ({43 handle: f.handle,44 url: f.url,45 filename: f.filename,46 mimetype: f.mimetype,47 size: f.size,48 }));49 onUploadComplete(files);50 setIsOpen(false);51 }}52 onError={(err) => {53 console.error('Filestack upload error:', err);54 setIsOpen(false);55 }}56 onClose={() => setIsOpen(false)}57 pickerOptions={{58 accept,59 maxFiles,60 sources: ['local_file_system', 'googledrive', 'dropbox', 'url'],61 storeTo: {62 location: 'gcs',63 path: '/uploads/',64 },65 }}66 />67 )}68 </div>69 );70}Pro tip: Pass storeTo: { location: 'gcs', path: '/uploads/' } to organize files in a consistent path in Filestack's storage. Without this, files are stored at root level. Use different paths for different types: '/profiles/', '/documents/', '/products/' to keep your Filestack storage organized.
Expected result: The FilestackUploader component renders an 'Upload Files' button. Clicking it opens the Filestack Picker modal. After uploading, onUploadComplete receives the file handles and URLs. The widget works in Bolt's WebContainer preview.
Use Filestack's Transformation API for Image Processing
Use Filestack's Transformation API for Image Processing
Filestack's most powerful feature beyond the upload widget is its transformation API: you can resize, crop, convert, watermark, and optimize any uploaded image by modifying the CDN URL. No backend processing required — transformations are applied by Filestack's CDN servers on-the-fly and cached for subsequent requests. Transformation URL format: https://cdn.filestackcontent.com/[transformations]/[handle]. Multiple transformations are chained with / separators. Common transformations: - resize=width:300,height:300 — resize to 300x300 (may distort) - resize=width:300,height:300,fit:crop — resize and crop to exactly 300x300 - resize=width:600 — resize to 600px wide, maintain aspect ratio - quality=value:80 — compress to 80% quality (JPEG) - output=format:webp — convert to WebP format - rotate=deg:90 — rotate 90 degrees - flip — flip horizontally - watermark=file:https://example.com/logo.png,size:15,position:bottom-right — add watermark - circle — crop to circle (great for avatars) - blur=amount:5 — apply Gaussian blur Create a utility function that generates transformation URLs from a Filestack handle and a configuration object. This makes it easy to generate thumbnails, medium-size images, and full-size images from the same handle stored in your database.
Create a lib/filestack-transforms.ts utility that exports transformation URL helpers. Export these functions: getThumbnail(handle: string, size?: number): string — returns URL with resize=width:{size},height:{size},fit:crop/quality=value:80 (default size 200). getMedium(handle: string, width?: number): string — returns resize=width:{width}/quality=value:85 (default 600px). getFull(handle: string): string — returns quality=value:90 URL. getCircleAvatar(handle: string, size?: number): string — returns resize=width:{size},height:{size},fit:crop/circle URL. All return https://cdn.filestackcontent.com/{transforms}/{handle} format. Also export getDownloadUrl(handle: string, filename?: string): string using the /content/{handle}?dl=filename format.
Paste this in Bolt.new chat
1// lib/filestack-transforms.ts2const CDN = 'https://cdn.filestackcontent.com';34function buildUrl(handle: string, transforms: string): string {5 return `${CDN}/${transforms}/${handle}`;6}78export const filestack = {9 // 200x200 square thumbnail (default)10 thumbnail(handle: string, size = 200): string {11 return buildUrl(handle, `resize=width:${size},height:${size},fit:crop/quality=value:80`);12 },1314 // Responsive width with quality optimization15 medium(handle: string, width = 600): string {16 return buildUrl(handle, `resize=width:${width}/quality=value:85`);17 },1819 // Full size with mild compression20 full(handle: string): string {21 return buildUrl(handle, 'quality=value:90');22 },2324 // Circular crop (perfect for avatars)25 avatar(handle: string, size = 120): string {26 return buildUrl(handle, `resize=width:${size},height:${size},fit:crop/circle`);27 },2829 // WebP conversion for modern browsers30 webp(handle: string, width?: number): string {31 const resize = width ? `resize=width:${width}/` : '';32 return buildUrl(handle, `${resize}output=format:webp/quality=value:85`);33 },3435 // Direct download link36 download(handle: string, filename?: string): string {37 const dl = filename ? `?dl=${encodeURIComponent(filename)}` : '?dl=true';38 return `${CDN}/content/${handle}${dl}`;39 },4041 // Raw CDN URL42 raw(handle: string): string {43 return `${CDN}/${handle}`;44 },45};4647// Usage example:48// filestack.thumbnail('AbC123', 100) → tiny square49// filestack.avatar('AbC123') → circular profile photo50// filestack.medium('AbC123', 800) → blog post hero imagePro tip: Store only the Filestack handle (the short ID like 'AbC123XY') in your database, not the full CDN URL. The CDN URL format may change, but the handle is permanent. Generate different URLs from the handle at render time using your transform helpers.
Expected result: The filestack transform helpers generate correct CDN transformation URLs from handles. Images are served at the requested size and quality from Filestack's CDN.
Secure Uploads with Server-Side Policies (Optional)
Secure Uploads with Server-Side Policies (Optional)
By default, any JavaScript application with your Filestack API key can upload files to your account. For production apps where you need to restrict uploads — prevent unauthorized users from uploading, limit file types at the API level, or set per-user upload quotas — implement Filestack Security Policies. Filestack Security works by generating a policy and signature on your server using your App Secret. The policy is a JSON object specifying what is allowed (expiry time, maximum file size, allowed MIME types, allowed operations). The signature is an HMAC-SHA256 hash of the base64-encoded policy using your App Secret. You pass both policy and signature to the Picker instead of just the API key. Since the policy must be signed server-side (the App Secret must never reach the client), create a Next.js API route that generates a fresh policy+signature pair. Call this endpoint before opening the Picker and pass the returned values as pickerOptions.policy and pickerOptions.signature. Policies have an expiry time (set to 30–60 minutes) — generate a new policy each time the user opens the Picker. This security layer is optional for most Bolt apps — basic API key authentication is sufficient if you trust your users. Implement Security Policies for apps handling sensitive files, apps with paid upload plans where you need to prevent abuse, or apps with strict compliance requirements.
Create a Next.js API route at app/api/filestack/policy/route.ts that generates a Filestack security policy and signature. The policy should allow: handle (read any file), store (upload new files), convert (transformations). Set expiry to now + 1 hour. Encode the policy object as base64url. Sign with HMAC-SHA256 using FILESTACK_APP_SECRET from env. Return {policy: string, signature: string}. The Picker component should call this endpoint on mount and pass policy and signature to the PickerOverlay via pickerOptions.
Paste this in Bolt.new chat
1// app/api/filestack/policy/route.ts2import { NextResponse } from 'next/server';3import crypto from 'crypto';45export async function GET() {6 const appSecret = process.env.FILESTACK_APP_SECRET;7 if (!appSecret) {8 return NextResponse.json({ error: 'Filestack App Secret not configured' }, { status: 500 });9 }1011 const expiry = Math.floor(Date.now() / 1000) + 3600; // 1 hour from now1213 const policyObject = {14 expiry,15 call: ['read', 'store', 'convert', 'pick', 'run_workflow'],16 maxSize: 20 * 1024 * 1024, // 20MB max file size17 };1819 const policy = Buffer.from(JSON.stringify(policyObject)).toString('base64url');20 const signature = crypto21 .createHmac('sha256', appSecret)22 .update(policy)23 .digest('hex');2425 return NextResponse.json({ policy, signature });26}2728// In your FilestackUploader component (secure version):29// const [security, setSecurity] = useState<{policy: string; signature: string} | null>(null);30// useEffect(() => {31// fetch('/api/filestack/policy').then(r => r.json()).then(setSecurity);32// }, []);33//34// Then pass to PickerOverlay:35// pickerOptions={{ ...options, policy: security?.policy, signature: security?.signature }}Pro tip: Regenerate the security policy each time the user opens the Picker by calling /api/filestack/policy before setting isOpen to true. Do not cache policies for extended periods — a 1-hour expiry policy generated once per session is sufficient and limits exposure window if a policy is intercepted.
Expected result: Server-side security policy generation works. The Picker includes policy and signature in its configuration, restricting uploads to authenticated users within the policy constraints.
Common use cases
User Avatar Upload with Automatic Cropping
Implement a profile photo upload flow where users crop their photo to a square aspect ratio during upload. Filestack's Picker has a built-in image editor with crop, rotate, and filter tools. Configure the Picker to require a 1:1 crop ratio and accept only image files. The uploaded image is stored on Filestack's CDN and you use the transformation API to generate thumbnail URLs at the exact dimensions your UI needs.
Add a profile photo upload feature using Filestack. Install @filestack/react. Create an AvatarUploader component that uses the PickerOverlay from @filestack/react with options: accept ['image/*'], maxFiles: 1, transformations: {crop: {aspectRatio: 1, force: true}}. On successful upload, the onSuccess callback receives a PickerFileMetadata object with handle property (the Filestack file handle). Store the handle in state and display the avatar using the Filestack CDN URL: https://cdn.filestackcontent.com/{handle}. For a 120x120 thumbnail, use the transform URL: https://cdn.filestackcontent.com/resize=width:120,height:120,fit:crop/{handle}. Read VITE_FILESTACK_API_KEY from environment variables.
Copy this prompt to try it in Bolt.new
Multi-Source Document Upload for Content Management
Allow users to upload documents from multiple sources: their device, Google Drive, Dropbox, or by URL. Filestack's Picker supports all these sources natively without additional OAuth setup. Configure accepted file types to PDFs and Office documents. Store Filestack file handles in your database and generate optimized preview thumbnails using the transformation API.
Build a document upload feature using Filestack with multiple sources. Use PickerOverlay with: accept ['application/pdf', '.docx', '.xlsx'], sources: ['local_file_system', 'googledrive', 'dropbox', 'url'], maxFiles: 10, storeTo: {location: 'gcs'} (or leave default Filestack storage). On upload, collect file handles from the PickerResponse.filesUploaded array. For each file, store {handle, filename, mimetype, size} in Supabase documents table. Show uploaded documents in a list with filename, size, and a 'Download' link using https://cdn.filestackcontent.com/{handle}. Use VITE_FILESTACK_API_KEY from env.
Copy this prompt to try it in Bolt.new
Product Image Gallery with Transformation API
Build a product image upload and gallery system where merchants upload product photos. Filestack automatically generates multiple size variants via URL transformations: thumbnail for listings, medium for product cards, and full-size for the lightbox. No image processing pipeline or Lambda function needed — transformations happen via CDN URL parameters.
Create a product image gallery upload system using Filestack. Use PickerOverlay accepting images only, up to 8 files per product. Store the Filestack handle (not the full URL) in the product's images array in Supabase. Create a Filestack helper function that generates size variants from a handle: thumbnail (200x200 crop): https://cdn.filestackcontent.com/resize=width:200,height:200,fit:crop/quality=value:80/{handle}, medium (600px wide): https://cdn.filestackcontent.com/resize=width:600/quality=value:85/{handle}, full: https://cdn.filestackcontent.com/quality=value:90/{handle}. Build a ProductImageGallery component that shows a scrollable row of medium-size images with click-to-expand lightbox showing the full-size version.
Copy this prompt to try it in Bolt.new
Troubleshooting
Filestack Picker opens but files fail to upload with a generic error
Cause: The API key is incorrect, the account's upload limit has been exceeded (free plan: 1,000 uploads/month), or the storeTo configuration specifies a cloud storage provider not configured in your Filestack account.
Solution: Verify VITE_FILESTACK_API_KEY matches exactly what's shown in the Filestack dashboard (Dashboard → API Key). Check your Filestack account usage in the dashboard. For storeTo issues, either remove storeTo to use Filestack's default storage or configure the cloud storage connection in the Filestack dashboard under Storage Providers.
Picker widget doesn't open when clicking the trigger button — no modal appears
Cause: The @filestack/react package requires the PickerOverlay to be conditionally rendered in the DOM to open. If isOpen is true but the Picker doesn't appear, it may be a z-index conflict with another modal or overlay on the page, or a rendering issue with the conditional.
Solution: Ensure the PickerOverlay is rendered at the root level of your component, not nested inside a dialog or another positioned element. Check browser console for errors. Verify the @filestack/react package installed correctly by checking node_modules/@filestack/react exists.
1// Render PickerOverlay at the top of your component return:2return (3 <div>4 <button onClick={() => setIsOpen(true)}>Upload</button>5 {/* PickerOverlay at top level, not nested in positioned containers */}6 {isOpen && <PickerOverlay apikey={apikey} onClose={() => setIsOpen(false)} />}7 </div>8);Transformation URLs return 400 Bad Request or show an error image
Cause: Transformation syntax is incorrect — a common mistake is using spaces or incorrect parameter names. Filestack transformations are case-sensitive and use specific parameter formats.
Solution: Verify transformation syntax matches Filestack documentation exactly: resize=width:300,height:200 (no spaces, colon separators). Chain transforms with / between them: resize=width:300/quality=value:80/{handle}. Test transformation URLs directly in the browser — the error response includes a description of which parameter is invalid.
1// Correct transformation URL format:2// https://cdn.filestackcontent.com/resize=width:300,height:300,fit:crop/quality=value:80/HANDLE34// Common mistakes:5// WRONG: resize=width:300, height:300 (space after comma)6// WRONG: resize=Width:300 (capital W)7// WRONG: quality=80 (missing 'value:' prefix)8// CORRECT: quality=value:809// CORRECT: resize=width:300,height:300,fit:cropBest practices
- Store only the Filestack handle (short unique ID) in your database, not the full CDN URL — handles are permanent, URLs may change, and you can generate any transformation URL from the handle at render time
- Use the VITE_ prefix for your Filestack API key in Vite projects — unlike secret keys (S3, Stripe), Filestack's API key is a public identifier safe for client-side use
- Implement Filestack Security Policies with server-side signing for production apps where you need to restrict uploads — basic API key authentication is fine for development and low-trust environments
- Configure maxSize in Picker options to limit file sizes and prevent users from uploading files that exceed your storage plan limits or cause performance issues
- Use the transformation API to generate multiple size variants from a single stored handle rather than storing multiple files — thumbnail, medium, and full-size all served from one source file with zero storage overhead
- Set explicit accept types in Picker configuration to match what your app handles — don't accept all file types if you only process images or only process PDFs
- The Filestack Picker works in Bolt's WebContainer preview — test the full upload flow during development without needing to deploy first, unlike OAuth-based storage integrations
Alternatives
AWS S3 is raw object storage where you build your own upload UI; Filestack provides the entire upload experience as a pre-built widget with multi-source selection — S3 is more flexible and cheaper at scale, Filestack is faster to integrate.
Dropbox gives users access to their existing stored files; Filestack handles new file uploads from device or cloud sources into your app's storage — use Dropbox to import user's existing files, Filestack to collect new uploads.
Canva is a design creation tool while Filestack is a file upload platform — Filestack is the right choice for collecting and transforming files users want to upload to your app.
Frequently asked questions
Does Filestack work in Bolt's WebContainer preview?
Yes — the Filestack Picker widget works directly in the Bolt preview because it communicates with Filestack's CDN servers over HTTPS. There are no TCP connections, no incoming webhooks, and no native modules involved. Add your VITE_FILESTACK_API_KEY to .env and the upload widget functions immediately. This makes Filestack one of the easiest integrations to test in Bolt's WebContainer.
Is it safe to expose the Filestack API key in client-side code?
The Filestack API key is a public identifier (like a Stripe publishable key) — it identifies your app to Filestack but is not a secret. Anyone who finds it can upload files to your Filestack account, which could exhaust your monthly upload quota. For basic prototypes and low-traffic apps, exposing the API key is acceptable. For production apps with real costs at stake, implement Security Policies with server-side signing to restrict who can upload.
Where are uploaded files stored and how long are they kept?
By default, Filestack stores uploaded files on Filestack's own CDN infrastructure. Files are stored indefinitely as long as your account is active and within your plan's storage limit. For production apps, you can configure Filestack to store uploads in your own AWS S3, Google Cloud Storage, or Azure Blob Storage using the storeTo option — this gives you full control over file retention and costs.
Can I use Filestack transformations on files uploaded from external URLs?
Yes. Filestack has a fetch transformation that retrieves a file from any public URL and applies transformations: https://cdn.filestackcontent.com/resize=width:400/https://example.com/photo.jpg. This caches the external image on Filestack's CDN and applies the transformation. Useful for transforming user-provided image URLs without uploading them to your storage first.
How do I delete files from Filestack storage?
Use the Filestack Management API to delete files by handle. Send a DELETE request to https://www.filestackapi.com/api/file/{handle}?key={apikey}. For files stored in your own S3 or GCS bucket via storeTo, delete them directly from your cloud storage bucket — Filestack's CDN cache will eventually expire. Implement a delete API route in your Next.js app that calls the Filestack Management API server-side using your API key, never exposing the delete endpoint to the browser.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation