Self-Hosted Google Drive Explorer, CMS & Streaming Platform
Transform your Google Drive into a professional file manager, media gallery, and streaming server.
Shared Drive management · Video Streaming · Password-Protected Folders · Share Links
Click to expand
| Feature | Description |
|---|---|
| Virtualized Rendering | Smooth scrolling through 10,000+ files with @tanstack/react-virtual |
| Smart Prefetching | Preloads folder contents on hover for instant navigation |
| Multi-Layer Caching | Redis + in-memory cache for blazing-fast API responses |
| Turbopack | Next.js 16 Turbopack for ultra-fast development builds |
| PWA Support | Installable as a Progressive Web App with offline caching |
| Dark/Light Mode | Automatic theme detection with manual toggle |
| Feature | Description |
|---|---|
| Video Streaming | Direct stream with VidStack player, resume playback, theater mode |
| Auto Subtitles | Automatic .srt / .vtt subtitle detection and loading |
| Audio Dock | Persistent audio player that continues across navigation |
| Image Gallery | Masonry grid with lightbox using yet-another-react-lightbox |
| PDF Viewer | Built-in viewer powered by react-pdf |
| Code Editor | Monaco Editor for syntax-highlighted code preview |
| Office Files | Preview Word, Excel, PowerPoint via Google Viewer |
| Archive Preview | Browse ZIP contents without downloading |
| Ebook Reader | Read ePub files in-browser |
| Feature | Description |
|---|---|
| Role-Based Access | Admin / Editor / User / Guest roles |
| Folder Passwords | Recursive folder protection with bcrypt-hashed passwords |
| Two-Factor Auth | Optional TOTP-based 2FA with QR code setup |
| Share Links | JWT-signed links with expiry, max uses, download prevention, watermarks |
| Rate Limiting | Per-endpoint rate limiting for API, admin, auth, and download |
| CSP Headers | Content Security Policy, HSTS, X-Frame-Options, and more |
| bcrypt Passwords | Timing-safe password comparison with bcrypt hashing |
| Feature | Description |
|---|---|
| Multi-Drive Support | Personal, Shared, and Team Drives in unified sidebar |
| Manual Drives | Add drives via config with optional password protection |
| Folder Aliases | Custom display names without modifying Google Drive |
| Private Folders | Hide specific folders from non-admin users |
| Favorites | Pin files and folders for quick access |
| Drag & Drop | Move files between folders via drag and drop |
| Bulk Operations | Multi-select, bulk download (ZIP), bulk delete |
| Feature | Description |
|---|---|
| Analytics | Page views, visitors, bandwidth, device breakdown |
| Activity Logs | Track downloads, uploads, config changes |
| User Management | Add editors, manage admin access via email |
| Storage Monitor | Real-time storage usage with warnings |
| Cache Control | Clear Redis cache, view cache stats |
| System Health | Monitor database, Redis, API health |
| File Request | Create public upload links |
| Layer | Technology | Purpose |
|---|---|---|
| Frontend | Next.js 16 + React 19 | App Router, Server Components, Streaming SSR |
| Tailwind CSS + Framer Motion | Styling, glassmorphism, micro-animations | |
| Zustand + TanStack Query | Global state + server state management | |
| Backend | Next.js API Routes | REST API with edge-compatible middleware |
| NextAuth.js v5 (Beta) | OAuth, credentials, guest auth, JWT sessions | |
| Google Drive API v3 | File storage, streaming, metadata | |
| Prisma + PostgreSQL 16 | Database ORM with migration support | |
| Infrastructure | Redis 7 | Caching, rate limiting, session data |
| Docker + Caddy | Containerization, auto-HTTPS reverse proxy | |
| Dev Tools | TypeScript 5 (strict) | Type safety across the entire codebase |
| Vitest + Playwright | Unit tests + end-to-end testing | |
| ESLint + Prettier + Husky | Linting, formatting, git hooks |
flowchart TB
subgraph CLIENT["🌐 Client Browser"]
A["React 19 + Next.js 16\nApp Router · Zustand · TanStack Query"]
end
subgraph CADDY["🔒 Caddy Reverse Proxy"]
B["Auto-HTTPS · Let's Encrypt\n:443 → :3000"]
end
subgraph APP["⚡ Zee-Index Application"]
C["API Routes"]
D["Middleware\nAuth · i18n · Rate Limit"]
E["Server Components\nStreaming SSR"]
end
subgraph SERVICES["📦 Backend Services"]
F[("🐘 PostgreSQL 16\nUsers · Shares\nActivity · Config")]
G[("🔴 Redis 7\nCache · KV Store\nRate Limiting")]
H["☁️ Google Drive API v3\nFiles · Streaming\nMetadata"]
end
CLIENT <-->|HTTPS| CADDY
CADDY <--> APP
C <--> F
C <--> G
C <--> H
D --- C
E --- C
style CLIENT fill:#1a1a2e,stroke:#e94560,color:#fff
style CADDY fill:#0f3460,stroke:#e94560,color:#fff
style APP fill:#16213e,stroke:#0f3460,color:#fff
style SERVICES fill:#1a1a2e,stroke:#533483,color:#fff
Live Demo: https://zee-index.duckdns.org
| Requirement | Version | Required |
|---|---|---|
| Docker + Docker Compose | Latest | ✅ Yes |
| Git | Latest | ✅ Yes |
| Node.js + pnpm | 20.x+ / 9.x+ | 🔶 Only for local dev |
| Google Cloud Project | — | ✅ Yes |
The fastest way to get Zee-Index running with PostgreSQL, Redis, auto-HTTPS, all preconfigured:
# 1. Clone the repository
git clone https://github.com/ifauzeee/Zee-Index.git
cd Zee-Index
# 2. Copy environment template
cp .env.example .env
# 3. Edit .env with your credentials (see Environment Variables section)
nano .env
# 4. Build and start all services
docker compose up -d --build
# 5. Open http://localhost:3000 (or your domain)
# Navigate to /setup to complete Google Drive configurationUseful Docker commands:
# View logs
docker compose logs -f zee-index
# Restart after .env changes
docker compose up -d
# Rebuild after code changes
docker compose up -d --build
# Stop all services
docker compose down
# Stop and remove all data (⚠️ destructive)
docker compose down -vFor contributors or those who prefer local development with hot reload:
# 1. Clone and install
git clone https://github.com/ifauzeee/Zee-Index.git
cd Zee-Index
pnpm install
# 2. Configure environment
cp .env.example .env
# Edit .env — set DATABASE_URL for a local PostgreSQL instance
# 3. Setup database
pnpm prisma migrate deploy # or: pnpm prisma db push
# 4. Start Redis (optional but recommended)
docker run -d --name zee-redis -p 6379:6379 redis:7-alpine
# 5. Start development server (with Turbopack)
pnpm dev
# 6. Open http://localhost:3000Development commands:
pnpm dev # Start with Turbopack (fast)
pnpm dev:webpack # Start with Webpack (fallback)
pnpm build # Production build
pnpm typecheck # TypeScript type checking
pnpm lint # ESLint
pnpm format:check # Prettier check
pnpm check:all # Run all checks
pnpm test # Unit tests (Vitest)
pnpm test:e2e # E2E tests (Playwright)Step-by-step Google Cloud configuration
- Go to Google Cloud Console
- Create a new project (or select an existing one)
- Navigate to APIs & Services → Library
- Search for "Google Drive API"
- Click Enable
- Go to APIs & Services → OAuth consent screen
- Select External user type
- Fill in app name, support email, developer email
- Add scopes:
https://www.googleapis.com/auth/drivehttps://www.googleapis.com/auth/drive.filehttps://www.googleapis.com/auth/userinfo.emailhttps://www.googleapis.com/auth/userinfo.profile
- Add your email as a test user (while in testing mode)
- Go to APIs & Services → Credentials
- Click Create Credentials → OAuth client ID
- Select Web application
- Add Authorized redirect URIs:
http://localhost:3000/setup(development)https://yourdomain.com/setup(production)
- Save the Client ID and Client Secret
- Set
GOOGLE_CLIENT_IDandGOOGLE_CLIENT_SECRETin.env - Leave
GOOGLE_REFRESH_TOKENempty - Start the application and navigate to
/setup - Complete the OAuth flow → copy the Refresh Token
- Add it to
.envasGOOGLE_REFRESH_TOKEN - Restart the application
| Variable | Description | Example |
|---|---|---|
NEXTAUTH_URL |
Your application URL | https://yourdomain.com |
NEXTAUTH_SECRET |
Encryption key (min 32 chars) | openssl rand -base64 32 |
GOOGLE_CLIENT_ID |
Google OAuth Client ID | xxx.apps.googleusercontent.com |
GOOGLE_CLIENT_SECRET |
Google OAuth Client Secret | GOCSPX-xxx |
GOOGLE_REFRESH_TOKEN |
OAuth Refresh Token | Obtained via /setup |
NEXT_PUBLIC_ROOT_FOLDER_ID |
Root Google Drive folder ID | 1ABcDeFgHiJkLmNoPqRsT |
ADMIN_EMAILS |
Comma-separated admin emails | admin@example.com |
ADMIN_PASSWORD |
Admin fallback login password | Use a strong password |
SHARE_SECRET_KEY |
JWT signing key (min 32 chars) | openssl rand -base64 32 |
| Variable | Description | Default |
|---|---|---|
POSTGRES_USER |
PostgreSQL username | postgres |
POSTGRES_PASSWORD |
PostgreSQL password | postgres |
POSTGRES_DB |
Database name | zee_index |
DATABASE_URL |
Full connection string (non-Docker) | Auto-generated in Docker |
REDIS_URL |
Redis connection string | redis://redis:6379 (Docker) |
| Variable | Description | Default |
|---|---|---|
ADMIN_PASSWORD_HASH |
bcrypt hash of admin password (recommended) | — |
NEXT_PUBLIC_ROOT_FOLDER_NAME |
Display name for root folder | Home |
NEXT_PUBLIC_MANUAL_DRIVES |
JSON array of additional drives | [] |
PRIVATE_FOLDER_IDS |
JSON array of private folder IDs | [] |
STORAGE_LIMIT_GB |
Storage warning limit | 15 |
STORAGE_WARNING_THRESHOLD |
Warning threshold (0–1) | 0.90 |
CRON_SECRET |
Cron job authentication token | — |
TMDB_API_KEY |
TMDB API key for movie metadata | — |
DUCKDNS_DOMAIN |
DuckDNS subdomain | — |
DUCKDNS_TOKEN |
DuckDNS authentication token | — |
| Variable | Description | Default |
|---|---|---|
SMTP_HOST |
SMTP server | smtp.gmail.com |
SMTP_PORT |
SMTP port | 465 |
SMTP_USER |
SMTP username | — |
SMTP_PASS |
SMTP password / app password | — |
EMAIL_FROM |
Sender email address | Zee Index <no-reply@example.com> |
📋 Complete .env template
# ==============================================================================
# ZEE-INDEX CONFIGURATION
# ==============================================================================
# 1. CORE
NEXTAUTH_URL="http://localhost:3000"
NEXTAUTH_SECRET="" # openssl rand -base64 32
SHARE_SECRET_KEY="" # openssl rand -base64 32
ADMIN_EMAILS="admin@example.com"
ADMIN_PASSWORD="your-secure-password"
# ADMIN_PASSWORD_HASH="" # Generate: scripts/hash-password.sh "password"
# 2. GOOGLE DRIVE
GOOGLE_CLIENT_ID=""
GOOGLE_CLIENT_SECRET=""
GOOGLE_REFRESH_TOKEN=""
NEXT_PUBLIC_ROOT_FOLDER_ID=""
NEXT_PUBLIC_ROOT_FOLDER_NAME="Home"
# 3. DATABASE (Docker auto-configures DATABASE_URL)
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB=zee_index
# 4. LIMITS & MONITORING
STORAGE_LIMIT_GB=15
STORAGE_WARNING_THRESHOLD=0.90
CRON_SECRET="random-string"
# 5. BUILD
SKIP_ENV_VALIDATION=false
# 6. HTTPS (Optional)
# DUCKDNS_DOMAIN="your-subdomain"
# DUCKDNS_TOKEN="your-token"
# 7. EMAIL (Optional)
# SMTP_HOST="smtp.gmail.com"
# SMTP_PORT="465"
# SMTP_USER="your-email@gmail.com"
# SMTP_PASS="your-app-password"
# EMAIL_FROM="Zee Index <no-reply@example.com>"
# 8. EXTERNAL SERVICES (Optional)
# TMDB_API_KEY=""Zee-Index is optimized for deployment on low-resource VPS instances (1 CPU / 1 GB RAM):
# 1. SSH into your server
ssh root@your-server-ip
# 2. Install Docker
curl -fsSL https://get.docker.com | sh
# 3. Create a non-root user (recommended)
adduser zee && usermod -aG docker zee
su - zee
# 4. Clone and configure
git clone https://github.com/ifauzeee/Zee-Index.git
cd Zee-Index
cp .env.example .env
nano .env # Configure all required variables
# 5. Deploy
docker compose up -d --build
# 6. Verify
docker compose ps # All containers should be "healthy"
docker compose logs -f # Watch startup logsResource usage (approximate):
| Container | Memory Limit | Typical Usage |
|---|---|---|
zee-index |
512 MB | ~300 MB |
postgres |
200 MB | ~50 MB |
redis |
150 MB | ~20 MB |
caddy |
50 MB | ~10 MB |
| Total | ~912 MB | ~380 MB |
The included docker-compose.yml has built-in support for free HTTPS:
- Get a DuckDNS domain at duckdns.org
- Add to
.env:DUCKDNS_DOMAIN="your-subdomain" DUCKDNS_TOKEN="your-duckdns-token" NEXTAUTH_URL="https://your-subdomain.duckdns.org"
- Create a
Caddyfile:your-subdomain.duckdns.org { reverse_proxy zee-index:3000 } - Deploy — Caddy automatically provisions SSL via Let's Encrypt
Railway
- Create a project at railway.app
- Add PostgreSQL and Redis services
- Connect your GitHub repository
- Set environment variables
- Deploy
Render
- Create a Web Service at render.com
- Build command:
pnpm install && pnpm prisma migrate deploy && pnpm build - Start command:
pnpm start - Add PostgreSQL database and Redis instances
- Set environment variables
| Method | Description | Config |
|---|---|---|
| Google OAuth | Login with Google account | Set OAuth credentials |
| Admin Password | Email + password login for admins | ADMIN_EMAILS + ADMIN_PASSWORD |
| Guest Access | Read-only access (can be disabled) | Toggle in admin settings |
| Two-Factor Auth | TOTP-based 2FA with QR code | Admin dashboard setup |
Role Hierarchy:
| Role | Permissions |
|---|---|
ADMIN |
Full access — settings, user management, all files |
EDITOR |
Can manage files but not system settings |
USER |
Standard access to permitted folders |
GUEST |
Read-only access to public content |
Admin passwords support bcrypt hashing for production security:
# Generate a bcrypt hash for your password
docker compose exec zee-index sh /app/scripts/hash-password.sh "your-password"
# Add the output to .env
ADMIN_PASSWORD_HASH=$2a$10$...your-hash-here...
# You can then remove the plaintext ADMIN_PASSWORDMigration path: If
ADMIN_PASSWORD_HASHis set, bcrypt is used. Otherwise, the system falls back to timing-safe comparison ofADMIN_PASSWORD.
Zee-Index includes comprehensive security headers:
- Content-Security-Policy — Prevents XSS by restricting script/style/media sources
- Strict-Transport-Security — Forces HTTPS (63072000s / ~2 years)
- X-Frame-Options: DENY — Prevents clickjacking
- X-Content-Type-Options: nosniff — Prevents MIME sniffing
- Referrer-Policy —
strict-origin-when-cross-origin - Permissions-Policy — Disables camera, microphone, geolocation
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/health |
Health check |
GET |
/api/config/public |
Public app configuration |
GET |
/api/files |
List files (with optional share token) |
GET |
/api/download?fileId=… |
Download / stream file |
GET |
/api/folderpath?folderId=… |
Get folder breadcrumb path |
GET |
/api/metadata?fileId=… |
Get file metadata |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/search?q=… |
Search files |
GET |
/api/datausage |
Storage usage info |
POST |
/api/favorites |
Toggle favorites |
POST |
/api/tags |
Manage file tags |
POST |
/api/share/create |
Create share link |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/admin/analytics |
Analytics data |
GET |
/api/admin/activity |
Activity logs |
GET |
/api/admin/cache-stats |
Cache statistics |
POST |
/api/admin/config |
Update app configuration |
POST |
/api/admin/2fa/setup |
Configure 2FA |
POST |
/api/admin/protected-folders |
Manage folder passwords |
POST |
/api/admin/manual-drives |
Manage drives |
DELETE |
/api/admin/clearcache |
Clear all caches |
| Shortcut | Action |
|---|---|
| Ctrl/⌘ + K | Open Command Palette |
| / | Focus Search |
| Space | Quick Preview |
| Ctrl + A | Select All Files |
| Delete | Delete Selected |
| F2 | Rename Selected |
| Enter | Open Selected Item |
| Escape | Close Modal / Clear Selection |
| G then H | Go to Home |
Zee-Index supports multiple languages via next-intl:
| Language | Code | Status |
|---|---|---|
| 🇬🇧 English | en |
✅ Complete |
| 🇮🇩 Indonesian | id |
✅ Complete |
Adding a new language:
- Copy
messages/en.json→messages/xx.json - Translate all strings
- Add
"xx"to the locales array inmiddleware.ts:const intlMiddleware = createMiddleware({ locales: ["en", "id", "xx"], defaultLocale: "en", });
zee-index/
├── app/ # Next.js App Router
│ ├── [locale]/ # Internationalized routes
│ │ ├── (main)/ # Main layout (sidebar + content)
│ │ ├── admin/ # Admin dashboard
│ │ ├── login/ # Login page
│ │ └── setup/ # Setup wizard
│ └── api/ # API Routes
│ ├── admin/ # Admin-only APIs
│ ├── auth/ # NextAuth handlers
│ ├── download/ # File download & streaming
│ ├── files/ # File listing
│ ├── share/ # Share link APIs
│ └── cron/ # Scheduled tasks
│
├── components/ # React Components
│ ├── admin/ # Admin dashboard UI
│ ├── file-browser/ # File listing, actions, modals
│ │ ├── share/ # Share modal components
│ │ └── details/ # Detail panel components
│ ├── file-details/ # File preview & player
│ │ └── video-player/ # Video overlays & controls
│ ├── layout/ # Header, Sidebar, Footer
│ │ └── sidebar/ # Sidebar sub-components
│ ├── common/ # Shared UI components
│ └── ui/ # Radix-based primitives
│
├── lib/ # Core Libraries
│ ├── drive/ # Google Drive API client
│ ├── kv/ # Redis/KV abstraction layer
│ │ ├── index.ts # Factory + re-exports
│ │ ├── types.ts # KVClient interface
│ │ ├── redis-kv.ts # Redis implementation
│ │ └── memory-kv.ts # In-memory fallback
│ ├── store/ # Zustand state management
│ ├── services/ # Business logic (download, etc.)
│ └── *.ts # Utils, auth, logger, ratelimit
│
├── hooks/ # Custom React Hooks
├── types/ # TypeScript definitions
├── messages/ # i18n translations (en, id)
├── prisma/ # Database schema & migrations
│ ├── schema.prisma
│ └── migrations/ # Prisma migration history
├── scripts/ # Utility scripts
│ └── hash-password.sh # bcrypt password hash generator
│
├── docker-compose.yml # Production stack
├── Dockerfile # Multi-stage optimized build
├── Caddyfile # Reverse proxy config
├── middleware.ts # Auth, i18n, rate limiting
└── next.config.mjs # Next.js + security headers
pnpm test # Run all tests
pnpm test -- --watch # Watch mode
pnpm test -- --coverage # Coverage reportnpx playwright install # Install browsers (first time)
pnpm test:e2e # Run E2E tests
npx playwright test --ui # Run with interactive UI
npx playwright show-report # View HTML report🔴 Container fails to start ("unhealthy")
# Check logs for errors
docker compose logs zee-index --tail 50
# Common causes:
# 1. Database not ready — increase start_period in healthcheck
# 2. Missing .env variables — check all required vars are set
# 3. Port conflict — ensure 3000, 5432, 6379 are free🔴 Login fails
- Verify
ADMIN_EMAILSmatches your email exactly (case-insensitive) - Check
ADMIN_PASSWORDhas no surrounding quotes in.env - For bcrypt: ensure
ADMIN_PASSWORD_HASHis a valid bcrypt hash - Clear browser cookies and retry
- Check
docker compose logs zee-indexfor[Auth]messages
🔴 Google Drive API errors (401/403)
- Verify
GOOGLE_REFRESH_TOKENis valid - Re-run
/setupflow to obtain a new token - Check API quota at Google Cloud Console
- Ensure the Google account has access to the target folders
🟡 Slow performance
- Enable Redis (don't rely on in-memory fallback)
- Check Google Drive API quota (default: 12,000 requests/min)
- Monitor with
docker compose exec zee-index sh -c "cat /proc/1/status | grep VmRSS" - Increase memory limit if needed:
NODE_OPTIONS=--max-old-space-size=512
🟡 Build fails in Docker
# Build without cache
docker compose build --no-cache
# Check disk space
df -h
# Ensure SKIP_ENV_VALIDATION=true is set for builds without full .env🟡 Database migration issues
# Check migration status
docker compose exec zee-index npx prisma migrate status
# Force apply migration
docker compose exec zee-index npx prisma migrate deploy
# Reset database (⚠️ destructive)
docker compose exec zee-index npx prisma migrate resetContributions are welcome! Here's how to get started:
# 1. Fork and clone
git clone https://github.com/YOUR_USERNAME/Zee-Index.git
cd Zee-Index
# 2. Create a feature branch
git checkout -b feat/amazing-feature
# 3. Install and develop
pnpm install && pnpm dev
# 4. Run all checks before committing
pnpm check:all
# 5. Commit with conventional format
git commit -m "feat: add amazing feature"
# 6. Push and open a Pull Request
git push origin feat/amazing-featureCommit Convention (Conventional Commits):
| Prefix | Usage |
|---|---|
feat: |
New feature |
fix: |
Bug fix |
refactor: |
Code restructuring |
security: |
Security improvement |
docs: |
Documentation |
chore: |
Maintenance |
test: |
Adding/updating tests |
This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0) with an attribution requirement.
- ✅ Free to use, modify, and distribute
- ✅ Commercial use allowed
⚠️ Attribution required: display© 2025 Muhammad Ibnu Fauziin your deployment⚠️ Modified versions that are hosted must share source code⚠️ Changes must be documented
See the LICENSE file for full details.
Built with these amazing open-source projects:
- Next.js — The React framework
- VidStack — Video player components
- Radix UI — Accessible UI primitives
- TanStack — React Query & Virtual
- Framer Motion — Animation library
- Zustand — State management
- Prisma — Database ORM
- Lucide — Beautiful icons