A personal project replicating TikTok's core features, built with Next.js (frontend) and Laravel 12 (backend API) to practice full-stack development.
Author: Nguyen Dang Truong
Live Demo: taplamit.tech
- Infinite scrolling video feed
- User authentication (login, signup)
- Like, comment, and share videos
- Follow/unfollow users
- Search videos & profiles
- Dark mode support
- Internationalization (English & Vietnamese)
- Responsive design for mobile & desktop
This repository currently runs as a monorepo with:
- Frontend: Next.js 15 (TypeScript)
- Backend: Laravel 12 API (JWT)
- Infrastructure: Docker Compose + Nginx + PostgreSQL + Redis + MinIO + MailCatcher
- Backend Nginx (
backend-nginx) serves the Laravel API viaphp-fpm - Frontend Nginx (
frontend-nginx) proxies all requests to Next.js (frontend) - Background jobs (queues) are processed by Laravel queue worker (
worker) - Object storage is provided by MinIO (S3-compatible)
- Development email testing is handled by MailCatcher (SMTP + web UI)
Default local URLs with Docker:
- App (Frontend):
http://localhost:9697 - API Base (Backend):
http://localhost:9696/api - MinIO API:
http://localhost:9000 - MinIO Console:
http://localhost:9001 - MailCatcher UI:
http://localhost:1080
The repository now separates environment variables into 4 layers:
- Root
.env: Docker Compose infrastructure variables only (ports, container names, postgres container credentials, selected env file paths) backend/.env: Laravel application variables onlyfrontend/.env: Next.js application variables onlyai/.env: AI moderation service and AI scripts variables only
You can switch service env files independently by editing root .env:
BACKEND_ENV_FILE=./backend/.envFRONTEND_ENV_FILE=./frontend/.envAI_ENV_FILE=./ai/.env
- Copy environment files:
Copy-Item .env.example .env
Copy-Item backend/.env.example backend/.env
Copy-Item frontend/.env.example frontend/.env
Copy-Item ai/.env.example ai/.env- Start development stack:
docker compose -f compose.dev.yaml up --build -dThis also starts a dedicated queue worker container (worker).
- Install backend dependencies and run migrations:
docker compose -f compose.dev.yaml exec workspace composer install
docker compose -f compose.dev.yaml exec workspace php artisan migrateThe repository includes a dedicated worker service so you don't need to run php artisan queue:work manually.
Development:
- Worker runs
supervisordand loads config from.docker/development/backend/worker/supervisord.conf(mounted). - Tail logs:
docker compose -f compose.dev.yaml logs -f worker - Restart worker:
docker compose -f compose.dev.yaml restart worker
Production:
- Worker runs
supervisordwith/etc/supervisord.confbaked into the image from.docker/production/backend/worker/supervisord.conf. - After changing the config, rebuild + restart:
docker compose -f compose.prod.yaml up -d --build worker
If you need a different env profile (for example staging/production-like), update these variables in root .env before running compose:
NEXT_APP_ENVBACKEND_ENV_FILEFRONTEND_ENV_FILEAI_ENV_FILE
Root .env (copy from .env.example) contains infrastructure variables for both services:
MINIO_PORTMINIO_PORT_CONSOLEMINIO_ROOT_USERMINIO_ROOT_PASSWORDMAILCATCHER_WEB_PORTMAILCATCHER_SMTP_PORT
Environment behavior:
- Development (
compose.dev.yaml): MinIO and MailCatcher run by default. - Production (
compose.prod.yaml): MinIO runs by default, MailCatcher is optional and attached to profiletools.
Start MailCatcher in production-like stack only when required:
docker compose -f compose.prod.yaml --profile tools up -d mailcatcherRecommended Docker-based backend mail/storage values in backend/.env:
MAIL_MAILER=smtp
MAIL_HOST=mailcatcher
MAIL_PORT=1025
AWS_ACCESS_KEY_ID=minio_root_user
AWS_SECRET_ACCESS_KEY=minio_root_password
AWS_ENDPOINT=http://minio:9000
AWS_USE_PATH_STYLE_ENDPOINT=true- Docker and Nginx: .docker/README.md
- Backend API: backend/README.md
- Frontend app: frontend/README.md








