- Resume a 2 GB upload after the signal drops
- Google Drive approval and a yearly assessment
- Login checks, size limits and safe file types
- Malware scanning before anyone opens a file
- A CDN, thumbnails and document previews
- Runtime, SDK and provider API upgrades
The Prompt Writes the Upload. Production Needs the Rest.
Ask an AI assistant for a file uploader and a first prompt can return as little as one request and one bucket. It works, and for a prototype it’s enough. This page uses that short version for brevity. A detailed prompt or an agent session can build a full framework project.
A production upload system is a set of services around that one request: an ingestion network, OAuth apps with certifications behind them, a policy engine, a malware scanner, a CDN, a document converter and an audited control environment. A prompt can draft code for most of them. It can’t pass a certification, run the infrastructure, or keep any of it working once the runtime, the SDK or a provider’s API changes.
Six gaps separate a vibe-coded uploader from a production one: large uploads, cloud sources, security, malware, delivery and upkeep. Each chapter below shows what closing the gap yourself takes, then how Filestack closes it.
import express from "express";import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";import { getSignedUrl } from "@aws-sdk/s3-request-presigner";import crypto from "node:crypto"; const app = express();const s3 = new S3Client({ region: "us-east-1" }); app.get("/upload-url", async (req, res) => { const key = `uploads/${crypto.randomUUID()}-${req.query.name}`; const command = new PutObjectCommand({ Bucket: "my-app-uploads", Key: key, ContentType: req.query.type, }); const url = await getSignedUrl(s3, command, { expiresIn: 300 }); res.json({ url, key });}); app.listen(3000);
const file = document.querySelector("#file").files[0];const params = new URLSearchParams({ name: file.name, type: file.type });const { url } = await fetch(`/upload-url?${params}`).then((r) => r.json()); // one request, the whole fileawait fetch(url, { method: "PUT", body: file });
What One Prompt Gives You
Ask Claude, ChatGPT or Cursor for a file uploader and a first prompt can come back with something like this: a server that signs an S3 upload URL, and a browser script that sends the file to it. Point it at a bucket and files land in S3.
The example is simplified for brevity. It is a reference point, not the most an AI can write. Keep prompting and the code gets a lot better.
Ask for More and You Get More
An agent working in a framework will split the uploader across many files, validate input, handle errors, upload in parts and write tests. All of it is code in your repository, running on servers you pay for.
One prompt
- A presigned S3 upload URL
- One
PUTfrom the browser
A detailed prompt
- Input validation and a login check
- Error handling and retries
- Upload in parts for large files
An agent session
- Routes, services and config in Next.js or NestJS
- Resumable uploads
- Tests and a CI pipeline
- Servers and storage to run
- A malware scan engine
- Google’s security assessment
- A SOC 2 audit
- A global CDN
- Ongoing upkeep
A Garage-Built Car and a McLaren Both Get You Across Town
The uploader from the prompt and a production upload system both move a file from a browser into storage, the way both cars reach the same finish line. What separates them is everything around the engine.
- 1Engine. The upload request itself. Both cars have one, and it's the part a prompt writes.
- 2Transmission. Resumable parts that shrink when the network slows.
- 3Brakes. Signed, expiring policies on every upload and download.
- 4Crash structure. Malware scanning and safe headers before anyone opens a file.
- 5Navigation. Google Drive, OneDrive and Box sign-in through certified OAuth apps.
- 6Road legal. SOC 2 and Google's yearly security assessment.
- 7Pit crew. Upgrades, fixes and monitoring after every dependency change.
The Same Gap, as an Iceberg
Picture the upload request as the tip of an iceberg. It’s the part the prompt writes, and the only part anyone sees in a demo.
Below the waterline sit the services that make uploads survive real networks, reach the places users keep their files, stay safe to open, load fast everywhere, and keep working after every dependency changes.
Each one took design work, testing on real networks and devices, and years of fixes to get where it is.
The prompt writes what’s above the waterline. Production runs on what’s below it.
What a Full-Featured Upload System Is Made Of
Break a full-featured upload system into parts and one way to count them comes to 61 components in 8 layers. Yours depends on what your app does. A prototype uses a handful, and a product that takes files from anyone uses most of them. An AI assistant can write code for many of them. Each one still has to be built, hosted, certified or kept current by someone. On Filestack, all 8 layers sit behind one API.
Build it yourself
8 layers, 61 componentsEvery layer built, then wired to the upload button.
With Filestack
8 layers, 1 APIAll 8 layers, behind one API.
Illustration, not to scale.
What Production Needs, and What Filestack Has Ready
Every layer of that iceberg, one row at a time. The left column is the work that stays with you after the code is written. The right column is already running.
| What production needs | Vibe-coded, yours to build, certify and fix | Filestack, ready-built |
|---|---|---|
| Upload code | AI writes it, and it works | Ready. Picker and SDK |
| Google Drive access | AI writes the sign-in. You apply for Google's OAuth verification, pass a third-party security assessment, and repeat it every year | Ready. Our registered OAuth apps carry Google's restricted-scope verification |
| OneDrive, Box, Facebook | A separate app review for each provider, and a fix each time its API changes | Ready. One line per source in the picker config |
| SOC 2 | An independent audit of your own controls, every year | Ready. Audited for SOC 2 every year, report on request |
| Ingestion network | Upload servers in regions near your users, deployed and paid for by you | Ready. Our Content Ingestion Network receives each file at the nearest server |
| Retries on bad networks | Multipart and retry code, tested by you on real phones and dropping connections | Ready. Each part retried on its own, and parts shrink on a weak signal |
| Upload security | Auth checks, size limits and content type rules you write and review | Ready. Short-lived signed policies, and a CSP header on every file |
| Malware scanning | A scan engine to run, virus signatures to keep current, and a quarantine to build | Ready. Virus detection on upload, results sent to your webhook |
| Delivery and previews | A CDN, an image pipeline and a document viewer to deploy | Ready. One CDN URL per file, resized, converted or previewed |
| Security testing | Vulnerability scans and penetration tests you schedule | Ready. Daily vulnerability scans and a yearly third-party penetration test |
| When it breaks | You find the bug, prompt for a fix and test it yourself. Each prompt can return a different fix, and none comes with a guarantee | Ours to fix. Monitored around the clock, with a public status page |
A Dropped Connection Can Restart a Large Upload From Zero
The short uploader on this page sends the whole file in one request. If a 2 GB video drops at 90% on a train, the next attempt starts from the first byte. S3 also caps a single request at 5 GB.4
Ask the AI to upload in parts next, and the code gets a lot more complicated. It has to split the file, track which parts landed, resume after a page reload, and abort abandoned uploads. S3 keeps the parts of an unfinished upload and bills them as storage until the upload is aborted or a lifecycle rule removes them.5
| Uploader | Data sent again |
|---|---|
| Single-request uploader | 2,048 MB |
| Filestack SDK | 18 MB at most |
Assumes the connection returns while the SDK is still retrying. Parts that already arrived are kept.
Only the Failed Part Is Sent Again
Our SDK sends the file in small parts and retries only the part that failed, so a dropped connection costs a few megabytes instead of the whole file. On a weak phone signal, Intelligent Ingestion makes the parts smaller until they get through. The Content Ingestion Network takes each file at the server nearest the user, then moves it to final storage, ours or your own bucket, while the file is already usable.8
Director of Product at JibJab
Google Drive Imports Need Approval AI Can’t Get
Unless you ask for more, the code you get back only reads files from the user’s computer. Users keep files in Google Drive, OneDrive, Box, Google Photos and Facebook. Each is a separate integration with its own registered OAuth app, its own review, and its own API changes.
Google Drive is the hardest. Letting a user browse their whole Drive needs access Google classes as restricted. Restricted access requires Google’s OAuth app verification plus a Cloud App Security Assessment by an authorized third-party assessor, and Google revalidates the app every year.2,3 AI can write the sign-in code. It can’t pass Google’s security assessment for you.
A narrower path exists. Google’s own file picker can hand your app single files without the assessment. It covers Google Drive only, and every other provider still needs its own integration.
Cloud Sources Are One Line of Config
Users sign in through our registered OAuth apps, so adding Google Drive, OneDrive or Box is one entry in the picker config.
- My Device
- Google Drive
- OneDrive
- Box
- Google Photos
Three Security Flaws in the Short Example
The server code from the prompt, the part that hands out upload URLs, has three security flaws. Another model or a more careful prompt might avoid all of them. Whether yours did is something you have to check line by line.
- Anyone can call it.No login check, so anyone who finds the URL gets signed upload URLs for your bucket, and you pay for whatever they store.
- The browser picks the content type.A caller can send
type=text/htmland upload a page with a script in it. Serve that bucket from your own domain through a CDN, and the script runs on your domain when someone opens the file. - There's no size cap.Someone can fill your bucket with 5 GB files, and you pay to store them.
app.get("/upload-url", async (req, res) => {1 const key = `uploads/${crypto.randomUUID()}-${req.query.name}`; const command = new PutObjectCommand({ Bucket: "my-app-uploads", Key: key, ContentType: req.query.type,2 }); const url = await getSignedUrl(s3, command, { expiresIn: 300 });3
A follow-up prompt fixes each flaw once someone spots it. Spotting it is the hard part. Veracode’s 2026 report puts the average security pass rate of AI-generated code at 56% with no security-specific prompting, and 15% for cross-site scripting, the class the second flaw belongs to.1
| Vulnerability type | Pass rate |
|---|---|
| Cryptographic algorithms | 87% |
| SQL injection | 83% |
| Average, all tasks | 56% |
| Cross-site scripting | 15% |
| Log injection | 12% |
Source: Veracode, 2026 GenAI Code Security Report.1
All Three Flaws, Fixed
Every upload and download can require a short-lived security policy that your server signs. It limits what the request can do, how big the file can be and where it goes, and the secret that signs it never reaches the browser. Each policy expires on a timer you set, so your server issues fresh ones as it goes and a leaked policy stops working on its own.9
Every file our CDN serves carries a Content-Security-Policy header that blocks inline scripts. We’re audited for SOC 2 every year, and the report is available on request.
- 1Anyone can call it A signed policy that expires
- 2The browser picks the content type A CSP header that blocks inline scripts
- 3There's no size cap A maximum file size in the policy
- SOC 2 Independently audited controls
Malware Scanning Is a Service, Not a Function
Unless you ask for scanning, the code you get back stores whatever arrives. A user uploads an infected PDF, and the next person to open it downloads the infection from your app.
Adding a scan yourself means building another service. One option is running the open-source ClamAV scanner on your own server, keeping its virus signatures up to date, and hiding each file until its scan passes. The other is AWS’s GuardDuty Malware Protection for S3, which scans new files and reports the result.6 You still build the part that quarantines an infected file and stops your app from serving a file that hasn’t been scanned.
ClamAV on your server, or GuardDuty plus your own quarantine and serving logic.
Scanned as Soon as It Lands
Virus detection runs as a Workflows task as soon as a file reaches storage. Your server hears about an infected file, and the name of the threat, as soon as the scan finishes. Virus detection runs on the Start plan and above.
CDN, Thumbnails and Previews Are Separate Projects
The short uploader gives you an S3 key in a private bucket, so showing the file to anyone needs another signed URL. An AI can write each missing piece, and each is then a service you deploy and run.
One URL Does All Four Jobs
Every uploaded file gets a URL on our CDN, which caches each unique URL for 30 days.10 Resizing an image, converting a Word file to PDF, or showing a Word, Excel or PowerPoint file in our document viewer is a change to that URL. The document viewer runs on the Grow plan and above.11
Someone Has to Keep It Current
A prompt produces code on the day you ask. Everything that code depends on keeps changing after that: the runtime, the SDK, Google’s assessment and every provider’s API.
Each change lands on whoever owns the uploader, on top of the work of building an upload service in house in the first place.
The Upgrades Are Ours to Make
We ship the runtime upgrades, provider API changes and fixes. Your side of the integration stays the few lines below.
import * as filestack from "filestack-js"; const client = filestack.init("YOUR_API_KEY");client.picker({ fromSources: ["local_file_system", "googledrive"],}).open();
Your Roadmap Starts on Day One
Same team, same roadmap. The only difference is who builds and keeps up the upload stack.
Build it yourself
8 systems to buildUpload stack
Product features
Prompt loopAttempt 3110
YouSigned URLs expire mid-upload.
AgentYou’re absolutely right. I should have caught that. Tokens refresh during long uploads now.
0features built
Still debuggingTest failed: signed URLs expire mid-upload
With Filestack
1 SDK callUpload stack
filestack.init('YOUR_API_KEY')
Upload, transform, AI, store, deliver
Product features
10features built
Building featuresWorking on: the rest of the roadmap
Skip the infrastructure sprint
Uploads, processing, storage, delivery and security come ready.
Skip the upkeep
We scale, monitor and maintain the stack after launch.
Ship feature one sooner
Your first sprint goes to something customers can see.
CTO at Pingboard.com
So, Should You Vibe Code Your Uploader?
Sometimes, yes. It depends on who uploads, from where, and who opens the file afterwards.
AIVibe code it when
- It's a prototype or an internal tool
- A few trusted people do the uploading
- Files are small and come from a desktop
- Nobody else opens what gets uploaded
The code from the prompt does that job.
Build on Filestack when
- Customers upload from phones on weak or dropping connections
- Files are large, like video, and a failed upload can't start over
- Users pick files from Google Drive, OneDrive or Box
- Anyone outside your team can upload
- Uploads need limits on size, type and who sent them
- Other users open what gets uploaded
- Every file has to be scanned before anyone opens it
- Images need several sizes or formats
- Word, Excel or PowerPoint files need a preview in the browser
- Files load for users in more than one region
- A customer's security review asks for SOC 2
- Nobody on the team wants to own runtime, SDK and provider API upgrades
Each of these becomes a feature your product owns once it applies. On our SDK, each one is configuration.
Keep Vibe Coding, on Top of Filestack
Our Filestack plugin for Claude Code, which also works in Cursor, gives your assistant tools that upload, transform, convert and secure files on your own account, plus skills for SDK integration, workflow design, webhook setup and error diagnosis.14
Ask for an uploader built on Filestack, and the assistant writes it against the picker, signed policies and virus scanning instead of a bare request to S3. Policy signing runs on your machine, so your app secret stays local.
# add the marketplace, then install/plugin marketplace add https://github.com/filestack/filestack-claude-plugin.git/plugin install filestack-claude-plugin@filestack-plugin
import * as filestack from "filestack-js"; // policy and signature come from your serverconst security = await fetch("/filestack-security").then((r) => r.json());const client = filestack.init("YOUR_API_KEY", { security }); client.picker({ fromSources: ["local_file_system", "googledrive", "onedrive", "box", "url", "webcam"], accept: ["image/*", "application/pdf"], maxSize: 100 * 1024 * 1024, storeTo: { workflows: ["YOUR_WORKFLOW_ID"] }, // virus scan onUploadDone: (res) => console.log(res.filesUploaded),}).open();
Frequently Asked Questions
Can't we ask the AI to add each missing piece?
For most of the code, yes, one prompt at a time. Each piece is then yours to test, run and update when its dependencies change. Google’s restricted-scope verification, its yearly security assessment and a SOC 2 audit aren’t code, so no prompt produces them.
Isn't building it ourselves cheaper?
The first version can be fast. What it costs to run depends on your team, and our file upload cost calculator estimates it with your own numbers. What it can’t produce is Google’s restricted-scope approval, a SOC 2 audit or a global CDN.
Do we have to stop using AI coding tools?
No. Our Filestack plugin for Claude Code and Cursor lets your assistant build on the picker, signed policies and virus scanning, so you keep the speed of a prompt.
Can files stay in our own storage?
Yes. Uploads can go to your own Amazon S3, Google Cloud Storage, Azure or Dropbox storage, or to Filestack storage by default.
Is Filestack SOC 2 compliant?
Yes. We’re audited for SOC 2 every year, and the report is available on request. Our file upload security page lists the audits and the contract documents behind them.
Which plans include virus detection and document preview?
Virus detection runs on the Start plan and above. The document viewer runs on the Grow plan and above. Every plan, including Free, includes the CDN.
We already built an uploader with AI. Can we move to Filestack?
Yes. Talk to our team about moving your current upload code to the picker, signed policies and CDN URLs.
Sources
- Veracode. 2026 GenAI Code Security Report.
- Google. Choose Google Drive API scopes, restricted scope classification.
- Google. Security assessment for restricted scopes, annual revalidation.
- Amazon Web Services. Uploading objects, 5 GB single PUT limit.
- Amazon Web Services. Uploading and copying objects using multipart upload.
- Amazon Web Services. GuardDuty Malware Protection for S3.
- Node.js. Release schedule, end-of-life dates.
- Filestack. Uploading, Intelligent Ingestion and the Content Ingestion Network.
- Filestack. Security policies.
- Filestack. CDN, caching.
- Filestack. Document viewer.
- Filestack. filestack-js 3.51.6, upload defaults: 6 MB parts, 3 concurrent, 10 retries.
- Amazon Web Services. End of support for AWS SDK for JavaScript v2.
- Filestack. Filestack plugin for Claude Code and Cursor, version 1.3.0.