# Reader Project Đây là dự án nền tảng đọc truyện (Web Application) được xây dựng với kiến trúc hiện đại, kết hợp cơ sở dữ liệu quan hệ (PostgreSQL) và NoSQL (MongoDB) để tối ưu hóa việc lưu trữ và truy xuất nội dung văn bản lớn. ## 🚀 Tính năng nổi bật - **Xác thực & Phân quyền**: Đăng nhập bằng Google Authentication (NextAuth). Hỗ trợ phân quyền người dùng (USER, MOD, ADMIN). - **Quản lý nội dung (Dành cho MOD/ADMIN)**: Dashboard quản lý truyện, tải lên chương mới, quản lý trạng thái truyện (Đang ra, Hoàn thành, Tạm ngưng). - **Trải nghiệm đọc**: Khám phá truyện theo thể loại, tìm kiếm truyện, đọc chương truyện với hiệu suất cao (nội dung lưu ở MongoDB). - **Tương tác người dùng**: Tính năng tủ sách (bookmark) giúp lưu lại tiến độ đọc, hỗ trợ bình luận ở truyện và từng chương. ## 🛠 Tech Stack - **Framework**: [Next.js](https://nextjs.org/) (App Router), React 19 - **Styling**: [TailwindCSS v4](https://tailwindcss.com/) & [Radix UI](https://www.radix-ui.com/) (shadcn/ui) - **Database Hybrid**: - **PostgreSQL**: Lưu trữ dữ liệu cấu trúc (Tài khoản, Truyện, Thể loại, Bình luận, Tủ sách) thông qua **Prisma ORM**. - **MongoDB**: Lưu trữ nội dung lớn (Chương truyện) thông qua **Mongoose**. - **Auth**: [NextAuth.js](https://next-auth.js.org/) --- ## 💻 Hướng dẫn chạy Local (Phát triển) ### 1. Yêu cầu cài đặt - [Node.js](https://nodejs.org/) (Khuyến nghị bản LTS) - [pnpm](https://pnpm.io/) (Tool quản lý package) - Database: PostgreSQL và MongoDB đang chạy cục bộ hoặc trên máy chủ. ### 2. Cấu hình môi trường Tạo file `.env` ở thư mục gốc dựa trên `.env.example` (nếu có) hoặc điền các thông tin sau: ```env # URL kết nối PostgreSQL DATABASE_URL="postgresql://user:password@localhost:5432/reader?schema=public" # URL kết nối MongoDB MONGODB_URI="mongodb://user:password@localhost:27017/reader?authSource=admin" # Cấu hình NextAuth NEXTAUTH_SECRET="your-super-secret-key" NEXTAUTH_URL="http://localhost:3000" # API backend dùng chung cho web + mobile READER_API_ORIGIN="http://localhost:8000" # Cấu hình Google Login GOOGLE_CLIENT_ID="your_google_client_id" GOOGLE_CLIENT_SECRET="your_google_client_secret" # AI Tool cho MOD (LLM + web search) OPENAI_API_KEY="your_openai_api_key" # Tùy chọn, mặc định: gpt-4o-mini-search-preview OPENAI_WEB_MODEL="gpt-4o-mini-search-preview" # Cloudflare R2 (lưu ảnh bìa) R2_ACCOUNT_ID="your_cloudflare_account_id" R2_ACCESS_KEY_ID="your_r2_access_key_id" R2_SECRET_ACCESS_KEY="your_r2_secret_access_key" R2_BUCKET_NAME="your_r2_bucket_name" R2_PUBLIC_BASE_URL="https://your-public-r2-domain" ``` ### 3. Cài đặt dependencies và khởi tạo DB ```bash # Cài đặt các gói thư viện pnpm install # Đồng bộ schema xuống PostgreSQL và generate Prisma client npx prisma db push # hoặc (nếu muốn dùng migrate) # npx prisma migrate dev # Generate thư viện Prisma npx prisma generate ``` ### 4. Chạy môi trường phát triển ```bash pnpm dev ``` Truy cập vào [http://localhost:3000](http://localhost:3000) để xem ứng dụng. Lưu ý: các endpoint user-facing đã migrate (`/api/genres`, `/api/novels/*`, `/api/truyen/*`, `/api/chapters/*`, `/api/user/*`, `/api/auth/mobile-login`) sẽ được proxy sang `READER_API_ORIGIN`. --- ## 🏗 Hướng dẫn Build Để build project cho môi trường production: ```bash # Đảm bảo Prisma Client đã được generate npx prisma generate # Chạy lệnh build của Next.js pnpm build ``` Sau khi build xong, bạn có thể khởi chạy server production bằng: ```bash pnpm start ``` --- ## 🐳 Triển khai dưới dạng Docker Bạn có thể dễ dàng triển khai ứng dụng bằng nền tảng Docker. Dưới đây là cách đóng gói và chạy thông qua `docker-compose`. ### 1. Tạo file `Dockerfile` Tạo file `Dockerfile` ở thư mục gốc của dự án với cấu hình multi-stage build để tối ưu dung lượng: ```dockerfile # Stage 1: Dependencies FROM node:22-alpine AS deps WORKDIR /app COPY package.json pnpm-lock.yaml ./ RUN corepack enable pnpm && pnpm install --frozen-lockfile # Stage 2: Builder FROM node:22-alpine AS builder WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . # Tạo prisma client RUN npx prisma generate # Chạy build RUN corepack enable pnpm && pnpm build # Stage 3: Runner FROM node:22-alpine AS runner WORKDIR /app ENV NODE_ENV=production COPY --from=builder /app/public ./public COPY --from=builder /app/.next/standalone ./ COPY --from=builder /app/.next/static ./.next/static EXPOSE 3000 ENV PORT=3000 CMD ["node", "server.js"] ``` *(Lưu ý: Để build mục `standalone` hoạt động, bạn cần bổ sung `output: 'standalone'` trong file `next.config.mjs`)* ### 2. Tạo file `docker-compose.yml` Sử dụng Docker Compose để chạy ứng dụng (giả sử Database của bạn được host riêng hoặc bạn có thể thêm service DB vào file này): ```yaml version: '3.8' services: web: build: context: . dockerfile: Dockerfile image: reader-web:latest container_name: reader-app ports: - "3000:3000" env_file: - .env restart: unless-stopped ``` ### 3. Khởi chạy bằng Docker Chạy lệnh sau để build image và start container: ```bash # Build và chạy ngầm (detached mode) docker-compose up -d --build ``` Để xem log của container: ```bash docker-compose logs -f web ``` Dừng và xóa container: ```bash docker-compose down ```