The file manager that embeds anywhere
PHP ≥ 8.1 + Flysystem 3. Alpine.js UI. Local, S3, Cloudflare R2, SFTP. Embed with a few lines of JavaScript.
See it in action
Your customers' files stay in your customers' buckets
FluxFiles is the embeddable file manager where each tenant connects their own S3/R2 bucket — and you never store their data or their credentials.
-
Data sovereignty
Files live in the customer's own cloud account and region — built for GDPR, compliance, and enterprise procurement.
-
Zero data, zero creds at rest
Bucket credentials are AES-256-GCM encrypted inside the JWT and decrypted only at runtime — never written to a database or a log.
-
Storage cost that scales to zero
Storage and egress are billed to each customer, not to you. No storage bill that grows with your user base.
-
Stateless & embeddable
No central database. Drop the picker into any app by iframe or SDK; your backend mints a scoped, short-lived token.
How it works: your app encrypts the tenant’s bucket credentials into a short-lived JWT (HKDF-SHA256 + AES-256-GCM). FluxFiles decrypts them only to run the requested operation.
One token per tenant — each with its own rules
FluxFiles is stateless: the JWT your backend mints is the tenant's config. Storage path, file-size limit, quota, file count, allowed types, permissions — all enforced server-side. No per-tenant config files, no restarts.
// Your backend, per request — the token IS the tenant's config.
import { createToken } from '@fluxfiles/node';
const claims = tenant.plan === 'pro'
// 100 MB/file · any type · 50 GB · unlimited files · own bucket
? { disks: ['s3'], maxUploadMb: 100, allowedExt: null,
maxStorageMb: 51200, maxFiles: 0 }
// 5 MB/file · images only · 500 MB · 200 files
: { disks: ['local'], maxUploadMb: 5, allowedExt: ['jpg','png','webp'],
maxStorageMb: 500, maxFiles: 200 };
const token = createToken({
secret: process.env.FLUXFILES_SECRET,
userId: tenant.id,
prefix: `tenant_${tenant.id}/`, // isolates each tenant's files
perms: ['read', 'write', 'delete'],
...claims,
}); Pair it with BYOB to put each tenant on their own bucket.
Built for teams that ship file features
If your product needs uploads, FluxFiles drops in — without making you the landlord of your customers' data.
SaaS & multi-tenant apps
Give every customer a file manager on their own bucket. Per-tenant token scoping and data sovereignty are built in.
Agencies & freelancers
Ship a polished media library to each client without standing up storage infrastructure per project.
CMS & editor integrations
Drop a media picker into CKEditor, TinyMCE, Summernote, or your own editor via the iframe SDK.
Internal tools & dashboards
Add uploads, previews and audited file operations to admin panels in an afternoon.
Everything a modern file manager needs
Built for developers who need flexibility.
Multi-storage
Local, AWS S3, Cloudflare R2, SFTP via Flysystem v3 — swap with config, no code change.
Embed anywhere
iframe + postMessage SDK. Standalone UI is Alpine.js (zero build). Works with any framework.
JWT auth + scoping
Per-user path prefix, permission claims, disk whitelist, owner-only mode.
AI auto-tag
Claude / OpenAI vision — auto alt text, title, tags.
Image crop
Inline crop tool with aspect ratio presets.
Image optimization
Auto WebP variants — thumb, medium, large.
Presigned uploads
Browser uploads directly to S3/R2 — zero bandwidth on your server.
Chunk upload
S3 multipart for files > 10MB.
Full-text search
Indexed search across names, titles, tags — file-based, no database.
Bulk operations
Multi-select move, copy, delete, download.
Cross-disk transfer
Copy/move between Local ↔ S3 ↔ R2.
Trash / soft delete
Recoverable deletes with auto-purge.
SEO metadata
Title, alt, caption, tags — S3 object metadata (cloud) or sidecar JSON (local). Full-text search.
Dark mode
Light / dark / auto in UI and SDK.
16 languages
Default English. Set locale via SDK, URL (?locale=), or FLUXFILES_LOCALE. RTL for Arabic.
Audit log
All write actions logged for compliance.
Rate limiting
Token bucket per user for API protection.
Storage quota
Per-user storage limits via JWT claims.
BYOB buckets
Users bring their own S3/R2 — credentials encrypted in JWT (AES-256-GCM).
Duplicate detection
SHA-256 match skips redundant uploads unless you force overwrite.
SDK token refresh
onTokenRefresh on 401 — coalesced refresh, retry, and updateToken() for proactive rotation.
Bucket Doctor
Diagnose any S3/R2 disk — credentials, read/write/delete, presign, CORS, multipart — with ready-to-paste IAM & CORS fixes. Onboard BYOB buckets in minutes.
Node token SDK
Mint FluxFiles tokens from any JS backend (Express, Next.js, Nuxt) with @fluxfiles/node — byte-compatible with the PHP core. No PHP required to issue tokens.
SFTP disk
A 3rd driver after S3/R2 — turn any VPS or shared host into a managed file manager.
Code / config editor
Edit text and config files (wp-config.php, .env, nginx.conf) in-browser, cPanel-style.
Zip & Extract
Download a selection as a zip, or extract an archive in place — zip-slip & bomb guarded.
Watermark
Apply a text or logo watermark on the fly for preview protection — the source is never touched.
On-demand WebP + AVIF
Serve any image size as cached AVIF/WebP via one URL (Accept-negotiated), with ready responsive srcset.
SFTP permissions
Change Unix file permissions (chmod) on SFTP disks with a cPanel-style dialog.
Usage dashboard
See storage at a glance — quota plus a per-type and per-folder breakdown.
Media preview
Inline image, video, audio & PDF preview; private local media streams securely (Range-capable).
Up and running in 2 minutes
composer require fluxfiles/fluxfiles
cp .env.example .env
# .env
FLUXFILES_SECRET=your-random-32-char-secret
FLUXFILES_ALLOWED_ORIGINS=https://yourapp.com
require_once 'vendor/autoload.php';
$token = fluxfiles_token(
userId: 'user-123',
perms: ['read', 'write', 'delete'],
disks: ['local', 's3', 'r2'],
prefix: 'user-123/',
maxUploadMb: 10,
allowedExt: null,
ttl: 3600
); composer require fluxfiles/laravel
php artisan vendor:publish --tag=fluxfiles-config
# .env — point the adapter at your FluxFiles server
FLUXFILES_ENDPOINT=https://fm.yourdomain.com
FLUXFILES_SECRET=your-secret-min-32-chars
# Optional: match CORS on the FluxFiles host
# FLUXFILES_ALLOWED_ORIGINS=https://yourapp.com
# Config: config/fluxfiles.php npm install @fluxfiles/node
// Express / Next.js route — mint a token from your JS backend (no PHP)
import { createToken } from '@fluxfiles/node';
app.get('/fluxfiles-token', (req, res) => {
const token = createToken({
secret: process.env.FLUXFILES_SECRET, // >= 32 bytes
userId: req.user.id,
perms: ['read', 'write', 'delete'],
prefix: `users/${req.user.id}`,
ttl: 3600,
});
res.json({ token });
}); <!-- Demo: unpkg. In production, serve fluxfiles.js from your FluxFiles host -->
<script src="https://unpkg.com/fluxfiles@latest/fluxfiles.js"></script>
<script>
FluxFiles.open({
endpoint: 'https://your-api.com',
token: 'eyJhbGci...',
disk: 'local',
mode: 'picker',
container: '#file-picker',
onSelect: function(file) {
console.log('Selected:', file.url);
},
async onTokenRefresh() {
const r = await fetch('/api/auth/refresh-fluxfiles-token');
const { token } = await r.json();
return token;
}
});
</script> npm install @fluxfiles/react
import { FluxFilesModal } from '@fluxfiles/react';
<FluxFilesModal
open={open}
endpoint="https://your-api.com"
token={token}
onSelect={(file) => console.log(file)}
onClose={() => setOpen(false)}
/> npm install @fluxfiles/vue
<script setup>
import { FluxFilesModal } from '@fluxfiles/vue';
</script>
<FluxFilesModal
v-model:open="open"
endpoint="https://your-api.com"
:token="token"
@select="onSelect"
@close="open = false"
/> git clone https://github.com/thai-pc/fluxfiles.git
docker build -f fluxfiles/docker/Dockerfile.prod -t fluxfiles fluxfiles
docker run -p 8080:80 \\
-e FLUXFILES_SECRET=your-random-32-char-secret \\
fluxfiles
# UI: http://localhost:8080/public/index.html git clone https://github.com/thai-pc/fluxfiles.git
cd fluxfiles
composer install -d packages/core
cp .env.example .env
cd packages/core
php -S localhost:8080 router.php
# UI: http://localhost:8080/public/index.html
# API: http://localhost:8080/api/fm/list?disk=local&path= Works with
Integrations
Drop-in adapters for your stack
Official adapters embed FluxFiles natively in the frameworks and editors you already use.
Embed
Embed it in a few lines
Load fluxfiles.js, pass a server-minted JWT, and drop a full file manager — or a file-picker modal — into any page.
<script src="https://fm.example.com/fluxfiles.js"></script>
FluxFiles.open({
endpoint: 'https://fm.example.com',
token: 'eyJhbGci...', // JWT from your backend
disk: 'local',
mode: 'picker', // select & close
theme: 'auto',
onSelect(file) {
// { url, key, name, size, disk, meta, variants }
document.querySelector("#img").src = file.url;
},
}); <div id="fm" style="height:600px"></div>
FluxFiles.open({
endpoint: 'https://fm.example.com',
token: 'eyJhbGci...',
mode: 'browser', // full manager, stays open
container: '#fm', // omit for a modal overlay
disks: ['local', 's3', 'r2'],
});
FluxFiles.on('FM_EVENT', (e) => console.log(e.event));
FluxFiles.navigate('/photos/2024'); import { FluxFilesModal } from '@fluxfiles/react';
function Picker({ open, setOpen, token }) {
return (
<FluxFilesModal
open={open}
endpoint="https://fm.example.com"
token={token}
onSelect={(file) => console.log(file.url)}
onClose={() => setOpen(false)}
/>
);
} Tokens are minted server-side — never ship your secret to the browser.
Built for what others forgot
| Feature | FluxFiles | elFinder | Laravel-FM | RichFilemanager | Responsive FM |
|---|---|---|---|---|---|
| S3 + R2 + Local + SFTP | ✓ | ⚠ | ⚠ | ⚠ | ✗ |
| Embed any framework | ✓ | ⚠ | ✗ | ⚠ | ✗ |
| JWT auth + scoping | ✓ | ✗ | ✗ | ✗ | ✗ |
| SEO metadata | ✓ | ✗ | ✗ | ✗ | ✗ |
| AI auto-tag | ✓ | ✗ | ✗ | ✗ | ✗ |
| Image crop | ✓ | ✓ | ✗ | ✗ | ✗ |
| Chunk upload | ✓ | ✗ | ✗ | ✗ | ✗ |
| Full-text search | ✓ | ✗ | ✗ | ✗ | ✗ |
| Dark mode | ✓ | ✗ | ⚠ | ✗ | ✗ |
| 16 languages | ✓ | ✓ | ✗ | ✗ | ✗ |
| PHP ≥ 8.1 | ✓ | ✓ | ✗ | ✓ | ✓ |
| Actively maintained | ✓ | ✓ | ⚠ | ✗ | ✗ |
| Modern UI | ✓ | ✗ | ⚠ | ✗ | ✗ |
Self-hosted and embeddable — not another upload SaaS
Hosted file APIs are great, but they store your data and bill per use. FluxFiles runs in your stack, with each tenant on their own bucket.
| Capability | FluxFiles | Filestack | Uploadcare | Cloudinary | Supabase Storage |
|---|---|---|---|---|---|
| Self-hosted (runs in your infra) | ✓ | ✗ | ✗ | ✗ | ⚠ |
| BYOB — each customer’s own bucket | ✓ | ⚠ | ⚠ | ✗ | ✗ |
| Embeddable file-manager UI | ✓ | ✓ | ✓ | ⚠ | ✗ |
| Open source (MIT) | ✓ | ✗ | ✗ | ✗ | ✓ |
| No per-storage / per-upload SaaS fees | ✓ | ✗ | ✗ | ✗ | ⚠ |
| Multi-storage (S3 / R2 / local) | ✓ | ⚠ | ✗ | ✗ | ✗ |
| Per-tenant token scoping built in | ✓ | ⚠ | ⚠ | ⚠ | ⚠ |
Comparison reflects typical default offerings; each product excels in its own space. FluxFiles’ niche is the embeddable, self-hosted, bring-your-own-bucket combination.
Sellable products
Do more than manage files — sell & receive them
The free core embeds a file manager. The paid modules turn it into products your clients pay for.
Branded Share
Send a branded, self-serve link to any file or folder — with expiry, password, download cap, and view analytics. Your logo, your domain.
- Expiring / password-protected links
- Download caps + view analytics
- Scoped token — no account for the recipient
Upload Portals
A public “send us your files” page that drops straight into your storage. Perfect for agencies, photographers, and client onboarding — no account for the uploader.
- Public portal → your bucket
- Per-portal size / type / expiry limits
- Anonymous upload, owner-scoped
Compliance bundle
Virus scanning, C2PA content provenance and audit retention — for regulated and enterprise deployments.
WordPress
One plugin instead of three
On WordPress, FluxFiles is both a client file-portal AND a media manager — replacing separate folder, cloud, and offload plugins.
| Capability | FluxFiles | FileBird | WP Media Folder | WP Offload |
|---|---|---|---|---|
| Media folders | — | |||
| S3 / R2 / SFTP storage | — | |||
| Offload + URL rewrite | — | — | ||
| Client upload portals | — | — | — | |
| Branded share links | — | — | — | |
| Typical price | One license | $49/yr | $69/yr | paid |
Folders + cloud + offload + client portals in one — instead of paying FileBird and WP Media Folder and WP Offload separately.
Pricing
Free core. Pay only for the paid modules.
The MIT core is free forever. Upgrade for the two hero products — Branded Share + Upload Portals — and beyond.
Free (Core)
The full MIT file manager, self-hosted.
Get started- Local / S3 / R2 / SFTP storage, JWT-scoped
- On-demand WebP + AVIF + image/PDF optimization
- Watermark, versioned-hook, usage dashboard, AI auto-tag
- 7 adapters + BYO-embed terminal / PDF / office / e-sign
Pro
Sell & receive files with clients.
Coming soonComing soon- Everything in Free
- Branded Share — links with expiry / password / cap / analytics
- Upload Portals — public “send us files”, no account
- Priority support + updates
Studio
Build a product on FluxFiles.
Coming soonComing soon- Everything in Pro
- Versioning + Webhooks (Zapier/Make/n8n)
- AI Vision + OCR (BYO-key)
- Multi-tenant claim-tiering + white-label
Enterprise
Compliance, at scale.
Contact sales- Everything in Studio
- Virus scan + C2PA provenance + audit retention
- SSO bridge + custom onboarding
- SLA + priority roadmap
Flat-fee, unlimited sites — not metered per file/call. Annual saves ~2 months; a lifetime option is available. 14-day refund. Buyer-side VAT handled at checkout.
FAQ
Frequently asked questions
Is FluxFiles free and open source?
Where are my files stored?
How does authentication work?
Do my users need a FluxFiles account?
Can I embed it in my existing app or editor?
What do I need to run it?
What do the paid tiers include?
How do I activate a license?
One-time or subscription?
Ready to embed FluxFiles?
Add a production-ready file manager to your app in minutes — no framework lock-in, MIT licensed.