High-Performance, Secure File Management System built with Next.js 16, MinIO (S3), Redis, and ZITADEL authentication.
- 📁 S3-Compatible Storage - Multi-bucket architecture with MinIO
- 🔐 YAML-based RBAC - Enterprise-grade access control with role-based permissions
- ⚡ Redis Caching - Lightning-fast permission checks and file listings
- 🔑 ZITADEL Auth - OIDC authentication with Auth.js v5
- 📝 Audit Logging - Complete operation tracking
- 🎨 Modern UI - Built with Shadcn UI and Tailwind CSS v4
- 👁️ File Preview - In-browser preview for images and PDFs (no download required)
- 🐳 Docker Ready - Multi-stage production Dockerfile included
| Category | Technology |
|---|---|
| Framework | Next.js 16.1.6 (App Router + Turbopack) |
| Runtime | Node.js 22+ |
| Auth | Auth.js v5 (next-auth@5.0.0-beta.30) + ZITADEL OIDC |
| Storage | MinIO (S3-compatible) |
| Cache | Redis (ioredis) |
| UI | Shadcn UI, Tailwind CSS v4, Lucide Icons |
| Language | TypeScript 5 |
- Node.js 22+ (use
nvm usewith included.nvmrc) - Docker & Docker Compose
- ZITADEL instance (for authentication)
git clone <repo-url>
cd s3-browser
npm installcp .env.local.example .env.local
# Edit .env.local with your configuration# Start MinIO and Redis
npm run docker:up
# MinIO Console: http://localhost:9001
# Redis Commander: http://localhost:8081# Create S3 buckets
npm run init-buckets
# Sync permissions to Redis
npm run sync-permissionsnpm run dev
# Open http://localhost:3000s3-browser/
├── src/
│ ├── app/ # Next.js App Router
│ │ ├── api/
│ │ │ ├── auth/ # Auth.js v5 handlers
│ │ │ ├── files/ # File operation endpoints
│ │ │ └── permissions/ # Permission sync endpoint
│ │ ├── auth/ # Auth pages (signin, error)
│ │ └── (dashboard)/ # Protected routes
│ │ └── explorer/ # File explorer
│ ├── components/
│ │ ├── explorer/ # File explorer components
│ │ │ ├── FileExplorer.tsx
│ │ │ ├── FileList.tsx
│ │ │ ├── FileItem.tsx
│ │ │ ├── FilePreview.tsx # Image/PDF preview modal
│ │ │ ├── Breadcrumb.tsx
│ │ │ ├── UploadZone.tsx
│ │ │ └── PermissionBadge.tsx
│ │ └── ui/ # Shadcn UI components
│ ├── lib/
│ │ ├── auth.ts # Auth.js v5 configuration
│ │ ├── redis.ts # Redis client
│ │ └── s3-client.ts # S3/MinIO client
│ ├── services/
│ │ ├── s3Service.ts # S3 operations
│ │ ├── permissionService.ts # RBAC engine
│ │ ├── cacheService.ts # Redis caching
│ │ ├── auditService.ts # Audit logging
│ │ └── syncService.ts # YAML sync
│ ├── types/ # TypeScript types
│ └── proxy.ts # Auth proxy (Next.js 16 pattern)
├── scripts/
│ ├── init-buckets.ts # Bucket initialization
│ └── sync-permissions.ts # Permission sync CLI
├── permissions.yaml # Permission configuration
├── Dockerfile # Multi-stage production build
├── docker-compose.yml # Development services
├── .nvmrc # Node.js version (22)
└── .vscode/ # VS Code debug configs
- OWNER - Full control (read, write, delete)
- EDITOR - Read and write access
- VIEWER - Read-only access
roles:
admin:
priority: 100
permissions:
- path: "*"
level: OWNER
engineering:
priority: 50
permissions:
- path: "shared/engineering/*"
level: EDITOR
users:
john@company.com:
priority: 80
permissions:
- path: "projects/secret/*"
level: OWNER
defaults:
authenticated:
permissions:
- path: "shared/public/*"
level: VIEWEREvery user automatically gets OWNER access to their home directory: home/${username}/*
| Endpoint | Method | Description |
|---|---|---|
/api/files/list |
GET | List files in a path |
/api/files/upload-url |
POST | Get presigned upload URL |
/api/files/download-url |
POST | Get presigned download URL |
/api/files/preview-url |
POST | Get presigned preview URL (images/PDF) |
/api/files/create-folder |
POST | Create a new folder |
/api/files/rename |
POST | Rename file/folder |
/api/files/delete |
DELETE | Delete file/folder |
/api/permissions/sync |
POST | Sync permissions to Redis |
The file explorer supports in-browser preview for:
| File Type | Features |
|---|---|
| Images (jpg, png, gif, webp, svg, bmp) | Zoom in/out, Rotate |
| Embedded iframe viewer |
Click the 👁️ (eye) icon on any previewable file to open the preview modal without downloading.
# Auth.js v5
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=your-secret-key
AUTH_TRUST_HOST=true
# ZITADEL
ZITADEL_ISSUER=https://your-instance.zitadel.cloud
ZITADEL_CLIENT_ID=your-client-id
ZITADEL_CLIENT_SECRET=your-client-secret
# MinIO
S3_ENDPOINT=http://localhost:9000
S3_REGION=us-east-1
S3_ACCESS_KEY_ID=minioadmin
S3_SECRET_ACCESS_KEY=minioadmin
S3_BUCKET_USER_FILES=user-files
S3_BUCKET_SHARED_FILES=shared-files
S3_BUCKET_TEMP_UPLOADS=temp-uploads
# Redis
REDIS_URL=redis://localhost:6379
# App Config
MAX_FILE_SIZE_MB=100
ALLOWED_FILE_TYPES=.pdf,.jpg,.png,.doc,.docx,.xls,.xlsx,.zip
PRESIGNED_URL_EXPIRY_SECONDS=3600npm run dev # Start development server (Turbopack)
npm run build # Build for production
npm run start # Start production server
npm run lint # Run ESLint
npm run sync-permissions # Sync permissions.yaml to Redis
npm run init-buckets # Create S3 buckets
npm run docker:up # Start Docker services
npm run docker:down # Stop Docker services# Start MinIO + Redis
docker compose up -d
# Access MinIO Console
open http://localhost:9001# Build and run the app
docker compose --profile app up -d
# Or build manually
docker build -t s3-browser .
docker run -p 3000:3000 --env-file .env.local s3-browser- ✅ All S3 operations are server-side only
- ✅ Presigned URLs with expiration
- ✅ Permission checks before every operation
- ✅ Audit logging for all file access
- ✅ Path sanitization and validation
- ✅ File type and size restrictions
- ✅ CSRF protection with Auth.js v5
- ✅ Server Actions for authentication
The project includes VS Code launch configurations for debugging:
- Next.js: Debug Server - Debug the Next.js server
- Next.js: Full Stack - Debug both server and client
Use nvm use to switch to Node.js 22 before running.
This project requires Node.js 22+. Use the included .nvmrc:
nvm useMIT