Create a ZIP Client-Side — No Server Required
What "no server" really covers when zipping in the browser — local files and public URLs work with zero backend; private storage needs one small signing endpoint, and nothing more.
"Can I zip files without a server?" has a precise answer: yes for anything the browser can already read, and almost for everything else. This page draws the line exactly, because knowing which side you're on decides whether you deploy anything at all.
Fully serverless: files the browser already has
Local files, picked or dropped, plus anything you generate in the page — zero backend, zero uploads, works from a static site:
import { createZip } from '@eazip/core';
const result = await createZip({
files: [
...fileInput.files,
{ file: new Blob([reportCsv]), filename: 'report.csv' },
],
zipName: 'export.zip',
});
result.download();Eazip.js is an MIT-licensed library, not a service — no account, no API key, nothing phones home. A GitHub Pages site can ship this.
Still serverless: URLs the page is allowed to fetch
Remote sources work without a backend when the browser can fetch them:
- Same-origin files — anything your own site serves.
- Public URLs with CORS — hosts that allow cross-origin
GETfrom your origin (your own CDN, public buckets with a CORS rule).
The gate is CORS, not the library: if fetch(url) works from your page,
the URL can go straight into files. The exact rules are in
Inputs and sources.
The honest boundary: private storage
Private buckets are private because anonymous browsers can't read them — so something with credentials has to authorize the user and mint short-lived signed URLs. That something is one small endpoint (or, on Supabase, optionally the RLS-governed client itself — the closest thing to serverless private signing). The zipping still happens entirely in the browser; the server's only job is saying "these ten URLs, for this user, for fifteen minutes":
Browser ──▶ your endpoint: "sign my files" (auth, ~10 lines)
Browser ◀── [{ url, filename }, …]
Browser ──▶ storage directly, zips locally (no server in the data path)Per-platform signing recipes: S3, R2, Supabase Storage. If you're weighing this against building a server-side ZIP pipeline instead, the neutral comparison is Client-side vs. server-side ZIP.
What "no server" can't give you
Also part of the honest answer:
- Jobs that outlive the tab — a reload ends a browser job.
- Very large exports — tab memory is the ceiling (the details).
- Fetching CORS-less third-party URLs — no client-side trick reads a host that refuses cross-origin requests; some proxy or service must fetch it.
Those cases move to managed Eazip with strategy: 'cloud' — which is,
deliberately, the moment "no server" stops being the requirement.
FAQ
Is anything uploaded when I zip local files?
No. Local files are read and packaged inside the page; the archive goes straight to the user's download. Nothing leaves the browser.
Can I ship this from a static host like GitHub Pages or Netlify?
Yes — the fully-serverless and public-URL cases need only static hosting. The signing endpoint for private storage can live anywhere that runs ten lines of code, including a serverless function.
Why can't I just fetch any public URL?
CORS: the host decides whether browsers on other origins may read its
responses. A URL that opens fine in a new tab can still refuse
cross-origin fetch.
Is a signed-URL endpoint "a server" in the bad sense?
It's ~10 lines that never touch file bytes — no ZIP code, no streaming, no bandwidth through it. Most teams run it as a serverless function next to their existing auth.
ZIP Files Larger Than 4 GB in JavaScript (ZIP64)
Classic ZIP stops at 4 GB and 65,535 entries; ZIP64 removes both limits. What Eazip.js writes, which extractors cope, and what the real problem usually is at that size.
Scale with Eazip
Keep the Eazip.js API and move URL-based ZIP jobs beyond browser limits when you need to.