Streaming platform aggregator — browse and watch short dramas, films, anime, and Indonesian content from 16+ content providers through the Cutad API. Built with Laravel 12 and Docker.
- Features
- Tech Stack
- Project Structure
- Requirements
- Installation
- Environment Variables
- Payment System
- VIP & Voucher System
- Admin Panel
- API Architecture
- Sitemap & SEO
- Local Development
- Docker Services
- License
- 16+ content providers — ReelShort, DotDrama, NetShort, Hollywood, Anime, Drama Korea, Film Indonesia, and more
- Categories — Short Drama, Drama, Film, Anime
- Parallel full-text search across all providers simultaneously
- Provider browsing with ranked and categorized content
- Content ranking with popularity and trending indicators
- HLS video streaming with HLS proxy for cross-origin delivery
- Subtitle proxy for seamless subtitle loading
- Episode navigation within multi-episode content
- Video proxy for secure media delivery
- Watch history tracking — resume where you left off
- Favorites / bookmarking with toggle support
- VIP subscription system via voucher codes
- QRIS dynamic payment (Indonesian QR payment standard)
- Dynamic QR code generation with CRC16 error-checking
- Mutasi API integration for automatic payment verification
- Real-time payment status polling
- Support for all Indonesian QRIS-enabled banking apps
- Voucher tiers:
3hari,7hari,15hari,30hari,3bulan,1tahun - Device-based binding — up to 5 devices per voucher code
- Voucher redemption and status checking
- Flexible VIP purchase and activation flow
- Filament-based admin dashboard
- Voucher generation, editing, toggling, and deletion
- Per-voucher device management (add/remove devices)
- Payment transaction log and verification
- API caching layer (Redis-backed) to reduce external API calls
- Sitemap generation with 5 sitemap clusters for Google indexing
- Docker multi-stage builds (small final image)
- Redis for sessions, cache, and queue management
| Layer | Technology |
|---|---|
| Backend | Laravel 12, PHP 8.2 |
| Database | MySQL 8.0 |
| Cache / Queue / Sessions | Redis |
| Frontend | Blade templates, Tailwind CSS, Vite |
| Admin Panel | Filament |
| Web Server | Nginx |
| Process Manager | Supervisor (php-fpm + nginx) |
| Containerization | Docker, Docker Compose |
| Payment | QRIS (Indonesian QR standard), Mutasi API |
dracin/
├── app/
│ ├── Http/Controllers/
│ │ ├── AdminController.php # Admin panel (Filament)
│ │ ├── FavoriteController.php # Favorites toggle & listing
│ │ ├── HistoryController.php # Watch history
│ │ ├── HomeController.php # Homepage / landing
│ │ ├── PaymentController.php # QRIS payment flow
│ │ ├── ProviderController.php # Content provider browsing
│ │ ├── SearchController.php # Cross-provider search
│ │ ├── SitemapController.php # Sitemap XML generation
│ │ ├── StreamController.php # HLS/subtitle/video proxy
│ │ ├── VipController.php # VIP purchase & redemption
│ │ └── WatchController.php # Content detail & watch page
│ ├── Models/
│ │ ├── ApiCache.php # External API response cache
│ │ ├── Content.php # Content metadata
│ │ ├── ContentEpisode.php # Episode data
│ │ ├── ContentRanking.php # Rankings & trending
│ │ ├── Favorite.php # User favorites
│ │ ├── Payment.php # QRIS payment records
│ │ ├── User.php # Authenticated users
│ │ ├── Voucher.php # VIP voucher codes
│ │ ├── VoucherDevice.php # Device-to-voucher bindings
│ │ └── WatchHistory.php # Watch history entries
│ └── Services/
│ ├── CutadApiService.php # Content API client (HTTP pool)
│ ├── MutasiService.php # Payment verification client
│ └── QrisService.php # QRIS QR code generation + CRC16
├── config/ # Laravel configuration
├── database/ # Migrations, factories, seeders
├── nginx/
│ └── nginx.conf # Nginx server configuration
├── public/ # Web root
├── resources/ # Blade views, CSS, JS
├── routes/
│ └── web.php # All application routes
├── storage/ # Logs, cache, uploads
├── docker-compose.yml # Docker services (app + MySQL + Redis)
├── Dockerfile # Multi-stage Docker build
├── supervisord.conf # Supervisor process configuration
├── composer.json # PHP dependencies + setup scripts
├── package.json # Frontend dependencies
└── vite.config.js # Vite bundler configuration
- PHP 8.2+
- Composer 2.x
- MySQL 8.0
- Redis 7.x
- Node.js 20+ & npm 10+
- Docker 24+
- Docker Compose v2+
# 1. Clone the repository
git clone <your-repo-url> dracin
cd dracin
# 2. Create and configure environment
cp .env.example .env
# Edit .env with your credentials (see Environment Variables below)
# 3. Start all services
docker compose up -d --build
# 4. Generate app key and run migrations
docker compose exec app php artisan key:generate
docker compose exec app php artisan migrate
# 5. Access the application
# Web: http://localhost:1100
# Admin: http://localhost:1100/admin# 1. Clone and configure
git clone <your-repo-url> dracin
cd dracin
# 2. One-command setup
composer setup
# OR step-by-step:
cp .env.example .env
composer install
php artisan key:generate
php artisan migrate
npm install && npm run build
# 3. Start development server
composer dev
# Starts: server, queue worker, log viewer, and Vite concurrentlyNote:
composer setuprunscomposer install, copies.env.example, generates the app key, runs migrations, installs npm packages, and builds frontend assets — all in one command.
Copy .env.example to .env and fill in the required variables:
| Variable | Required | Description |
|---|---|---|
CUTAD_API_KEY |
✅ | API key for Cutad content provider |
DB_PASSWORD |
✅ | MySQL database password |
STATIC_QRIS_STRING |
✅ | QRIS static payment string for QR generation |
MUTASI_API_URL |
✅ | Mutasi API endpoint for payment verification |
MUTASI_USERNAME |
✅ | Mutasi API username |
MUTASI_TOKEN |
✅ | Mutasi API authentication token |
MUTASI_ID |
✅ | Mutasi API account ID |
ADMIN_EMAIL |
✅ | Admin panel login email |
ADMIN_PASSWORD |
✅ | Admin password as bcrypt hash — generate with: php artisan tinker --execute="echo Hash::make('your_password');" |
CUTAD_CACHE_TTL |
— | API cache TTL in minutes (default: 30) |
REDIS_PASSWORD |
— | Redis password (default: none) |
Devanze Mirai TV uses the QRIS (Quick Response Code Indonesian Standard) payment system for VIP subscriptions.
User selects VIP plan → System generates QRIS QR code →
User scans with banking app → System polls Mutasi API →
Payment confirmed → VIP activated
| Component | File | Purpose |
|---|---|---|
| QR Generation | app/Services/QrisService.php |
Builds QRIS payload with CRC16 checksum, renders QR code |
| Payment Gateway | app/Services/MutasiService.php |
Verifies incoming payments via Mutasi API |
| Payment Controller | app/Http/Controllers/PaymentController.php |
Orchestrates payment creation, status polling, and confirmation |
| Code | Duration |
|---|---|
3hari |
3 days |
7hari |
7 days |
15hari |
15 days |
30hari |
30 days |
3bulan |
3 months |
1tahun |
1 year |
Each voucher code supports up to 5 devices. Devices are identified and bound at redemption time, preventing code sharing beyond the allowed limit.
Admins can generate, edit, enable/disable, and delete voucher codes through the admin panel. Per-voucher device management allows viewing and revoking individual device bindings.
The admin panel is built with Filament and provides:
- Dashboard — overview of system state
- Voucher Management — generate, edit, toggle, and delete voucher codes
- Device Management — view, add, and revoke devices per voucher
- Payment Logs — view and verify payment transactions
Access: http://localhost:1100/admin
Admin credentials are set via
ADMIN_EMAILandADMIN_PASSWORDin.env. The password must be a bcrypt hash — generate with:php artisan tinker --execute="echo Hash::make('your_password');"
The CutadApiService communicates with the Cutad API to aggregate content from 16+ providers. It uses Laravel's HTTP pool (Http::pool()) to execute requests to all providers in parallel, dramatically reducing response times for search and browse operations.
A Redis-backed ApiCache model stores API responses with configurable TTL (CUTAD_CACHE_TTL, default 30 minutes). This minimizes external API calls for frequently-accessed content like homepages, provider listings, and rankings.
The StreamController provides three proxy endpoints:
| Route | Purpose |
|---|---|
/video-proxy |
Standard video file proxying |
/hls-proxy |
HLS manifest + segment proxying for cross-origin delivery |
/subtitle-proxy |
Subtitle file proxying |
These proxies ensure media content loads correctly regardless of the origin server's CORS or access policies.
The SitemapController generates XML sitemaps organized into 5 clusters:
| Sitemap | URL | Content |
|---|---|---|
| Index | /sitemap.xml |
Master index referencing all clusters |
| Main | /sitemap-main.xml |
Homepage and static pages |
| Providers | /sitemap-providers.xml |
Provider listing pages |
| Short Drama | /sitemap-short.xml |
Short drama content entries |
| Drama | /sitemap-drama.xml |
Drama content entries |
| Film | /sitemap-film.xml |
Film content entries |
| Anime | /sitemap-anime.xml |
Anime content entries |
Submit the sitemap index to Google Search Console for optimal indexing.
# Start the full development environment
composer dev
# This launches concurrently:
# server — php artisan serve
# queue — php artisan queue:listen
# logs — php artisan pail
# vite — npm run dev (hot module replacement)The composer dev script uses npx concurrently to run all four services in one terminal with color-coded output.
Other useful commands:
php artisan test # Run PHPUnit tests
composer test # Same as above (clears config first)
php artisan pint # Format code with Laravel Pint
php artisan optimize # Cache config, routes, and views| Service | Image | Internal Port | Host Port | Purpose |
|---|---|---|---|---|
app |
Custom (Dockerfile) | 80 | 1100 |
PHP 8.2-FPM + Nginx + Supervisor |
db |
mysql:8.0 |
3306 | 3307 |
MySQL database |
redis |
redis:alpine |
6379 | 6380 |
Cache, sessions, queues |
The Dockerfile uses a multi-stage build:
Stage 1 (build):
php:8.2-fpm → install Node.js + extensions → composer install → npm ci → npm run build
Stage 2 (runtime):
php:8.2-fpm → install nginx + supervisor → copy built assets → optimize → run supervisor
This keeps the final image small by excluding build tooling (Node.js, Composer) from the runtime image.
docker compose up -d # Start all services
docker compose down # Stop all services
docker compose logs -f app # Follow app logs
docker compose exec app bash # Shell into app container
docker compose exec app php artisan # Run artisan commands
docker compose restart # Restart all servicesThis project is open-sourced software licensed under the MIT license.
Built with Laravel 12, Tailwind CSS, and ❤️