File hosting
Stable links for every file your app needs
Host images, fonts, video and your users' uploads on a CDN with one command. No buckets to configure, no egress bills. Included in every plan.
❯ npx slingdrop host ./assets --space acme Hosting 3 files in acme (412 KB) ✓ https://cdn.slingdropcontent.my/acme/logo.svg ✓ https://cdn.slingdropcontent.my/acme/hero.webp ✓ https://cdn.slingdropcontent.my/acme/inter.woff2
Built for apps
The boring parts of file hosting, done
One command
npx slingdrop host ./assets uploads a folder and prints a URL for every file, or a JSON manifest your build can import.
Stable URLs on a CDN
Files live at cdn.slingdropcontent.my/your-space/path and are served from Cloudflare's network, with CORS, ranges and ETags.
Resize on the fly
Add ?w=400&format=auto to any image URL to get a smaller WebP or AVIF, cached at the edge.
Your users' uploads
Create a signed upload URL on your server, and your users' browsers upload straight to Slingdrop. Limit the type and size.
Overwrite or pin forever
Re-upload to update a file (short cache), or mark hashed files immutable to cache them for a year.
Safe by design
Files are served from an isolated domain. HTML, JavaScript and SVG download instead of running, and every upload is checked against known malware.
How to use it
Hosted files belong to a space: a name that becomes the first part of every URL. Uploading to a free name creates it. Sign in once with the CLI, or create an API key in Settings → Developer.
From your terminal
# Sign in once
npx slingdrop login
# Upload a folder; every file gets a public URL
npx slingdrop host ./public/assets --space acme
# Hashed build output: cache for a year
npx slingdrop host ./dist/assets --space acme --prefix v42 --immutable
# A manifest for your build
npx slingdrop host ./public/assets --space acme --json > assets.jsonAlso slingdrop host ls, host rm <path>, host spaces and host usage.
With the REST API
curl -X PUT https://slingdrop.my/api/v1/hosting/acme/objects/img/logo.png \
-H "Authorization: Bearer $SLINGDROP_API_KEY" \
-H "Content-Type: image/png" \
--data-binary @logo.png
# → { "data": { "url": "https://cdn.slingdropcontent.my/acme/img/logo.png", … } }Files over 95 MB use the multipart endpoints. The API reference lists them all.
Let your users upload: on your server
import { Slingdrop } from "@slingdrop/sdk";
const sd = new Slingdrop({ apiKey: process.env.SLINGDROP_API_KEY });
// In your API route: let a signed-in user upload an avatar
const upload = await sd.hosting.createUploadUrl("acme", {
prefix: `avatars/${user.id}`,
filename: "avatar.png",
contentType: "image/*",
maxBytes: 5_000_000,
});
return Response.json(upload); // { uploadUrl, url, maxBytes, expiresAt }…and in their browser
// In the browser: upload straight to Slingdrop
const { uploadUrl, url } = await fetch("/api/avatar-upload").then((r) => r.json());
await fetch(uploadUrl, { method: "PUT", headers: { "content-type": file.type }, body: file });
avatar.src = `${url}?w=256&format=auto`;Upload URLs expire (one hour by default, up to seven days), are tied to one path, and refuse files of the wrong type or size.
Limits
Hosting is part of every plan. Hosted files count towards your plan's storage. When a monthly limit runs out, files answer 429 until the month resets or you upgrade, and we email you at 80%.
| Per account | Free | Pro | Team |
|---|---|---|---|
| Hosted storage | 1 GB | Within your 50 GB | Within your 250 GB |
| Bandwidth per month | 10 GB | 250 GB, shared with drops | 1 TB, shared with drops |
| Largest file | 25 MB | 5 GB | 50 GB |
| Image resizes per month | 1,000 | 5,000 | 50,000 |
| Spaces | 3 | 20 | 100 |
Hosting is for your apps' assets and your users' files. Piracy, phishing and malware aren't allowed: see the Acceptable Use Policy. Spot abuse? Report a hosted file.