Connect Filestack to Lovable using your Filestack API key in Lovable Cloud Secrets and a Supabase Edge Function for server-side processing operations. Filestack's JavaScript SDK can be used client-side for its upload widget (the API key is safe to expose in the widget), while transformation operations and sensitive API calls route through the Edge Function. Filestack adds automatic image optimization, format conversion, CDN delivery, and virus scanning on top of file uploads.
Filestack Integration in Lovable: Intelligent File Upload and Processing
Filestack is fundamentally different from raw object storage services like S3, B2, or Wasabi. It is not just a place to store files — it is a file upload and processing pipeline. When a user uploads through Filestack, the file is automatically scanned for viruses, stored on Filestack's CDN, and made available for on-the-fly transformations via transformation URLs. An image uploaded once can be served as any size, format, or quality level by simply changing the URL parameters.
For Lovable apps, this means you handle file uploads once and let Filestack's transformation engine handle all the derivative images and formats your UI needs. A user uploads a profile photo → Filestack stores it → your app serves it as a 100px thumbnail, a 300px medium image, and a full-size version all from the same stored file by using different transformation URL parameters. No server-side image processing code required.
Filestack's architecture also differs from raw storage in its pickup widget: the Filestack Picker is a fully-featured file upload UI that handles drag-and-drop, clipboard paste, URL imports, and 20+ cloud source integrations (Google Drive, Dropbox, OneDrive, Instagram, etc.) in a ready-made React component. Embedding the Picker handles everything from file selection through upload completion, returning a Filestack file handle URL that your app stores and uses for display and transformations.
Integration method
Filestack integrates with Lovable using a hybrid approach: the Filestack upload widget (using the public API key) handles browser-side file picking and uploading directly to Filestack's infrastructure, while a Supabase Edge Function handles server-side transformation operations, signed security policies, and webhook processing. The API secret and security policy generation always stay server-side in the Edge Function, while the client-side API key is safe to use in the frontend.
Prerequisites
- A Filestack account at filestack.com (free tier: 100 transformations/month, 500 MB storage, 500 uploads/month)
- An active Lovable project with Lovable Cloud/Supabase enabled
- Access to Lovable's Cloud tab → Secrets panel
- Your Filestack API Key from the Filestack dashboard (Dashboard → API Keys)
Step-by-step guide
Get your Filestack API key and API secret
Get your Filestack API key and API secret
Log in to your Filestack account at app.filestack.com. The main dashboard shows your API Key prominently — it is a short alphanumeric string like AHZb0pCeRvK8dpW7RqmTzC. This is your public API key, safe to use in client-side code and in the Filestack Picker widget configuration. Unlike most API keys, the Filestack API key is intentionally public-facing — it identifies your Filestack account but does not grant destructive API access by itself. For security-restricted operations (generating signed URLs, processing workflows, webhook verification), you also need the API Secret. Find it by going to your Filestack Dashboard → Security → Security Policy. The API Secret is the longer key shown there. This key is sensitive — treat it like a password. It must only be used in your Edge Function via Cloud Secrets, never in frontend code. Also note your Filestack Security settings. By default, Filestack allows unrestricted access to any uploaded file via its CDN URL. For production apps with user-uploaded content, enable security policies in the Filestack dashboard (Security → Policies tab). With security enabled, every file access requires a signed policy — the Edge Function generates these on-demand. Start with security disabled during development for simpler testing, then enable it before going to production. Optionally, configure your Filestack application's storage settings: in the Dashboard → App Settings, you can configure whether Filestack stores files in its own S3 infrastructure (default) or in your own S3 bucket (Intelligent Ingestion). Using your own S3 bucket keeps you in control of the files long-term but requires additional AWS configuration.
Pro tip: If you plan to enable Filestack security policies before launch, test the security policy generation in your Edge Function early — debugging signed URL issues in production is harder than in development.
Expected result: You have your Filestack API Key (for the client-side Picker widget) and API Secret (for the Edge Function). You understand whether Filestack security policies are enabled or disabled for your account.
Store credentials in Cloud Secrets and install the Filestack SDK
Store credentials in Cloud Secrets and install the Filestack SDK
Store your Filestack API Secret in Lovable's Cloud Secrets. Open the Cloud tab in Lovable, click Secrets, and add FILESTACK_API_SECRET with your API secret value. You do not need to add the API key as a secret since it is safe to use in frontend code — but you may want to add it as NEXT_PUBLIC_FILESTACK_API_KEY or VITE_FILESTACK_API_KEY so it is configured in one place even if technically safe in source code. Next, install the Filestack JavaScript SDK in your Lovable project. Use the Lovable chat to request the package installation: 'Add the filestack-js npm package to the project as a dependency.' Lovable updates package.json and the package becomes available for import in your React components. The SDK provides both the Picker component and utility functions for constructing transformation URLs. For the Edge Function, Filestack's Node.js SDK (@filestack/sdk) can be imported in Deno using the npm: specifier. However, for most Edge Function use cases (generating security policies, calling the Filestack API), you can use standard fetch calls with the API secret rather than importing the full SDK — keeping the Edge Function lightweight. The Filestack Picker is typically loaded either as an npm package import or via a script tag from Filestack's CDN. For Lovable React projects, the npm package approach is cleaner: import { PickerOverlay } from 'filestack-react' and use it as a React component in your upload UI. The PickerOverlay component handles the full upload flow and calls an onSuccess callback with the uploaded file's URL and handle.
Add filestack-js and filestack-react to my project's package.json. Then create a FileUpload component that uses the Filestack PickerOverlay to let users upload files. Configure the Picker with my API key (store it as a Vite env variable VITE_FILESTACK_API_KEY). On successful upload, call an onUpload callback with the file handle and CDN URL. Show the Picker as a modal overlay triggered by an upload button.
Paste this in Lovable chat
Pro tip: Filestack's Picker supports a fromSources configuration that controls which upload sources are shown (local, url, googledrive, dropbox, onedrive, etc.). For a clean user experience, only show the sources relevant to your app — remove cloud source integrations you do not need.
Expected result: The filestack-js and filestack-react packages are installed. A FileUpload component exists that shows the Filestack Picker and calls onUpload with the file URL after successful upload. The API key is configured as a Vite environment variable.
Build the Filestack Edge Function for security and transformations
Build the Filestack Edge Function for security and transformations
The Edge Function handles the server-side operations that require the API secret: generating signed security policies for restricted file access, and calling Filestack's workflow API for server-side processing operations. For basic Filestack integrations without security policies enabled, this Edge Function is optional — but it becomes necessary as soon as you enable Filestack security. Filestack security policies consist of a policy JSON object (specifying which operations are allowed, expiry time, and optionally which file handles or paths are allowed) and an HMAC-SHA256 signature of that policy computed using your API secret. The signed policy + signature combination is appended to CDN URLs or API calls to authorize restricted operations. The Edge Function takes a request specifying what operation the user needs to perform (view a specific file, upload, transform), computes the policy and signature, and returns them to the frontend. The frontend then appends the policy and signature to Filestack URLs or API calls. This keeps the secret entirely server-side while giving the frontend the tokens it needs for authorized access. For image transformation, Filestack transformation URLs do not require a secret — they are publicly accessible URL parameters on the Filestack CDN URL. Construct them in the frontend directly by manipulating the CDN URL string. Only add security policy tokens to transformation URLs if Filestack security is enabled on your account.
Create a Supabase Edge Function at supabase/functions/filestack-security/index.ts that generates signed Filestack security policies. The function should: 1) Read FILESTACK_API_SECRET from environment variables. 2) Accept a request body with fields: operation (view/pick/transform), handle (optional, specific file handle to restrict), expiresIn (seconds, default 3600). 3) Create a policy object: { call: [operation], expiry: current_epoch + expiresIn, handle: handle if provided }. 4) Base64url-encode the JSON policy. 5) Compute HMAC-SHA256 of the encoded policy using the API secret. 6) Return { policy: encodedPolicy, signature: hmacHex }. Include CORS headers.
Paste this in Lovable chat
1import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'2import { encodeBase64 } from 'https://deno.land/std@0.168.0/encoding/base64.ts'34const corsHeaders = {5 'Access-Control-Allow-Origin': '*',6 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',7 'Access-Control-Allow-Methods': 'POST, OPTIONS',8}910async function hmacSha256(secret: string, message: string): Promise<string> {11 const encoder = new TextEncoder()12 const key = await crypto.subtle.importKey(13 'raw',14 encoder.encode(secret),15 { name: 'HMAC', hash: 'SHA-256' },16 false,17 ['sign']18 )19 const sig = await crypto.subtle.sign('HMAC', key, encoder.encode(message))20 return Array.from(new Uint8Array(sig)).map(b => b.toString(16).padStart(2, '0')).join('')21}2223serve(async (req) => {24 if (req.method === 'OPTIONS') {25 return new Response('ok', { headers: corsHeaders })26 }2728 const apiSecret = Deno.env.get('FILESTACK_API_SECRET')29 if (!apiSecret) {30 return new Response(31 JSON.stringify({ error: 'FILESTACK_API_SECRET not configured' }),32 { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }33 )34 }3536 try {37 const { operation = 'read', handle, expiresIn = 3600 } = await req.json()3839 const expiry = Math.floor(Date.now() / 1000) + expiresIn40 const policyObj: Record<string, unknown> = {41 call: [operation],42 expiry,43 }44 if (handle) policyObj.handle = handle4546 const policyJson = JSON.stringify(policyObj)47 const policyEncoded = encodeBase64(policyJson)48 .replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '')4950 const signature = await hmacSha256(apiSecret, policyEncoded)5152 return new Response(53 JSON.stringify({ policy: policyEncoded, signature }),54 { headers: { ...corsHeaders, 'Content-Type': 'application/json' } }55 )56 } catch (err) {57 return new Response(58 JSON.stringify({ error: err instanceof Error ? err.message : 'Unknown error' }),59 { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }60 )61 }62})Pro tip: When generating security policies, always set a reasonable expiry time. For file viewing in the browser, 1-4 hours is appropriate. For upload sessions, 30 minutes is sufficient. Avoid very long expiry times (days/weeks) — if a signed URL is shared or leaked, the shorter the expiry, the more limited the damage.
Expected result: The filestack-security Edge Function is deployed. When called with an operation and optional handle, it returns a policy and signature that can be appended to Filestack CDN URLs or API calls for authorized access.
Implement transformation URLs for image optimization
Implement transformation URLs for image optimization
Filestack's most powerful feature for Lovable apps is transformation URLs — on-the-fly image processing without any server-side code. A Filestack CDN URL looks like https://cdn.filestackcontent.com/HANDLE. By inserting transformation parameters between the base URL and the handle, you get different processed versions of the same file. Common transformation operations useful in Lovable apps: resize (width, height, fit mode) for generating different image sizes; output format conversion (output=format:webp) for converting JPEGs and PNGs to WebP for better compression; quality reduction (quality=value:75) for balancing file size and visual quality; smart crop (crop=faces) for intelligent face-centered cropping for profile photos; and compress for automatic optimization without explicit quality setting. Construct transformation URLs in your React components by building a transformation chain string. The chain is inserted as URL segments: https://cdn.filestackcontent.com/resize=width:400,height:300,fit:crop/output=format:webp/quality=value:80/HANDLE. This single URL serves a 400x300px WebP image at 80% quality — all processed and cached by Filestack's CDN from the original uploaded file. For profile photos, a common transformation chain is: resize=width:200,height:200,fit:crop/crop=faces:true/output=format:webp — this resizes to 200x200, crops to the face, and outputs as WebP. Build a utility function in your Lovable project that constructs these URLs from a Filestack handle and a size/format specification, then use it consistently throughout all image display components.
Create a utility function in src/lib/filestack.ts that generates Filestack transformation URLs. The function should accept a handle (or full CDN URL), and an options object with: width, height, format ('webp'|'jpeg'|'png'), quality (0-100), fit ('crop'|'scale'|'fill'), and faceCrop (boolean). It should return the complete Filestack transformation URL. Also create TypeScript components: FilestackAvatar (accepts handle, size in px, always circles with face crop), FilestackImage (accepts handle, width, height, fit mode), and FilestackThumbnail (accepts handle, 80px square thumbnail). All should use WebP output by default.
Paste this in Lovable chat
1// src/lib/filestack.ts2const FILESTACK_CDN = 'https://cdn.filestackcontent.com'34interface TransformOptions {5 width?: number6 height?: number7 format?: 'webp' | 'jpeg' | 'png' | 'auto'8 quality?: number9 fit?: 'crop' | 'scale' | 'fill' | 'max'10 faceCrop?: boolean11}1213export function getFilestackUrl(handle: string, options: TransformOptions = {}): string {14 // Extract handle if full URL was passed15 const h = handle.includes('cdn.filestackcontent.com')16 ? handle.split('/').pop() ?? handle17 : handle1819 const transforms: string[] = []2021 if (options.width || options.height) {22 const parts = []23 if (options.width) parts.push(`width:${options.width}`)24 if (options.height) parts.push(`height:${options.height}`)25 if (options.fit) parts.push(`fit:${options.fit}`)26 transforms.push(`resize=${parts.join(',')}`)27 }2829 if (options.faceCrop) {30 transforms.push('crop=faces:true')31 }3233 const fmt = options.format ?? 'webp'34 if (fmt !== 'auto') {35 transforms.push(`output=format:${fmt}`)36 }3738 if (options.quality) {39 transforms.push(`quality=value:${options.quality}`)40 }4142 const chain = transforms.length > 0 ? transforms.join('/') + '/' : ''43 return `${FILESTACK_CDN}/${chain}${h}`44}4546export function getAvatarUrl(handle: string, sizePx: number): string {47 return getFilestackUrl(handle, {48 width: sizePx * 2, // 2x for retina49 height: sizePx * 2,50 fit: 'crop',51 faceCrop: true,52 format: 'webp',53 quality: 85,54 })55}5657export function getThumbnailUrl(handle: string): string {58 return getFilestackUrl(handle, { width: 160, height: 160, fit: 'crop', format: 'webp', quality: 75 })59}Pro tip: Filestack CDN caches transformed images — the first request for a specific transformation URL may be slower (Filestack processes the image), but subsequent requests for the same URL are served instantly from CDN cache. This means transformation URL patterns should be stable across page loads.
Expected result: Transformation utility functions are available in the project. React components using FilestackImage, FilestackAvatar, and FilestackThumbnail render correctly with appropriate sizes and WebP format. Image quality is visually good and file sizes are significantly smaller than the originals.
Common use cases
Profile photo upload with automatic resizing and optimization
Replace a basic file input for avatar/profile photo uploads with Filestack's Picker component. Users can upload from their device, Google Drive, or by pasting a URL. Filestack handles virus scanning and CDN storage. Display the profile photo using Filestack transformation URLs that automatically serve the right size and WebP format for optimal performance.
Add a profile photo upload feature using Filestack. Show the current avatar (circular, 96px) with a camera icon overlay that opens the Filestack Picker when clicked. Configure the Picker to accept only images, maximum 10 MB. After upload, save the Filestack file URL to the user's profile in Supabase. Display the avatar using a Filestack transformation URL that serves a 192px WebP image (for 2x retina): replace 'cdn.filestackcontent.com/' with 'cdn.filestackcontent.com/output=format:webp/resize=width:192/' in the CDN URL.
Copy this prompt to try it in Lovable
Document upload with format conversion and preview generation
Build a document management feature where users upload PDFs, Word documents, or images that Filestack automatically converts to a consistent format. Use Filestack's document conversion API to generate PDF previews from Word files, or image previews from the first page of PDFs, without any server-side processing infrastructure.
Create a document upload component using Filestack. Accept PDF, Word (DOCX), and Excel (XLSX) files up to 50 MB. After upload, store the Filestack handle in a Supabase documents table with metadata. For each document in the list view, generate a thumbnail preview by using the Filestack preview transformation URL. Add a 'Download as PDF' button that constructs a Filestack conversion URL to convert the original document to PDF format. Use the Edge Function to generate a signed Filestack URL that expires in 1 hour for secure document access.
Copy this prompt to try it in Lovable
Product image upload with automatic optimization for an e-commerce catalog
E-commerce product listings require multiple image sizes — thumbnails, product grid images, full-size detail views, zoom images — all optimized for web performance. Filestack stores the original image once and serves any derivative via transformation URLs, eliminating the need for server-side image processing or storing multiple versions.
Build a product image upload system using Filestack. Sellers can upload up to 10 product images. Display images in a reorderable grid with drag-and-drop. Store Filestack CDN URLs in Supabase product_images table. For display: use transformation URLs to serve 400px WebP for the grid thumbnail and 800px WebP for the detail view. Generate a Filestack transformation that adds a white background to images with transparent areas. Add a 'Remove Background' button that calls the Filestack Smart Crop API.
Copy this prompt to try it in Lovable
Troubleshooting
Filestack Picker opens but shows a blank white screen or JavaScript error
Cause: The Filestack API key is missing or incorrect, or the filestack-react package version is incompatible with the installed filestack-js version. Also occurs when the Picker is rendered before the DOM is fully mounted.
Solution: Verify the VITE_FILESTACK_API_KEY environment variable is set correctly in your Lovable project (visible in the Vite build as import.meta.env.VITE_FILESTACK_API_KEY). Ensure filestack-react and filestack-js versions are compatible (check the filestack-react readme for peer dependency requirements). Wrap the PickerOverlay in a state-controlled boolean: only render it when a button is clicked, not on initial component mount.
Filestack transformation URLs return 403 or redirect to an error page
Cause: If Filestack security is enabled on your account, all transformation URLs require a signed policy and signature appended. Without them, requests are rejected with 403. Also occurs if the file handle is invalid or the file was deleted from Filestack.
Solution: If security is enabled: call the filestack-security Edge Function to get a policy and signature, then append them as URL query parameters: ?policy=ENCODED_POLICY&signature=HMAC_SIG. If security is not intentionally enabled, check your Filestack dashboard → Security to verify it is off. For invalid handles, verify the handle value stored in Supabase matches the actual file handle returned by the Picker's onSuccess callback.
Uploaded files are accessible immediately after upload but disappear after a few days
Cause: Filestack's free tier has storage retention limits — files may be deleted after 30 days on the free plan. This is expected behavior on the free tier.
Solution: Upgrade to a paid Filestack plan for persistent storage, or configure Filestack to store files in your own S3 bucket (Filestack → App Settings → Storage). Using your own S3 bucket as the backend storage means files persist as long as they exist in your S3 bucket, independent of Filestack's plan limits. Files uploaded to your own S3 via Filestack remain accessible through standard S3 or Filestack's CDN indefinitely.
Best practices
- Use Filestack transformation URLs for all image display rather than serving original uploaded files — transformation URLs save bandwidth and provide optimal quality-to-size ratios automatically.
- Store only the Filestack file handle (the short alphanumeric ID) in your Supabase database, not the full CDN URL — construct the URL dynamically using the handle, so changing transformation parameters requires no database migration.
- Keep the Filestack API key in a Vite environment variable (VITE_ prefix) rather than hardcoded — it is technically safe in client code but centralizing it makes rotation easier.
- Keep the Filestack API secret exclusively in Cloud Secrets and only use it in the Edge Function for policy generation — never in frontend code.
- Enable Filestack security policies before going to production for any app with user-uploaded content — unrestricted CDN access to uploaded files means any file handle can be accessed publicly.
- Request WebP format in all transformation URLs — WebP is 25-35% smaller than JPEG at equivalent quality, significantly improving page load times.
- Implement client-side file type and size validation before opening the Picker — catching large files or wrong formats early prevents wasted upload bandwidth.
Alternatives
AWS S3 stores files without processing — use it when you need raw storage without image transformations, or when you want direct control of storage costs at scale.
Dropbox provides user-managed file sync and sharing rather than upload-and-transform functionality — better for apps where users need to manage their own cloud file collections.
Lovable Cloud Storage handles basic file upload and storage with no processing capabilities — use Filestack when you need image optimization, CDN delivery, or format conversion.
Frequently asked questions
Is it safe to put the Filestack API key in frontend React code?
Yes, intentionally. Filestack designed its API key to be used in client-side code — it identifies your Filestack account for the upload widget but does not grant access to manage or delete your stored files by itself. For operations requiring authorization (deleting files, accessing security-policy-protected files), the API Secret is needed, which must stay in your Edge Function via Cloud Secrets. Think of the API key as a Filestack 'username' and the API Secret as the 'password'.
How does Filestack compare to using Lovable Cloud Storage for image uploads?
Lovable Cloud Storage (Supabase Storage) stores files with no processing capabilities. Filestack adds automatic image optimization, on-the-fly resizing via transformation URLs, WebP conversion, virus scanning, and multi-source uploads (Google Drive, Dropbox, URL import). For apps that display images at multiple sizes (profile photos, product images, media galleries), Filestack's transformation URLs eliminate the need for server-side image processing code, saving significant development time.
What happens to Filestack files if I cancel my Filestack subscription?
Files stored in Filestack's own infrastructure become inaccessible when the subscription lapses. To avoid this risk, configure Filestack to use your own S3 bucket as the backend storage (Filestack → App Settings → Intelligent Ingestion). With this configuration, files are stored in your S3 bucket directly and remain accessible even if you stop using Filestack's CDN and processing features.
Does Filestack support video upload and processing?
Yes. Filestack handles video uploads through the same Picker widget and stores them to the CDN. Video transformation capabilities are more limited than image transformations — Filestack can generate thumbnails from videos and convert formats, but full video processing (transcoding, multiple quality levels, HLS streaming) requires Filestack's Video Conversion add-on or a dedicated video processing service. For simple video upload and playback with pre-signed URLs, Filestack works well without the add-on.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation