StreamVid adalah aplikasi streaming video monorepo dengan frontend Angular dan backend NestJS. Platform ini punya dua role utama:
USERuntuk browsing dan menonton video dengan pengalaman dark-firstADMINuntuk mengelola katalog video, kategori, metadata konten, dan overview dashboard
Konten video tidak di-host langsung oleh aplikasi. Admin menambahkan video dari Doodstream, lalu backend mengambil metadata dan frontend memutar video lewat embedUrl.
- Monorepo
frontend+backend - Angular SPA dengan standalone components, Signals, NgRx untuk auth, dan Tailwind CSS v4
- NestJS REST API dengan Prisma dan PostgreSQL
- Integrasi Doodstream hanya lewat backend agar API key tetap aman
- Integrasi Backblaze B2 untuk thumbnail custom admin
- Dual-token auth: access token di memory, refresh token di
httpOnlycookie - Dashboard admin untuk video, kategori, profil, dan overview data
- Halaman publik tambahan untuk
explore,trending, danlibrary
Angular SPA (localhost:4200 / localhost via Docker)
|
v
NestJS API (/api, localhost:3000 di dev, internal container di Docker)
|
+--> PostgreSQL
|
+--> Doodstream API
|
+--> Backblaze B2 (thumbnail custom)
Prinsip penting:
- Frontend tidak boleh mengakses Doodstream API secara langsung
- Business logic backend berada di service, bukan controller
- Komponen frontend mengakses data lewat service, bukan
HttpClientlangsung - Dark mode adalah default render untuk seluruh pengalaman pengguna
- Angular 21
- Standalone Components
- Tailwind CSS v4
- Angular Signals
- NgRx Store + Effects untuk auth global
- Angular Router lazy loading
@lucide/angular
- NestJS 11
- TypeScript strict mode
- Prisma 7
- PostgreSQL 15
- JWT + Passport
class-validator+class-transformerbcrypt
streamvid/
|-- AGENTS.md
|-- ARCHITECTURE.md
|-- DESIGN_SYSTEM.md
|-- docker-compose.yml
|-- backend/
`-- frontend/
Folder utama:
frontend/berisi Angular SPA untuk public pages dan admin dashboardbackend/berisi NestJS API, Prisma schema, migration, dan seed- file root seperti
ARCHITECTURE.mddanDESIGN_SYSTEM.mdmenjadi acuan struktur dan visual project
- Home page dengan daftar video
- Explore page untuk browsing konten
- Trending page
- Detail video berdasarkan
slug - Profil user setelah login
- Library user setelah login
- Layout dark-first dengan visual premium neon-tech
- Login user dan admin
- Dashboard ringkasan data
- Manajemen video
- Manajemen kategori
- Profil admin
- Upload thumbnail custom untuk video admin
StreamVid memakai strategi dual token:
accessTokenberlaku 15 menit dan disimpan di memory frontendrefreshTokenberlaku 7 hari dan disimpan di cookiehttpOnly
Flow singkat:
POST /api/auth/loginmengembalikanaccessToken- Backend menyetel cookie
refreshToken - Request berikutnya mengirim
Authorization: Bearer <accessToken> - Saat token kedaluwarsa, frontend memanggil
POST /api/auth/refresh - Jika refresh gagal, user diarahkan kembali ke
/login
Semua integrasi Doodstream harus lewat backend.
- Admin memasukkan URL Doodstream
- Frontend memanggil backend
- Backend mengekstrak
file_codedari URL - Backend memanggil Doodstream API
- Metadata dinormalisasi lalu disimpan ke database
- Frontend memakai
embedUrluntuk player iframe
Data video yang relevan disimpan di database:
doodUrldoodFileIdembedUrlthumbnailUrldurationfileSizestatus
Thumbnail default video tetap bisa berasal dari Doodstream, tetapi admin juga bisa mengunggah thumbnail custom.
- Admin memilih file thumbnail di dashboard video
- Frontend mengirim
multipart/form-datakePOST /api/admin/videos/thumbnail - Backend mengunggah file ke Backblaze B2
- Backend mengembalikan URL publik file
- URL itu dipakai sebagai
thumbnailUrlsaat create atau update video
Catatan:
- Integrasi Backblaze hanya berjalan di backend
- File yang diterima dibatasi ke JPG, PNG, atau WEBP
- Batas ukuran thumbnail saat ini adalah 5MB
- Jika thumbnail custom tidak diisi, video tetap memakai thumbnail dari metadata Doodstream
- Node.js 20 LTS atau lebih baru
- npm
- Docker Desktop atau Docker Engine
rtkuntuk menjalankan command project
Verifikasi rtk:
rtk --version
rtk gainrtk proxy powershell -NoProfile -Command "cd frontend; npm install"
rtk proxy powershell -NoProfile -Command "cd backend; npm install"rtk proxy powershell -NoProfile -Command "docker compose up -d postgres"Jika ingin menjalankan seluruh stack Docker sekaligus:
rtk proxy powershell -NoProfile -Command "docker compose up --build"Catatan Docker:
- Frontend container dibind ke
127.0.0.1:8088di host - Frontend production memanggil API lewat path relatif
/api - Nginx di frontend me-proxy
/apike servicebackenddi network Docker - Service
backendtidak dipublish ke host secara default - Service
postgresdipublish ke127.0.0.1:5433khusus untuk local development backend di host - Port
8088hanya bisa diakses dari host server sendiri dan ditujukan untuk reverse proxy Nginx host - Binding
127.0.0.1:5433tidak mengekspos Postgres ke publik internet dan tidak mengubah koneksi internal antar-container (postgres:5432)
Service PostgreSQL di docker-compose.yml memakai konfigurasi default:
- database:
streamvid - user:
streamvid_user - password:
streamvid_pass - host internal Docker:
postgres:5432 - host local development:
localhost:5433
Buat file backend/.env:
DATABASE_URL="postgresql://streamvid_user:streamvid_pass@localhost:5433/streamvid"
JWT_SECRET="replace-with-a-strong-secret"
DOODSTREAM_API_KEY="replace-with-your-doodstream-key"
BACKBLAZE_B2_KEY_ID="replace-with-your-backblaze-key-id"
BACKBLAZE_B2_APPLICATION_KEY="replace-with-your-backblaze-application-key"
BACKBLAZE_B2_BUCKET_NAME="replace-with-your-backblaze-bucket-name"
# Optional when using a CDN or custom public domain:
# BACKBLAZE_B2_PUBLIC_BASE_URL="https://cdn.example.com"
PORT=3000
NODE_ENV=developmentCatatan:
- Untuk development lokal di luar Docker, sesuaikan host database Anda sendiri
- Untuk runtime Docker Compose,
DATABASE_URLdioverride menjadipostgresql://streamvid_user:streamvid_pass@postgres:5432/streamvid DATABASE_URLwajib ada untuk Prisma dan seedJWT_SECRETdipakai untuk access token dan refresh tokenDOODSTREAM_API_KEYhanya boleh dipakai di backendBACKBLAZE_B2_*hanya dipakai di backend untuk thumbnail custom- Jika satu application key bisa mengakses lebih dari satu bucket, isi
BACKBLAZE_B2_BUCKET_NAMEatauBACKBLAZE_B2_BUCKET_IDsecara eksplisit
rtk proxy powershell -NoProfile -Command "cd backend; npx prisma migrate dev"
rtk proxy powershell -NoProfile -Command "cd backend; npx prisma generate"rtk proxy powershell -NoProfile -Command "cd backend; npx prisma db seed"Akun demo dari seed:
- Admin:
admin@streamvid.local/Admin123! - User:
user@streamvid.local/User123!
Backend:
rtk npm run start:dev --prefix backendFrontend:
rtk proxy powershell -NoProfile -Command "cd frontend; ng serve"URL default:
- Frontend:
http://localhost:4200 - Backend API:
http://localhost:3000/api - Docker frontend internal host binding:
http://127.0.0.1:8088
Untuk server yang menjalankan banyak container Docker, StreamVid tidak memakai port publik 80 secara langsung. Container frontend dibind ke 127.0.0.1:8088, lalu Nginx di host server menjadi gateway publik pada port 80 dan 443.
Contoh alur:
internet
-> nginx host server
-> http://127.0.0.1:8088
-> streamvid_frontend
-> /api diteruskan ke backend:3000 oleh nginx di container frontend
Contoh konfigurasi Nginx host:
server {
listen 80;
server_name streamvid.example.com;
location / {
proxy_pass http://127.0.0.1:8088;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Aktivasi dasar di Ubuntu:
sudo ln -s /etc/nginx/sites-available/streamvid /etc/nginx/sites-enabled/streamvid
sudo nginx -t
sudo systemctl reload nginxfrontend/src/environments/environment.tsdipakai untuk development lokal dan menunjuk kehttp://localhost:3000/apifrontend/src/environments/environment.prod.tsdipakai untuk build production dan Docker, denganapiUrl: '/api'- Build production Angular harus memakai file replacement environment production
rtk npm run build --prefix frontend
rtk npm run test --prefix frontend
rtk proxy powershell -NoProfile -Command "cd frontend; ng serve"rtk npm run build --prefix backend
rtk npm run test --prefix backend
rtk proxy powershell -NoProfile -Command "cd backend; npm run test:e2e"
rtk proxy powershell -NoProfile -Command "cd backend; npm run start:dev"rtk proxy powershell -NoProfile -Command "cd backend; npx prisma migrate dev"
rtk proxy powershell -NoProfile -Command "cd backend; npx prisma generate"
rtk proxy powershell -NoProfile -Command "cd backend; npx prisma studio"/home video list/explorebrowse katalog video/trendingdaftar video trending/video/:slugdetail video/profileprofil user/librarylibrary user/loginlogin/admin/dashboarddashboard admin/admin/videosmanajemen video/admin/categoriesmanajemen kategori/admin/profileprofil admin
AuthModuleUsersModuleVideosModuleCategoriesModuleDoodstreamModulePrismaModule
POST /api/auth/registerPOST /api/auth/loginPOST /api/auth/logoutPOST /api/auth/refreshGET /api/auth/meGET /api/videosGET /api/videos/trendingGET /api/videos/:slugGET /api/categoriesGET /api/admin/statsGET /api/admin/videosPOST /api/admin/videosPOST /api/admin/videos/thumbnailPUT /api/admin/videos/:idPATCH /api/admin/videos/:id/statusDELETE /api/admin/videos/:idGET /api/admin/categoriesPOST /api/admin/categoriesPATCH /api/admin/categories/:idDELETE /api/admin/categories/:id
Model utama di Prisma:
UserVideoCategoryTagView
Keputusan data penting:
- Primary key memakai UUID
- Video memakai
sluguntuk URL yang lebih ramah viewCountdisimpan di tabelVideountuk performafileSizememakaiBigInt
- Gunakan
rtkuntuk semua command CLI project - Jangan simpan token di
localStorageatausessionStorage - Jangan expose
DOODSTREAM_API_KEYke frontend - Jangan tambahkan business logic berat di controller backend
- Jangan buat
NgModulebaru di frontend - Gunakan standalone components untuk semua komponen Angular
- Jaga dark mode sebagai default render
Dokumen-dokumen tersebut adalah source of truth untuk keputusan arsitektur, aturan frontend, dan visual system StreamVid.