+
+
+
+### 3. Tạo Dockerfile
+
+> Vì chúng tôi không muốn tạo biến môi trường (environment variables) server vào container, vì thế [các bước xác thực biến môi trường](/vi/usage/env-variables) sẽ không thành công. Để ngăn điều này, chúng tôi đã thêm flag `SKIP_ENV_VALIDATION=1` vào lệnh build để không xác thực biến môi trường tại thời điểm build.
+
+
+
+ Click vào đây để xem nội dung của Dockerfile:
+
+
+
+```docker
+##### DEPENDENCIES
+
+FROM --platform=linux/amd64 node:20-alpine AS deps
+RUN apk add --no-cache libc6-compat openssl
+WORKDIR /app
+
+# Install Prisma Client - remove if not using Prisma
+
+COPY prisma ./
+
+# Install dependencies based on the preferred package manager
+
+COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml\* ./
+
+RUN \
+ if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
+ elif [ -f package-lock.json ]; then npm ci; \
+ elif [ -f pnpm-lock.yaml ]; then npm install -g pnpm && pnpm i; \
+ else echo "Lockfile not found." && exit 1; \
+ fi
+
+##### BUILDER
+
+FROM --platform=linux/amd64 node:20-alpine AS builder
+ARG DATABASE_URL
+ARG NEXT_PUBLIC_CLIENTVAR
+WORKDIR /app
+COPY --from=deps /app/node_modules ./node_modules
+COPY . .
+
+# ENV NEXT_TELEMETRY_DISABLED 1
+
+RUN \
+ if [ -f yarn.lock ]; then SKIP_ENV_VALIDATION=1 yarn build; \
+ elif [ -f package-lock.json ]; then SKIP_ENV_VALIDATION=1 npm run build; \
+ elif [ -f pnpm-lock.yaml ]; then npm install -g pnpm && SKIP_ENV_VALIDATION=1 pnpm run build; \
+ else echo "Lockfile not found." && exit 1; \
+ fi
+
+##### RUNNER
+
+FROM --platform=linux/amd64 gcr.io/distroless/nodejs20-debian12 AS runner
+WORKDIR /app
+
+ENV NODE_ENV production
+
+# ENV NEXT_TELEMETRY_DISABLED 1
+
+COPY --from=builder /app/next.config.js ./
+COPY --from=builder /app/public ./public
+COPY --from=builder /app/package.json ./package.json
+
+COPY --from=builder /app/.next/standalone ./
+COPY --from=builder /app/.next/static ./.next/static
+
+EXPOSE 3000
+ENV PORT 3000
+
+CMD ["server.js"]
+```
+
+> **_Ghi chú_**
+>
+> - _Việc giả lập môi trường bằng `--platform=linux/amd64` có thể là không cần thiết sau khi chuyển sang Node 18._
+> - _Tham khảo [`node:alpine`](https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine) để hiểu tại sao `libc6-compat` có thể cần thiết._
+> - _Sử dụng Alpine 3.17 [có thể tạo ra một số vấn đề với Prisma](https://github.com/t3-oss/create-t3-app/issues/975). Vì thế, hãy đặt `engineType = "binary"` giải quyết vấn đề trong Alpine 3.17, tuy nhiên [hiệu suất sẽ bị ảnh hưởng](https://www.prisma.io/docs/concepts/components/prisma-engines/query-engine#the-query-engine-at-runtime)._
+> - _Next.js thu thập [dữ liệu sử dụng tổng quan](https://nextjs.org/telemetry). Bỏ comment dòng đầu tiên của `ENV NEXT_TELEMETRY_DISABLED 1` để tắt thu thập dữ liệu (telemetry) trong quá trình build. Bỏ comment dòng thứ hai để tắt thu thập dữ liệu (telemetry) trong quá trình runtime._
+
+
+
+
+## Xây dựng và chạy image cục bộ
+
+Xây dựng và chạy image này cục bộ với các lệnh sau:
+
+```bash
+docker build -t ct3a-docker --build-arg NEXT_PUBLIC_CLIENTVAR=clientvar .
+docker run -p 3000:3000 -e DATABASE_URL="database_url_goes_here" ct3a-docker
+```
+
+Mở [localhost:3000](http://localhost:3000/) để xem ứng dụng của bạn đang chạy.
+
+## Docker Compose
+
+Bạn có thể sử dụng Docker Compose để xây dựng image và chạy container.
+
+
+
+ Theo các bước 1-3 ở trên, click vào đây, và bao gồm nội dung trong docker-compose.yml:
+
+
+
+```yaml
+version: "3.9"
+services:
+ app:
+ platform: "linux/amd64"
+ build:
+ context: .
+ dockerfile: Dockerfile
+ args:
+ NEXT_PUBLIC_CLIENTVAR: "clientvar"
+ working_dir: /app
+ ports:
+ - "3000:3000"
+ image: t3-app
+ environment:
+ - DATABASE_URL=database_url_goes_here
+```
+
+Xây dựng và chạy bằng lệnh `docker compose up --build`:
+
+```bash
+docker compose up --build
+```
+
+Mở [localhost:3000](http://localhost:3000/) để xem ứng dụng của bạn đang chạy.
+
+
+
+
+## Triển khai lên Railway
+
+Bạn có thể sử dụng một PaaS như [Railway's](https://railway.app) để tự động triển khai [Dockerfile](https://docs.railway.app/deploy/dockerfiles) của bạn. Nếu bạn đã cài đặt [Railway CLI](https://docs.railway.app/develop/cli#install) bạn có thể triển khai ứng dụng của bạn với các lệnh sau:
+
+```bash
+railway login
+railway init
+railway link
+railway up
+railway open
+```
+
+Đi đến "Variables" và thêm `DATABASE_URL` của bạn. Sau đó đi đến "Settings" và chọn "Generate Domain". Để tham khảo một ví dụ được triển khai trên Railway, truy cập [ct3a-docker.up.railway.app](https://ct3a-docker.up.railway.app/).
+
+## Tài liệu hữu ích
+
+| Tài liệu | Đường dẫn |
+| ------------------------------------- | -------------------------------------------------------------------- |
+| Tài liệu Dockerfile | https://docs.docker.com/engine/reference/builder/ |
+| Tài liệu Compose file version 3 | https://docs.docker.com/compose/compose-file/compose-file-v3/ |
+| Tài liệu Docker CLI | https://docs.docker.com/engine/reference/commandline/docker/ |
+| Tài liệu Docker Compose CLI | https://docs.docker.com/compose/reference/ |
+| Triển khai Next.js với Docker Image | https://nextjs.org/docs/deployment#docker-image |
+| Next.js trong Docker | https://benmarte.com/blog/nextjs-in-docker/ |
+| Ví dụ Next.js với Docker | https://github.com/vercel/next.js/tree/canary/examples/with-docker |
+| Tạo Docker Image của ứng dụng Next.js | https://blog.tericcabrel.com/create-docker-image-nextjs-application/ |
diff --git a/www/src/pages/vi/deployment/index.astro b/www/src/pages/vi/deployment/index.astro
new file mode 100644
index 0000000000..22aec56d1d
--- /dev/null
+++ b/www/src/pages/vi/deployment/index.astro
@@ -0,0 +1,24 @@
+---
+import IndexPage from "../../../components/docs/indexPage.astro";
+import { SIDEBAR, type Frontmatter } from "../../../config";
+import { getLanguageFromURL } from "../../../languages";
+import Layout from "../../../layouts/docs.astro";
+
+const frontmatter: Frontmatter = {
+ title: "Deployment",
+ layout: "docs",
+ description: "Learn how to deploy your T3 app to production.",
+};
+
+const lang = getLanguageFromURL(Astro.url.pathname);
+const sidebarEntries = SIDEBAR[lang]["Deployment"]!;
+const files = await Astro.glob("./*.{md,mdx,astro}");
+---
+
+
+
+
diff --git a/www/src/pages/vi/deployment/netlify.mdx b/www/src/pages/vi/deployment/netlify.mdx
new file mode 100644
index 0000000000..b7bd3b9448
--- /dev/null
+++ b/www/src/pages/vi/deployment/netlify.mdx
@@ -0,0 +1,93 @@
+---
+title: Netlify
+description: Triển khai lên Netlify
+layout: ../../../layouts/docs.astro
+lang: vi
+isMdx: true
+---
+
+import Callout from "../../../components/docs/callout.tsx";
+
+Netlify là một nhà cung cấp khác giúp bạn triển khai ứng dụng web của bạn tương tự như Vercel. Bạn có thể tham khảo [`ajcwebdev/ct3a-netlify`](https://github.com/ajcwebdev/ct3a-netlify) như là một repo ví dụ triển khai lên Netlify dựa trên tài liệu này.
+
+## Tại sao nên triển khai lên Netlify
+
+Một sự thật mà chúng ta không thể phủ nhận được đó chính là việc Vercel chính là cha đẻ của Next.js, thế nên Vercel hỗ trợ Next.js tốt hơn là điều tất nhiên. Thế nên, họ luôn đi đầu trong việc đảm bảo nền tảng được tối ưu hóa cho hiệu suất và nâng cao DX cho Next.js. Đối với hầu hết các trường hợp sử dụng, điều này sẽ đúng và sẽ không có lý do gì để chúng ta tách biệt ra khỏi cái khuôn khổ này.
+
+Và chúng ta cũng đều có chung một suy nghĩ rằng nhiều tính năng của Next.js chỉ được hỗ trợ trên Vercel. Mặc dù Vercel luôn đi đầu trong việc cho phép thử nghiệm các tính năng mới của Next.js và cho phép sử dụng chúng ngay khi được ra mắt, nhưng đồng thời cũng là trường hợp tương tự cho các nhà cung cấp khác như Netlify, khi mà họ cũng sẽ [nhanh chóng triển khai và phát hành hỗ trợ](https://www.netlify.com/blog/deploy-nextjs-13/) cho [các tính năng Next.js khi chúng được ra mắt](https://docs.netlify.com/integrations/frameworks/next-js/overview/).
+
+Tất nhiên, tất cả các nhà cung cấp triển khai sẽ đều có nhiều ưu và nhược điểm của riêng mình, vì không có một nhà cung cấp nào có thể có hỗ trợ tốt nhất cho tất cả các trường hợp sử dụng. Ví dụ, Netlify đã xây dựng hẳn một [runtime Next.js riêng cho Netlify's Edge Functions](https://github.com/netlify/next-runtime) (chạy trên Deno Deploy) và [duy trì middleware riêng để truy cập và sửa đổi HTTP responses](https://github.com/netlify/next-runtime#nextjs-middleware-on-netlify).
+
+
+ Để theo dõi những tính năng mới nhất của những phiên bản Next 13 non-stable,
+ xin mời tham khảo [Sử dụng Next 13 `app` directory trên
+ Netlify](https://github.com/netlify/next-runtime/discussions/1724).
+
+
+## Cấu hình dự án
+
+Có muôn vàn cách để cấu hình lệnh build cho dự án của bạn, bao gồm việc cấu hình trực tiếp qua Netlify CLI hoặc Netlify dashboard. Trong khi việc tạo và bao gồm một tệp [`netlify.toml`](https://docs.netlify.com/configure-builds/file-based-configuration/) là việc không bắt buộc, chúng tôi **khuyến khích** bạn nên làm điều này nhằm đảm bảo rằng các phiên bản được fork và clone của dự án sẽ dễ dàng triển khai lại.
+
+```toml
+[build]
+ command = "next build"
+ publish = ".next"
+```
+
+## Sử dụng Netlify Dashboard
+
+1. Hãy đẩy code của bạn lên một repository GitHub và đăng ký tài khoản [Netlify](https://app.netlify.com/signup). Sau khi đã tạo tài khoản, hãy click vào **Add new site** và sau đó **Import an existing project**.
+
+
+
+2. Kết nối với Git provider của bạn.
+
+
+
+3. Chọn repository của dự án của bạn.
+
+
+
+4. Netlify sẽ tự động phát hiện xem bạn có tệp `netlify.toml` hay không và tự động cấu hình lệnh build và thư mục publish.
+
+
+
+5. Click **Show advanced** và sau đó **New variable** để thêm biến môi trường của bạn.
+
+
+
+6. Chọn **Deploy site**, đợi cho quá trình build hoàn tất và xem trang web mới của bạn.
+
+## Sử dụng Netlify CLI
+
+Để triển khai sử dụng Netlify CLI, bạn phải đầu tiên đẩy code của bạn lên một repository GitHub và [cài đặt Netlify CLI](https://docs.netlify.com/cli/get-started/). Bạn có thể cài đặt `netlify-cli` dưới dạng **Dev Dependency** cho dự án hoặc cài đặt nó toàn cục trên máy của bạn với lệnh sau:
+
+```bash
+npm i -g netlify-cli
+```
+
+Để chạy dự án của bạn trên máy của bạn, chạy lệnh [`ntl dev`](https://docs.netlify.com/cli/get-started/#run-a-local-development-environment) và mở [`localhost:8888`](http://localhost:8888/) để xem dự án Netlify của bạn đang chạy:
+
+```bash
+ntl dev
+```
+
+Chạy lệnh [`ntl init`](https://docs.netlify.com/cli/get-started/#continuous-deployment) để bắt đầu cấu hình dự án của bạn:
+
+```bash
+ntl init
+```
+
+Nhập biến môi trường của dự án của bạn từ tệp `.env` với lệnh [`ntl env:import`](https://cli.netlify.com/commands/env#envimport):
+
+```bash
+ntl env:import .env
+```
+
+Triển khai dự án của bạn với lệnh [`ntl deploy`](https://docs.netlify.com/cli/get-started/#manual-deploys). Bạn sẽ cần truyền `--build` để chạy lệnh build trước khi triển khai và `--prod` để triển khai lên URL chính của trang web của bạn:
+
+```bash
+ntl deploy --prod --build
+```
+
+Để xem một ví dụ chạy trên Netlify, hãy truy cập [ct3a.netlify.app](https://ct3a.netlify.app/).
diff --git a/www/src/pages/vi/deployment/vercel.md b/www/src/pages/vi/deployment/vercel.md
new file mode 100644
index 0000000000..c618582637
--- /dev/null
+++ b/www/src/pages/vi/deployment/vercel.md
@@ -0,0 +1,62 @@
+---
+title: Vercel
+description: Triển khai lên Vercel
+layout: ../../../layouts/docs.astro
+lang: vi
+---
+
+Chúng tôi khuyến khích bạn nên triển khai ứng dụng của bạn lên [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss). Nó làm cho việc triển khai ứng dụng Next.js trở nên vô cùng dễ dàng.
+
+## Cấu hình dự án
+
+Vercel sẽ cấu hình lệnh build và đọc các thư mục một cách tự động. Tuy nhiên, bạn cũng có thể tự cấu hình thông tin này cùng với các cấu hình Vercel khác bằng cách tạo một file tên là [`vercel.json`](https://vercel.com/docs/project-configuration) và ghi đè các lệnh sau. Tuy nhiên, **Điều này hầu như không bắt buộc cho hầu hết các dự án.**
+
+```json
+{
+ "buildCommand": "npm run build",
+ "devCommand": "npm run dev",
+ "installCommand": "npm install"
+}
+```
+
+## Sử dụng trong Vercel Dashboard
+
+1. Sau khi đẩy code của bạn lên repository của bạn ở Github, bạn hãy đăng ký tài khoản [Vercel](https://vercel.com/?utm_source=t3-oss&utm_campaign=oss) với Github và click vào **Add New Project**.
+
+
+
+2. Thêm repository chứa source code của bạn.
+
+
+
+3. Thêm các biến môi trường.
+
+
+
+4. Chọn **Deploy**. Và kể từ bây giờ, mỗi khi nào bạn đẩy một thay đổi lên repository của bạn, Vercel sẽ tự động triển khai lại ứng dụng của bạn!
+
+## Sử dụng CLI của Vercel
+
+Để triển khai sử dụng CLI của Vercel, bạn phải trước tiên [cài đặt CLI của Vercel](https://vercel.com/docs/cli#installing-vercel-cli).
+
+```bash
+npm i -g vercel
+```
+
+Chạy lệnh [`vercel`](https://vercel.com/docs/cli/deploying-from-cli) để triển khai dự án của bạn.
+
+```bash
+vercel
+```
+
+Để thêm các biến môi trường như chuỗi kết nối cơ sở dữ liệu, bạn có thể sử dụng lệnh `--env DATABASE_URL=YOUR_DATABASE_URL_HERE`. Sử dụng `--yes` nếu bạn muốn bỏ qua các câu hỏi triển khai và mặc định đồng ý cho mỗi câu hỏi.
+
+```bash
+vercel --env DATABASE_URL=YOUR_DATABASE_URL_HERE --yes
+```
+
+Sau khi triển khai lần đầu tiên, lệnh này sẽ triển khai lên một nhánh preview. Nếu bạn muốn đẩy các thay đổi trực tiếp lên trang web live cho các triển khai tương lai, bạn sẽ cần phải bao gồm `--prod`.
+
+```bash
+vercel --prod
+```
diff --git a/www/src/pages/vi/examples.mdx b/www/src/pages/vi/examples.mdx
new file mode 100644
index 0000000000..bbbbcd4063
--- /dev/null
+++ b/www/src/pages/vi/examples.mdx
@@ -0,0 +1,23 @@
+---
+title: Ví dụ
+description: Ví dụ về các ứng dụng
+layout: ../../layouts/docs.astro
+lang: vi
+isMdx: true
+---
+
+import Callout from "../../components/docs/callout.tsx";
+import Form from "../../components/docs/exampleOptionForm.astro";
+
+Bạn có thể thử nghiệm các tổ hợp các công nghệ khác nhau mà create-t3-app cung cấp.
+
+
+ Hãy lưu ý rằng nạn không thể chọn cả `prisma` và `drizzle` cùng lúc.
+
+
+
+
+
+ Một số tính năng có thể không hoạt động nếu bạn không tạo tệp môi trường (env
+ file)
+
diff --git a/www/src/pages/vi/faq.mdx b/www/src/pages/vi/faq.mdx
new file mode 100644
index 0000000000..38abd2a817
--- /dev/null
+++ b/www/src/pages/vi/faq.mdx
@@ -0,0 +1,78 @@
+---
+title: Câu hỏi thường gặp
+description: Câu hỏi thường gặp về Create T3 App
+layout: ../../layouts/docs.astro
+lang: vi
+isMdx: true
+---
+
+import Callout from "../../components/docs/callout.tsx";
+
+Dưới đây là một số câu hỏi bạn sẽ thường gặp về Create T3 App.
+
+## Vậy bây giờ tôi có thể làm gì tiếp? Làm thế nào để tôi có thể tạo một ứng dụng với T3 Stack?
+
+Chúng tôi luôn cố gắng giữ cho dự án này đơn giản nhất có thể, vì vậy bạn có thể bắt đầu với những thứ đã được thiết lập sẵn, và thêm những thứ khác sau nếu như bạn cần.
+
+Nếu bạn không quen với các công nghệ được sử dụng trong dự án này, vui lòng tham khảo tài liệu tương ứng với công nghệ đó. Nếu bạn vẫn còn gặp khó khăn, hãy tham gia [Discord](https://t3.gg/discord) để được giải đáp thắc mắc của bạn.
+
+- [Next.js](https://nextjs.org/)
+- [NextAuth.js](https://next-auth.js.org)
+- [Prisma](https://prisma.io)
+- [Tailwind CSS](https://tailwindcss.com)
+- [tRPC](https://trpc.io)
+- [Drizzle](https://orm.drizzle.team/docs/overview)
+
+## Làm sao để ứng dụng của tôi được cập nhật ?
+
+Create T3 App là một công cụ dùng để tạo ra một bộ khung cho ứng dụng của bạn (scaffolding tool), không phải là một framework. Điều này có nghĩa là một khi bạn khởi tạo ứng dụng, nó hoàn toàn thuộc về bạn. Không có câu lệnh CLI nào tương tự như `postinstall` để giúp bạn cập nhật ứng dụng. Nếu bạn muốn theo dõi bất kỳ cập nhật nào chúng tôi thực hiện đối với template, bạn có thể [bật thông báo cho các bản phát hành](https://docs.github.com/en/account-and-profile/managing-subscriptions-and-notifications-on-github/setting-up-notifications/configuring-notifications#configuring-your-watch-settings-for-an-individual-repository) trên kho lưu trữ (repository) của chúng tôi. Tuy nhiên, việc áp dụng mọi thay đổi chúng tôi thực hiện đối với template vào ứng dụng của bạn là không thực sự cần thiết.
+
+## Hiện tại có bất kỳ tài liệu học tập nào không ?
+
+Mặc dù các tài liệu được liệt kê dưới đây là một số tài liệu tốt nhất hiện có dành cho T3 Stack, cộng đồng (và [Theo](https://youtu.be/rzwaaWH0ksk?t=1436)) khuyên bạn nên bắt đầu sử dụng và học hỏi stack trong quá trình xây dựng với nó.
+
+Nếu bạn đang cân nhắc Create T3 App, có khả năng bạn đã biết sử dụng một số phần của chiếc stack này. Vậy tại sao bạn không bắt đầu học các phần khác trong khi bạn xây dựng một cái gì đó, đúng không ?
+
+Tuy nhiên, chúng tôi cũng nhận ra kiểu học này không phù hợp với tất cả mọi người. Vì vậy, nếu bạn cảm thấy đã thử cách trên và vẫn muốn có thêm tài liệu, hoặc bạn không tự tin làm điều đó một mình và/hoặc cảm thấy quá tải bởi stack, vui lòng tham khảo các hướng dẫn tuyệt vời này về Create T3 App:
+
+### Bài viết
+
+Một số bài viết này có thể đã cũ.
+
+- [A first look at Create T3 App](https://dev.to/ajcwebdev/a-first-look-at-create-t3-app-1i8f)
+- [Migrating your T3 App into a Turborepo](https://www.jumr.dev/blog/t3-turbo)
+- [Integrating Stripe into your T3 App](https://blog.nickramkissoon.com/posts/integrate-stripe-t3)
+
+### Video
+
+- [From 0 to Production - The Modern React Tutorial (RSCs, Next.js, Shadui, Drizzle, TS and more)](https://www.youtube.com/watch?v=d5x0JCZbAJs) **(recommended)** (updated 2024)\*
+- [Jack Herrington - Build a Note Taking app with the T3 Stack](https://www.youtube.com/watch?v=J1gzN1SAhyM)
+- [Build a Twitter Clone with the T3 Stack - tRPC, Next.js, Prisma, Tailwind & Zod](https://www.youtube.com/watch?v=nzJsYJPCc80)
+- [Build a Blog With the T3 Stack - tRPC, TypeScript, Next.js, Prisma & Zod](https://www.youtube.com/watch?v=syEWlxVFUrY)
+- [Build a Live Chat Application with the T3 Stack - TypeScript, Tailwind, tRPC](https://www.youtube.com/watch?v=dXRRY37MPuk)
+- [The T3 Stack - How We Built It](https://www.youtube.com/watch?v=H-FXwnEjSsI)
+- [An overview of the Create T3 App (Next, Typescript, Tailwind, tRPC, Next-Auth)](https://www.youtube.com/watch?v=VJH8dsPtbeU)
+
+## Tại sao lại có các file `.js` trong dự án?
+
+Theo [T3-Axiom #3](/en/introduction#typesafety-isnt-optional), chúng tôi đề cao tính toàn vẹn của kiểu dữ liệu (typesafety). Tuy vậy, không phải tất cả các framework và plugin đều hỗ trợ TypeScript, điều này có nghĩa là một số tệp cấu hình phải ở dưới dạng `.js`.
+
+Chúng tôi nhấn mạnh rằng các tệp này được viết dưới dạng JavaScript vì một lý do, đó chính là khai báo kiểu của mỗi tệp (`cjs` hoặc `mjs`) tùy thuộc vào những gì được hỗ trợ bởi thư viện mà nó được sử dụng. Ngoài ra, tất cả các tệp `js` trong dự án này vẫn được kiểm tra kiểu dữ liệu bằng tùy chọn `checkJs` trong trình biên dịch (được định nghĩa trong tsconfig).
+
+## Tôi đang gặp khó khăn khi thêm i18n vào ứng dụng của tôi. Có bất kỳ tài liệu tham khảo nào tôi có thể sử dụng không?
+
+Chúng tôi đã quyết định không bao gồm i18n mặc định trong `create-t3-app` vì có rất nhiều ý kiến trái chiều xoay quanh chủ đề này và có nhiều cách để thực hiện nó.
+
+Tuy nhiên, nếu bạn gặp khó khăn khi thực hiện điều này và tham khảo muốn một dự án, chúng tôi có một [repository](https://github.com/juliusmarminge/t3-i18n) cho thấy cách bạn có thể thêm i18n vào một ứng dụng T3 sử dụng [next-i18next](https://github.com/i18next/next-i18next).
+
+## Tôi nên sử dụng `/app` từ Next.js 13 hay là vẫn sử dụng `/pages`?
+
+Bạn có thể chọn sử dụng cấu trúc thư mục `/app` khi khởi tạo một ứng dụng bằng Create T3 App. Tại thời điểm hiện tại, tính năng này đã được coi là đủ ổn định để được sử dụng trong môi trường production bởi cộng đồng T3 Stack. Để hiểu lý do tại sao chúng tôi đã tốn nhiều thời gian để đưa ra quyết định này, bạn có thể xem [video này](https://www.youtube.com/watch?v=PmBfq-SpzCU).
+
+Tuy nhiên, nếu bạn thực sự vẫn muốn sử dụng cấu trúc thư mục `/pages`, bạn vẫn có thể chọn nó. Chuyển đổi kiểu router của mà bạn đang dùng hiện tại có thể mất rất nhiều thời gian, vì vậy bạn đừng nên cảm thấy bị áp lực để làm điều đó không cần thiết.
+
+
+ Để xem danh sách các tính năng đã được hỗ trợ, dự kiến sẽ được hỗ trợ và đang
+ được hỗ trợ trong thư mục `/app`, truy cập [tài liệu beta của
+ Next.js](https://beta.nextjs.org/docs/app-directory-roadmap#supported-and-planned-features).
+
diff --git a/www/src/pages/vi/folder-structure-app.mdx b/www/src/pages/vi/folder-structure-app.mdx
new file mode 100644
index 0000000000..707df695c7
--- /dev/null
+++ b/www/src/pages/vi/folder-structure-app.mdx
@@ -0,0 +1,254 @@
+---
+title: Cấu trúc thư mục (App Router)
+description: Cấu trúc thư mục của một ứng dụng T3 được tạo mới với App Router
+layout: ../../layouts/docs.astro
+lang: vi
+isMdx: true
+---
+
+import Diagram from "../../components/docs/folderStructureDiagramApp.astro";
+import Form from "../../components/docs/folderStructureForm.astro";
+
+Vui lòng chọn các thư viện được đề cập ở dưới để xem cấu trúc thư mục của một ứng dụng T3 được tạo mới với các lựa chọn đó. Ở phía dưới, bạn sẽ tìm thấy mô tả chi tiết cho mỗi file trong cây thư mục.
+
+
+
+
+
+
+
+### `prisma`
+
+Thư mục `prisma` chứa file `schema.prisma` được sử dụng để cấu hình kết nối với cơ sở dữ liệu và định nghĩa schema cho cơ sở dữ liệu. Đây cũng là nơi lưu trữ các file migration và/hoặc seed script, nếu được sử dụng. Tham khảo [Cách sử dụng Prisma](/vi/usage/prisma) để biết thêm thông tin.
+
+
+
+
+### `public`
+
+Thư mục `public` chứa các file tĩnh (static assets) được phục vụ bởi web server. File `favicon.ico` là một ví dụ về file tĩnh.
+
+
+
+
+### `src/env`
+
+Được sử dụng để xác thực biến môi trường (environment variables) và định nghĩa kiểu cho biến môi trường (environment variables) đó - Tham khảo [Biến môi trường](/vi/usage/env-variables).
+
+
+
+
+### `src/app`
+
+Thư mục `app` chứa tất cả các định tuyến (routes) của ứng dụng Next.js. File `page.tsx` ở thư mục gốc `/app` là trang chủ của ứng dụng. File `layout.tsx` được sử dụng để định nghĩa layout cho ứng dụng và bao bọc ứng dụng với các provider. Tham khảo [tài liệu Next.js](https://nextjs.org/docs/app/building-your-application/routing) để biết thêm thông tin.
+
+
+
+
+#### `src/app/_components/post.tsx`
+
+File `post.tsx` là một ví dụ về client component mà một tRPC mutation được sử dụng.
+
+
+
+
+#### `src/app/api/auth/[...nextauth]/route.ts`
+
+File `[...nextauth]/route.ts` là slug route xác thực của NextAuth.js. Nó được sử dụng để xử lý các yêu cầu xác thực. Tham khảo [Cách sử dụng NextAuth.js](/vi/usage/next-auth) để biết thêm thông tin về NextAuth.js, và [Tài liệu Next.js Dynamic Routes](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes) để biết thông tin về các route catch-all/slug.
+
+
+
+
+#### `src/app/api/trpc/[trpc]/route.ts`
+
+File `[trpc].ts` là điểm xuất phát (entrypoint) API của tRPC. Nó được sử dụng để xử lý các yêu cầu tRPC. Tham khảo [Cách sử dụng tRPC](/vi/usage/trpc) để biết thêm thông tin về file này, và [Tài liệu Next.js Dynamic Routes](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes) để biết thông tin về các route catch-all/slug.
+
+
+
+
+### `src/server`
+
+Thư mục `server` được sử dụng để phân tách rõ ràng code chỉ được sử dụng và thực thi trên server.
+
+
+
+
+#### `src/server/auth.ts`
+
+Điểm xuất phát (entrypoint) cho logic xác thực phía server. Tại đây, chúng ta thiết lập các [tùy chọn cấu hình](/vi/usage/next-auth) NextAuth.js, thực hiện [module augmentation](/vi/usage/next-auth#inclusion-of-userid-on-the-session) cũng như cung cấp một số tiện ích DX cho việc xác thực như lấy session của người dùng ở phía server. Tham khảo [Cách sử dụng NextAuth.js](/vi/usage/next-auth#usage-with-trpc) để biết thêm thông tin.
+
+
+
+
+#### `src/server/db.ts`
+
+File `db.ts` được sử dụng để khởi tạo Prisma client ở phạm vi toàn cục (global scope). Tham khảo [Cách sử dụng Prisma](/vi/usage/prisma#prisma-client) và [các phương pháp tốt nhất để sử dụng Prisma với Next.js](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices) để biết thêm thông tin.
+
+
+
+
+### `src/server/db`
+
+Thư mục `db` chứa Drizzle client và schema. Lưu ý rằng drizzle cũng yêu cầu file cấu hình `drizzle.config.ts` (xem bên dưới).
+
+
+
+
+#### `src/server/db/index.ts`
+
+File `index.ts` được sử dụng để khởi tạo Drizzle client ở phạm vi toàn cục. Tham khảo [Cách sử dụng Drizzle](/vi/usage/drizzle#drizzle-client) để biết thêm thông tin.
+
+
+
+
+#### `src/server/db/schema.ts`
+
+File `schema.ts` được sử dụng để định nghĩa schema cơ sở dữ liệu. Tham khảo [Cách sử dụng Drizzle](/vi/usage/drizzle#drizzle-client) và [tài liệu Drizzle schema](https://orm.drizzle.team/docs/sql-schema-declaration) để biết thêm thông tin.
+
+
+
+#### `src/server/api/routers`
+
+Thư mục `routers` chứa tất cả các sub-router tRPC của bạn.
+
+
+
+
+#### `src/server/api/routers/example.ts`
+
+File `example.ts` là một ví dụ về tRPC router sử dụng helper `publicProcedure` để minh họa cách tạo một tRPC route công khai.
+
+Tùy thuộc vào các thư viện bạn đã chọn, router này chứa nhiều hoặc ít route hơn để minh họa tốt nhất cách sử dụng phù hợp với nhu cầu của bạn.
+
+
+
+
+#### `src/server/api/trpc.ts`
+
+File `trpc.ts` là file cấu hình chính cho back-end tRPC của bạn. Tại đây chúng ta:
+
+1. Định nghĩa context được sử dụng trong các yêu cầu tRPC. Tham khảo [Cách sử dụng tRPC](/vi/usage/trpc#-serverapitrpcts) để biết thêm thông tin.
+2. Xuất các helper procedure. Tham khảo [Cách sử dụng tRPC](/vi/usage/trpc#-serverapitrpcts) để biết thêm thông tin.
+
+
+
+
+
+#### `src/server/api/root.ts`
+
+File `root.ts` được sử dụng để hợp nhất các tRPC router và xuất chúng dưới dạng một router duy nhất, cũng như định nghĩa kiểu của router. Tham khảo [Cách sử dụng tRPC](/vi/usage/trpc#-serverapirootts) để biết thêm thông tin.
+
+
+
+
+### `src/trpc`
+
+Thư mục `trpc` chứa thiết lập để cho phép bạn gọi các procedure tRPC từ server component và client component.
+
+
+
+
+#### `src/trpc/query-client.ts`
+
+File `query-client.ts` tạo ra Query Client mà tRPC sử dụng để cache và loại bỏ dữ liệu trùng lặp trong client component.
+
+
+
+
+#### `src/trpc/react.tsx`
+
+File `react.tsx` là điểm bắt đầu phía front-end cho tRPC. Nó cũng chứa các kiểu dữ liệu được định nghĩa cho input và output của router. Tham khảo [Cách sử dụng tRPC](/vi/usage/trpc) để biết thêm thông tin.
+
+
+
+
+#### `src/trpc/server.ts`
+
+File `server.ts` là điểm bắt đầu để sử dụng tRPC trong Server Component.
+
+
+
+
+### `.env`
+
+File `.env` được sử dụng để lưu trữ các biến môi trường. Tham khảo [Biến môi trường](/vi/usage/env-variables) để biết thêm thông tin. File này **không** nên được commit vào lịch sử git.
+
+
+
+
+### `.env.example`
+
+File `.env.example` hiển thị các biến môi trường ví dụ dựa trên các thư viện đã chọn. File này **nên** được commit vào lịch sử git.
+
+
+
+
+### `.eslintrc.cjs`
+
+File `.eslintrc.cjs` được sử dụng để cấu hình ESLint. Tham khảo [Tài liệu ESLint](https://eslint.org/docs/latest/user-guide/configuring/configuration-files) để biết thêm thông tin.
+
+
+
+
+### `db.sqlite (chỉ sqlite)`
+
+File `db.sqlite` chứa cơ sở dữ liệu phát triển của bạn. File này chỉ được tạo sau khi chạy lệnh `db:push` và bị bỏ qua bởi git.
+
+
+
+
+### `drizzle.config.ts`
+
+File `drizzle.config.ts` được sử dụng để cấu hình drizzle kit. Tham khảo [tài liệu](https://orm.drizzle.team/kit-docs/config-reference) để biết thêm thông tin.
+
+
+
+
+### `next-env.d.ts`
+
+File `next-env.d.ts` đảm bảo các kiểu của Next.js được trình biên dịch TypeScript nhận diện. **Bạn không nên xóa hoặc chỉnh sửa nó vì nó có thể thay đổi bất cứ lúc nào.** Tham khảo [Tài liệu Next.js](https://nextjs.org/docs/app/building-your-application/configuring/typescript) để biết thêm thông tin.
+
+
+
+
+### `next.config.mjs`
+
+File `next.config.mjs` được sử dụng để cấu hình Next.js. Tham khảo [Tài liệu Next.js](https://nextjs.org/docs/api-reference/next.config.js/introduction) để biết thêm thông tin. Lưu ý: Phần mở rộng .mjs được sử dụng để cho phép import ESM.
+
+
+
+
+### `postcss.config.js`
+
+File `postcss.config.js` được sử dụng cho việc sử dụng Tailwind PostCSS. Tham khảo [Tài liệu Tailwind PostCSS](https://tailwindcss.com/docs/installation/using-postcss) để biết thêm thông tin.
+
+
+
+
+### `prettier.config.mjs`
+
+File `prettier.config.mjs` được sử dụng để cấu hình Prettier bao gồm `prettier-plugin-tailwindcss` để định dạng các lớp Tailwind CSS. Tham khảo [bài đăng blog Tailwind CSS](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier) để biết thêm thông tin.
+
+
+
+
+### `start-database.sh (chỉ mysql hoặc postgres)`
+
+File `start-database.sh` được sử dụng để khởi động cơ sở dữ liệu. Vui lòng xem các ghi chú chúng tôi đã đề cập ở bên trong file để biết thông tin về cách khởi động cơ sở dữ liệu với hệ điều hành của bạn.
+
+
+
+
+### `tsconfig.json`
+
+File `tsconfig.json` được sử dụng để cấu hình TypeScript. Một số tùy chọn không mặc định, chẳng hạn như `strict mode`, đã được bật để đảm bảo việc sử dụng TypeScript tốt nhất cho Create T3 App và các thư viện của nó. Xem [Tài liệu TypeScript](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) hoặc [Cách sử dụng TypeScript](/vi/usage/typescript) để biết thêm thông tin.
+
+
diff --git a/www/src/pages/vi/folder-structure-pages.mdx b/www/src/pages/vi/folder-structure-pages.mdx
new file mode 100644
index 0000000000..961fc3f2dc
--- /dev/null
+++ b/www/src/pages/vi/folder-structure-pages.mdx
@@ -0,0 +1,247 @@
+---
+title: Cấu trúc thư mục (Pages Router)
+description: Cấu trúc thư mục của một ứng dụng T3 được tạo mới với Pages Router
+layout: ../../layouts/docs.astro
+lang: vi
+isMdx: true
+---
+
+import Diagram from "../../components/docs/folderStructureDiagramPages.astro";
+import Form from "../../components/docs/folderStructureForm.astro";
+
+Vui lòng chọn các thư viện được đề cập ở dưới để xem cấu trúc thư mục của một ứng dụng T3 được tạo mới với các lựa chọn đó. Ở phía dưới, bạn sẽ tìm thấy mô tả chi tiết cho mỗi file trong cây thư mục.
+
+
+
+
+
+
+
+### `prisma`
+
+Trong thư mục `prisma`, một file `schema.prisma` được sử dụng để cấu hình kết nối với cơ sở dữ liệu và định nghĩa schema cho cơ sở dữ liệu. Đây cũng là nơi lưu trữ các file migration và/hoặc seed script, nếu được sử dụng. Tham khảo [Cách sử dụng Prisma](/vi/usage/prisma) để biết thêm thông tin.
+
+
+
+
+### `public`
+
+Thư mục `public` chứa các file tĩnh (static assets) được phục vụ bởi web server. File `favicon.ico` là một ví dụ về file tĩnh.
+
+
+
+
+### `src/env`
+
+Được sử dụng để xác thực biến môi trường (environment variables) và định nghĩa kiểu cho biến môi trường (environment variables) đó - Tham khảo [Biến môi trường](/vi/usage/env-variables).
+
+
+
+
+### `src/pages`
+
+Thư mục `pages` chứa tất cả các trang của ứng dụng Next.js. File `index.tsx` ở thư mục gốc `/pages` là trang chủ và là điểm bắt đầu của ứng dụng. File `_app.tsx` được sử dụng để bao bọc ứng dụng với các provider. Tham khảo [tài liệu Next.js](https://nextjs.org/docs/basic-features/pages) để biết thêm thông tin.
+
+
+
+
+#### `src/pages/api`
+
+Thư mục `api` là nơi bạn định nghĩa các API route của ứng dụng Next.js. Tham khảo [Tài liệu Next.js Api Routes](https://nextjs.org/docs/api-routes/introduction) để biết thêm thông tin về các API route.
+
+
+
+
+#### `src/pages/api/auth/[...nextauth].ts`
+
+File `[...nextauth].ts` là một slug route của Next.js được sử dụng để xử lý các yêu cầu xác thực của NextAuth.js. Tham khảo [Cách sử dụng NextAuth.js](/vi/usage/next-auth) để biết thêm thông tin về NextAuth.js, và [Tài liệu Next.js Dynamic Routes](https://nextjs.org/docs/routing/dynamic-routes) để biết thông tin về các route catch-all/slug.
+
+
+
+
+#### `src/pages/api/trpc/[trpc].ts`
+
+File `[trpc].ts` là điểm xuất phát (entrypoint) API của tRPC. Nó được sử dụng để xử lý các yêu cầu tRPC. Tham khảo [Cách sử dụng tRPC](/vi/usage/trpc#-pagesapitrpctrpcts) để biết thêm thông tin về file này, và [Tài liệu Next.js Dynamic Routes](https://nextjs.org/docs/routing/dynamic-routes) để biết thông tin về các route catch-all/slug.
+
+
+
+
+### `src/server`
+
+Thư mục `server` được sử dụng để định nghĩa code chỉ được sử dụng và thực thi trên server.
+
+
+
+
+#### `src/server/auth.ts`
+
+Điểm bắt đầu (Entrypoint) cho logic xác thực phía server. Tại đây, chúng ta thiết lập các [tùy chọn cấu hình](usage/next-auth) NextAuth.js, thực hiện [module augmentation](usage/next-auth#inclusion-of-userid-on-the-session) cũng như cung cấp một số tiện ích DX cho việc xác thực như lấy session của người dùng ở phía server. Tham khảo [Cách sử dụng NextAuth.js](/vi/usage/next-auth#usage-with-trpc) để biết thêm thông tin.
+
+
+
+
+#### `src/server/db.ts`
+
+File `db.ts` được sử dụng để khởi tạo Prisma client ở phạm vi toàn cục (global scope). Tham khảo [Cách sử dụng Prisma](/vi/usage/prisma#prisma-client) và [các phương pháp tốt nhất để sử dụng Prisma với Next.js](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices) để biết thêm thông tin.
+
+
+
+
+### `src/server/db`
+
+Thư mục `db` chứa Drizzle client và schema. Lưu ý rằng drizzle cũng yêu cầu file cấu hình `drizzle.config.ts` (xem bên dưới).
+
+
+
+
+#### `src/server/db/index.ts`
+
+File `index.ts` được sử dụng để khởi tạo Drizzle client ở phạm vi toàn cục. Tham khảo [Cách sử dụng Drizzle](/vi/usage/drizzle#drizzle-client) để biết thêm thông tin.
+
+
+
+
+#### `src/server/db/schema.ts`
+
+File `schema.ts` được sử dụng để định nghĩa schema cơ sở dữ liệu. Tham khảo [Cách sử dụng Drizzle](/vi/usage/drizzle#drizzle-client) và [tài liệu Drizzle schema](https://orm.drizzle.team/docs/sql-schema-declaration) để biết thêm thông tin.
+
+
+
+#### `src/server/api/routers`
+
+Thư mục `routers` chứa tất cả các sub-router tRPC của bạn.
+
+
+
+
+#### `src/server/api/routers/example.ts`
+
+File `example.ts` là một ví dụ về tRPC router sử dụng helper `publicProcedure` để minh họa cách tạo một route tRPC công khai không cần xác thực.
+
+Tùy thuộc vào các thư viện bạn đã chọn, router này có thể chứa nhiều hoặc ít route hơn tùy vào cách sử dụng phù hợp với nhu cầu của bạn.
+
+
+
+
+#### `src/server/api/trpc.ts`
+
+File `trpc.ts` là file định nghĩa cấu hình chính cho back-end tRPC của bạn. Tại đây chúng ta:
+
+1. Định nghĩa context được sử dụng trong các yêu cầu tRPC. Tham khảo [Cách sử dụng tRPC](/vi/usage/trpc#-serverapitrpcts) để biết thêm thông tin.
+2. Định nghĩa các helper procedure. Tham khảo [Cách sử dụng tRPC](/vi/usage/trpc#-serverapitrpcts) để biết thêm thông tin.
+
+
+
+
+
+#### `src/server/api/root.ts`
+
+File `root.ts` được sử dụng để hợp nhất các tRPC router và đưa chúng dưới dạng một router duy nhất, cũng như được sử dụng để định nghĩa kiểu của router. Tham khảo [Cách sử dụng tRPC](/vi/usage/trpc#-serverapirootts) để biết thêm thông tin.
+
+
+
+
+### `src/styles`
+
+Thư mục `styles` chứa các style toàn cục của ứng dụng.
+
+
+
+
+### `src/utils`
+
+Thư mục `utils` được sử dụng để lưu trữ các hàm thường được tái sử dụng.
+
+
+
+
+#### `src/utils/api.ts`
+
+File `api.ts` là điểm bắt đầu phía front-end cho tRPC. Tham khảo [Cách sử dụng tRPC](/vi/usage/trpc#-utilsapits) để biết thêm thông tin.
+
+
+
+
+### `.env`
+
+File `.env` được sử dụng để lưu trữ các biến môi trường. Tham khảo [Biến môi trường](/vi/usage/env-variables) để biết thêm thông tin. File này **không** nên được commit vào lịch sử git.
+
+
+
+
+### `.env.example`
+
+File `.env.example` hiển thị các biến môi trường ví dụ dựa trên các thư viện đã chọn. File này **nên** được commit vào lịch sử git.
+
+
+
+
+### `.eslintrc.cjs`
+
+File `.eslintrc.cjs` được sử dụng để cấu hình ESLint. Tham khảo [Tài liệu ESLint](https://eslint.org/docs/latest/user-guide/configuring/configuration-files) để biết thêm thông tin.
+
+
+
+
+### `db.sqlite (chỉ sqlite)`
+
+File `db.sqlite` chứa cơ sở dữ liệu phát triển của bạn. File này chỉ được tạo sau khi chạy lệnh `db:push` và bị bỏ qua bởi git.
+
+
+
+
+### `drizzle.config.ts`
+
+File `drizzle.config.ts` được sử dụng để cấu hình drizzle kit. Tham khảo [tài liệu](https://orm.drizzle.team/kit-docs/config-reference) để biết thêm thông tin.
+
+
+
+
+### `next-env.d.ts`
+
+File `next-env.d.ts` đảm bảo các kiểu của Next.js được trình biên dịch TypeScript nhận diện. **Bạn không nên xóa hoặc chỉnh sửa nó vì nó có thể thay đổi bất cứ lúc nào.** Tham khảo [Tài liệu Next.js](https://nextjs.org/docs/basic-features/typescript#existing-projects) để biết thêm thông tin.
+
+
+
+
+### `next.config.mjs`
+
+File `next.config.mjs` được sử dụng để cấu hình Next.js. Tham khảo [Tài liệu Next.js](https://nextjs.org/docs/api-reference/next.config.js/introduction) để biết thêm thông tin. Lưu ý: Phần mở rộng .mjs được sử dụng để cho phép import ESM.
+
+
+
+
+### `postcss.config.js`
+
+File `postcss.config.js` được sử dụng cho việc sử dụng Tailwind PostCSS. Tham khảo [Tài liệu Tailwind PostCSS](https://tailwindcss.com/docs/installation/using-postcss) để biết thêm thông tin.
+
+
+
+
+### `prettier.config.mjs`
+
+File `prettier.config.mjs` được sử dụng để cấu hình Prettier bao gồm `prettier-plugin-tailwindcss` để định dạng các lớp Tailwind CSS. Tham khảo [bài đăng blog Tailwind CSS](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier) để biết thêm thông tin.
+
+
+
+
+### `start-database.sh (chỉ mysql hoặc postgres)`
+
+File `start-database.sh` được sử dụng để khởi động cơ sở dữ liệu. Vui lòng xem các ghi chú chúng tôi đã đề cập ở bên trong file để biết thông tin về cách khởi động cơ sở dữ liệu với hệ điều hành của bạn.
+
+
+
+
+### `tsconfig.json`
+
+File `tsconfig.json` được sử dụng để cấu hình TypeScript. Một số tùy chọn không mặc định, chẳng hạn như `strict mode`, đã được bật để đảm bảo việc sử dụng TypeScript tốt nhất cho Create T3 App và các thư viện của nó. Xem [Tài liệu TypeScript](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) hoặc [Cách sử dụng TypeScript](/vi/usage/typescript) để biết thêm thông tin.
+
+
diff --git a/www/src/pages/vi/installation.mdx b/www/src/pages/vi/installation.mdx
new file mode 100644
index 0000000000..c21c3b5e16
--- /dev/null
+++ b/www/src/pages/vi/installation.mdx
@@ -0,0 +1,84 @@
+---
+title: Cài đặt
+description: Hướng dẫn cài đặt Create T3 App
+layout: ../../layouts/docs.astro
+lang: vi
+isMdx: true
+---
+
+import Callout from "../../components/docs/callout.tsx";
+
+Để khởi tạo một ứng dụng sử dụng `create-t3-app`, hãy chạy bất kỳ lệnh sau đây và trả lời các câu hỏi của được đưa ra:
+
+### npm
+
+```bash
+npm create t3-app@latest
+```
+
+### yarn
+
+```bash
+yarn create t3-app
+```
+
+### pnpm
+
+```bash
+pnpm create t3-app@latest
+```
+
+### bun
+
+```bash
+bun create t3-app@latest
+```
+
+Sau khi ứng dụng của bạn đã được khởi tạo, hãy đọc [bước đầu tiên](/vi/usage/first-steps) để bắt đầu phát triển ứng dụng mới của bạn.
+
+## Sử dụng nâng cao
+
+| Tùy chọn | Mô tả |
+| ----------------- | ---------------------------------------------------------------- |
+| `[dir]` | Bao gồm đối số thư mục với tên cho dự án |
+| `--noGit` | Không khởi tạo repo git mới trong dự án |
+| `-y`, `--default` | Bỏ qua câu hỏi và khởi tạo dự án mới với tất cả tùy chọn đã chọn |
+| `--noInstall` | Tạo dự án mà không cài đặt các thư viện đi kèm |
+
+## Sử dụng với những tùy chọn thử nghiệm
+
+Đối với CI của chúng tôi, chúng tôi cung cấp một số tùy chọn thử nghiệm cho phép bạn khởi tạo bất kỳ ứng dụng nào mà không cần bất kỳ câu hỏi nào. Nếu trường hợp này áp dụng cho bạn, bạn có thể sử dụng các tùy chọn này. Xin lưu ý rằng chúng tôi đang thử nghiệm các tùy chọn này và có thể thay đổi trong tương lai mà không tuân theo phiên bản semver.
+
+| Tùy chọn | Mô tả |
+| ------------------------- | ------------------------------------------------ |
+| `--CI` | Cho phép CLI biết bạn đang ở trong môi trường CI |
+| `--trpc` | Sử dụng tRPC trong dự án |
+| `--prisma` | Sử dụng Prisma trong dự án |
+| `--drizzle` | Sử dụng Drizzle trong dự án |
+| `--nextAuth` | Sử dụng NextAuth.js trong dự án |
+| `--tailwind` | Sử dụng Tailwind CSS trong dự án |
+| `--dbProvider [provider]` | Sử dụng cơ sở dữ liệu đã cấu hình trong dự án |
+| `--appRouter` | Sử dụng Next.js App Router trong dự án |
+
+
+ Nếu tùy chọn `CI` không được sử dụng, các tùy chọn còn lại sẽ không có hiệu
+ lực.
+
+
+Bạn không nhất thiết phải loại bỏ các tùy chọn mà bạn không muốn. Tuy nhiên, nếu bạn muốn loại bỏ chúng, bạn có thể truyền `false` vào sau các tùy chọn, ví dụ: `--nextAuth false`.
+
+Tùy chọn `--dbProvider` cung cấp 4 cơ sở dữ liệu cho bạn chọn: mysql, postgres, planetscale, sqlite. Nếu tùy chọn này không được sử dụng, giá trị mặc định sẽ là sqlite.
+
+### Ví dụ
+
+Ví dụ sau sẽ tạo ra một ứng dụng T3 với tRPC và Tailwind CSS.
+
+```bash
+pnpm dlx create-t3-app@latest --CI --trpc --tailwind
+```
+
+Ví dụ sau sẽ tạo ra một ứng dụng T3 với NextAuth.js, Tailwind CSS, Drizzle, và PostgreSQL.
+
+```bash
+pnpm dlx create-t3-app@latest --CI --nextAuth --tailwind --drizzle --dbProvider postgres
+```
diff --git a/www/src/pages/vi/introduction.mdx b/www/src/pages/vi/introduction.mdx
new file mode 100644
index 0000000000..02ee650fdb
--- /dev/null
+++ b/www/src/pages/vi/introduction.mdx
@@ -0,0 +1,41 @@
+---
+title: Giới thiệu
+description: Giới thiệu về T3 Stack
+layout: ../../layouts/docs.astro
+lang: vi
+---
+
+import { IntroductionTab } from "../../components/docs/introductionTab";
+
+
+## T3 Stack
+
+_"T3 Stack"_ là một stack dùng để phát triển web được tạo bởi [Theo](https://twitter.com/t3dotgg), nó tập trung vào sự đơn giản, mô-đun hóa và đảm bảo tính toàn vẹn của kiểu dữ liệu trong lập trình full-stack.
+
+T3 Stack được xây dựng dựa trên [**Next.js**](https://nextjs.org/) và [**TypeScript**](https://typescriptlang.org/). [**Tailwind CSS**](https://tailwindcss.com/) thường được dùng để thiết kế giao diện người dùng. Và nếu bạn đang làm bất cứ điều gì liên quan đến backend, đừng lo, hãy để [**tRPC**](https://trpc.io/), [**Prisma**](https://prisma.io/), và [**NextAuth.js**](https://next-auth.js.org/) là những "món ăn" kèm theo tuyệt vời.
+
+Bạn có thể thấy rằng stack này có nhiều phần khác nhau. Cái này chính là điểm mạnh của nó. Bạn có thể thêm hoặc bớt các phần theo nhu cầu của bạn - vì stack này được thiết kế mô-đun hóa ở mức cơ sở :)
+
+## Vậy... create-t3-app là gì? Là một template sao?
+
+Bạn cũng có thể coi là như vậy? `create-t3-app` là một CLI được xây dựng bởi các nhà phát triển T3 Stack dày dạn kinh nghiệm để hợp lý hóa việc thiết lập một ứng dụng T3 Stack dạng mô-đun. Chính vì vậy, bạn có thể thêm hoặc bớt các phần theo nhu cầu của bạn, và "template" được tạo ra để đáp ứng trên nhu cầu cụ thể của bạn.
+
+Sau vô số dự án và nhiều năm làm việc với công nghệ này, chúng tôi có rất nhiều kiến thức, kinh nghiệm và trải nghiệm sâu sắc với những công nghệ này. Chính vì vậy, chúng tôi đã cố gắng hết sức để "gộp" chúng vào chiếc CLI này.
+
+Hãy lưu ý rằng, đây **KHÔNG** phải là một template bao gồm tất cả mọi thứ. Chúng tôi **khuyến khích** bạn sẽ mang các thư viện của riêng mình vào T3 Stack để giải quyết nhu cầu của ứng dụng **CỦA BẠN**. Mặc dù chúng tôi không ràng buộc các giải pháp cho các vấn đề cụ thể hơn như quản lý trạng thái và triển khai, nhưng chúng tôi [có một số khuyến nghị được liệt kê ở đây](/vi/other-recs).
+
+## Các Nguyên tắc của T3
+
+Chúng tôi sẽ thẳng thắn - đây là một dự án _có chính kiến_. Chúng tôi chia sẻ một số niềm tin cốt lõi về việc xây dựng và chúng tôi coi chúng là cơ sở cho các quyết định của mình.
+
+### Giải quyết Vấn đề
+
+Bạn có thể sẽ dễ rơi vào cái bẫy "thêm mọi thứ" - chúng tôi rõ ràng không muốn điều đó xảy ra. Vì vậy, những công nghệ được tích hợp vào trong `create-t3-app` sẽ được sử dụng để giải quyết những vấn đề hiễn hữu còn có trong những công nghệ chủ đạo. Điều này có nghĩa là chúng tôi sẽ không thêm những thứ như thư viện quản lý trạng thái (`zustand`, `redux`), thay vì đó, chúng tôi sẽ thêm những thứ như NextAuth.js và tích hợp Prisma và tRPC cho bạn.
+
+### Chuyển đổi công nghệ một cách Có Trách nhiệm (Bleed Responsibly)
+
+Chúng tôi yêu thích những công nghệ tiên tiến (bleeding edge). Vì nó nhanh và, thành thật mà nói, niềm vui đến từ những thứ mới mẻ thực sự rất tuyệt. Chúng tôi nghĩ rằng chuyển đổi công nghệ một cách có trách nhiệm (Bleed Responsibly) là một điều quan trọng, sử dụng công nghệ rủi ro hơn để bù đắp những phần ít rủi ro hơn. Và đồng thời, chúng tôi sẽ không ⛔️ tất tay vào công nghệ cơ sở dữ liệu mới đầy rủi ro (Tôi yêu SQL!). Nhưng chúng tôi rất vui vẻ ✅ "tất tay" vào tRPC vì bản chất nó chỉ là các hàm và nó cũng không mất nhiều cônng sức để chuyển đổi khỏi nó.
+
+### Đảm bảo Tính Toàn Vẹn của Kiểu dữ liệu (Typesafety) Không Phải Là Tùy Chọn
+
+Mục tiêu đã nêu của Create T3 App là cung cấp cách nhanh nhất để bắt đầu một ứng dụng web full-stack mà vẫn đảm bảo **tính toàn vẹn của kiểu dữ liệu (typesafe)** . Chúng tôi rất coi trọng việc đảm bảo tính toàn vẹn của kiểu dữ liệu vì nó cải thiện năng suất của chúng tôi và giúp chúng tôi gặp ít lỗi hơn khi phát hành. Bất kỳ quyết định nào mà không tuân thủ tính toàn vẹn của kiểu dữ liệu của Create T3 App là một quyết định nên được thực hiện trong một dự án khác.
diff --git a/www/src/pages/vi/other-recs.md b/www/src/pages/vi/other-recs.md
new file mode 100644
index 0000000000..f2f276d9a3
--- /dev/null
+++ b/www/src/pages/vi/other-recs.md
@@ -0,0 +1,169 @@
+---
+title: Các khuyến nghị khác
+description: Thư viện và dịch vụ mà chúng tôi khuyến nghị cho nhiều dự án
+layout: ../../layouts/docs.astro
+lang: vi
+---
+
+Chúng tôi nhận thấy rằng các thư viện đi kèm trong `create-t3-app` sẽ không giúp bạn giải quyết được mọi vấn đề. Mặc dù chúng tôi khuyến khích bạn bắt đầu dự án của mình với những thư viện chúng tôi cung cấp, sẽ đến một thời điểm nào đó mà bạn cần sử dụng những thư viện khác. Chỉ bạn mới biết dự án của mình cần gì, tuy nhiên, dưới đây là một số thứ mà chúng tôi thường xuyên đề xuất.
+
+Đây là những đề xuất của các cộng tác viên cá nhân của Create T3 App và không nên được xem là những đề xuất "chính thức" bởi nhóm Create T3 App hoặc T3-OSS. _**Hãy nghiên cứu kỹ lưỡng trước khi sử dụng, đặc biệt là trước khi cam kết sử dụng các dịch vụ trả phí**_.
+
+## Quản lý trạng thái (State Management)
+
+_**Lưu ý của Editor**_: Các thư viện quản lý trạng thái (State Management Libraries) có thể rất tuyệt vời, nhưng chúng thường không cần thiết. Các hook React Query của tRPC có thể đảm nhiệm tốt việc quản lý trạng thái phía máy chủ (server state) của bạn. Đối với trạng thái phía máy khách (client state), hãy bắt đầu với `useState` của React và chỉ nên sử dụng một trong các tùy chọn này khi bạn cần nhiều hơn thế.
+
+### Zustand
+
+**Bạn sẽ không bao giờ phải dùng Redux nữa**
+
+Đây được coi là một "Redux hiện đại, đơn giản" mà bạn ước mình biết đến sớm hơn. [Poimandres](https://github.com/pmndrs) rất tín. Bạn có thể xây dựng mọi thứ từ ứng dụng gọi video đến trò chơi đến máy chủ với thư viện nhỏ bé này.
+
+- [Trang chủ Zustand](https://zustand-demo.pmnd.rs/)
+- [GitHub Zustand](https://github.com/pmndrs/zustand)
+
+### Jotai
+
+**Bạn sẽ không bao giờ phải dùng Context nữa**
+
+Khi đề cập đến cách tiếp cận nguyên tử (atomic), Jotai gần như không thể bị đánh bại. Thư viện này cũng được tạo bởi [Poimandres](https://github.com/pmndrs), Jotai cho phép bạn định nghĩa các singleton giống như một useState, nhưng sử dụng một cách toàn cục. Đây sẽ là một lựa chọn tuyệt vời cho các hành vi có trạng thái (stateful behaviors) mà chưa cần đến trạng thái máy (state machine).
+
+- [Trang chủ Jotai](https://jotai.org/)
+- [GitHub Jotai](https://github.com/pmndrs/jotai)
+
+## Thư viện Component
+
+Hầu hết các ứng dụng đều cần một số component giống nhau - nút bật tắt (toggle buttons), menu thả xuống (dropdown menus), modal, v.v. Các thư viện này cung cấp các component tuyệt vời, dễ tiếp cận mà bạn có thể sử dụng và tùy chỉnh theo ý thích.
+
+### Thư viện Component không định kiểu (Unstyled)
+
+Còn được gọi là thư viện headless, chúng cung cấp một danh sách component tuyệt vời, không có style sẵn và dễ tiếp cận, giúp bạn có thể tùy chỉnh theo ý thích cá nhân. Dưới đây là một vài đề xuất của chúng tôi.
+
+- [Radix UI](https://www.radix-ui.com/) cung cấp cho bạn một bộ primitives mạnh mẽ, tiện lợi và dễ tiếp cận mà bạn có thể định nghĩa bằng CSS thuần hoặc Tailwind CSS.
+
+- [Headless UI](https://headlessui.com/) được tạo bởi Tailwind, nó cung cấp các component không có style sẵn, dễ tiếp cận và dễ tích hợp với Tailwind CSS.
+
+- [React Aria](https://react-spectrum.adobe.com/react-aria/) cung cấp các UI primitives dễ tiếp cận cho hệ thống thiết kế (design system) của bạn. Date Picker của họ là một "wow" đáng kinh ngạc.
+
+### Thư viện Component có định kiểu (Styled)
+
+**Khi ứng dụng của bạn chỉ ở mức ổn**
+
+Đôi khi bạn đang xây dựng một dự án mà bạn chỉ muốn giao diện người dùng (UI) trông tươm tất ngay từ đầu. Đối với các Bảng điều khiển quản trị (Admin Dashboards) và các dự án tương tự khác, bất kỳ thư viện component nào trong số này cũng sẽ giúp bạn hoàn thành công việc trong thời gian ngắn nhất.
+
+- [Chakra UI](https://chakra-ui.com)
+- [Mantine](https://mantine.dev)
+- [@shadcn/ui](https://ui.shadcn.com/)
+
+### Class Variance Authority
+
+**Để xây dựng thư viện UI**
+
+Để xây dựng một Thư viện UI, bạn cần cách khai báo các biến thể màu sắc, kích thước, v.v. khác nhau. Khi dự án của bạn đạt đến quy mô mà bạn muốn có một bộ component UI được chuẩn hóa với nhiều biến thể sử dụng Tailwind CSS, CVA sẽ là một "người đồng hành" không thể thiếu của bạn.
+
+- [GitHub Class Variance Authority](https://github.com/joe-bell/cva)
+
+## Hoạt ảnh (Animations)
+
+Khi bạn cần hoạt ảnh trong ứng dụng của mình, đây là những đề xuất của chúng tôi.
+
+### AutoAnimate
+
+**Tạo hoạt ảnh chỉ với một dòng code**
+
+Hầu hết các thư viện hoạt ảnh cố gắng đáp ứng mọi trường hợp sử dụng có thể và kết quả là hầu hết chúng đều rất cồng kềnh. AutoAnimate là một công cụ không cần cấu hình (zero-configuration) mà đem lại cho bạn sự cải thiện đáng kể về UX mà không cần phải nghĩ nhiều về setup.
+
+- [Trang chủ AutoAnimate](https://auto-animate.formkit.com/)
+- [GitHub AutoAnimate](https://github.com/formkit/auto-animate)
+- [Đoạn mã Component AutoAnimate](https://gist.github.com/hwkr/3fdea5d7f609b98c162e5325637cf3cb)
+
+### Framer Motion
+
+**Tạo hoạt ảnh phức tạp với code khai báo đơn giản**
+
+Framer Motion cung cấp các cú pháp khai báo đơn giản và cho phép bạn viết ít code hơn để tạo ra mọi thứ từ hoạt ảnh phức tạp đến cả cử chỉ (gestures).
+
+- [Trang chủ Framer Motion](https://framer.com/motion)
+- [Tài liệu Framer Motion](https://www.framer.com/docs/)
+
+## Triển khai, Hạ tầng, Cơ sở dữ liệu và CI
+
+### Vercel
+
+**Host ứng dụng của bạn một cách đơn giản nhất**
+
+Vercel đã "vực dậy" việc triển khai web từ địa ngục đến việc chỉ cần thêm vào Github và "deploy". Chúng tôi đã mở rộng quy mô lên hàng trăm nghìn người dùng mà không gặp vấn đề gì. Được xây dựng trên nền của AWS, tuy nhiên giao diện của Vercel lại tốt hơn chục nghìn lần :)
+
+- [Trang chủ Vercel](https://vercel.com/)
+- [Hướng dẫn triển khai Create T3 App trên Vercel](/vi/deployment/vercel)
+
+### PlanetScale
+
+**Chiếc cơ sở dữ liệu mà bạn không cần lo lắng**
+
+PlanetScale là "nền tảng cơ sở dữ liệu serverless" tốt nhất mà chúng tôi từng sử dụng. Nó có khả năng mở rộng đáng kinh ngạc, trải nghiệm lập trình tuyệt vời và giá cả phải chăng. Nếu bạn đang sử dụng SQL (và hy vọng là Prisma), thì bạn khó có thể không sử dụng nền tảng này.
+
+- [Trang chủ PlanetScale](https://planetscale.com/)
+
+### Railway
+
+**Host hạ tầng của bạn**
+
+Được coi là một "Heroku hiện đại". Đây là cách dễ nhất để bạn khởi chạy và quản lý hạ tầng đám mây của bạn. Nếu Vercel và PlanetScale không đủ đối với bạn, Railway sẽ lấp đầy khoảng trống đó. Chỉ cần đưa nó vào một repo GitHub và bắt đầu hành trình của bạn.
+
+- [Trang chủ Railway](https://railway.app/)
+
+### Upstash
+
+**Một Redis serverless**
+
+Chúng tôi yêu thích Prisma và PlanetScale, nhưng một số dự án cần đòi hỏi giải pháp hiệu năng cao hơn. Upstash đẹm lại các tính năng của Redis trong dự án serverless của bạn mà không cần phải tự quản lý cơ sở hạ tầng và việc mở rộng quy mô.
+
+- [Trang chủ Upstash](https://upstash.com/)
+
+### Pusher
+
+**WebSockets serverless**
+
+Nếu WebSockets là trọng tâm chính của dự án của bạn, bạn có thể muốn xem xét sử dụng một backend server truyền thống như [Fastify](https://www.fastify.io/) (cũng [hoạt động với tRPC!](https://trpc.io/docs/v10/fastify)). Nhưng nếu bạn không đủ thời gian để thêm WebSockets vào một ứng dụng T3, đừng lo, Pusher sẽ là "món chính" tuyệt vời.
+
+- [Trang chủ Pusher](https://pusher.com/)
+
+### Soketi
+
+Soketi là một giải pháp tự host (self-hostable), đơn giản và nhanh chóng cho Pusher. Nó hoàn toàn tương thích với Pusher SDK mà bạn có thể sử dụng để kết nối với máy chủ. Hãy nhớ rằng, Soketi serverless hiện tại đang trong giai đoạn beta.
+
+- [Trang chủ Soketi](https://soketi.app)
+- [GitHub Soketi](https://github.com/soketi/soketi)
+
+## Phân tích (Analytics)
+
+Dữ liệu người dùng rất có giá trị khi bạn xây dựng một ứng dụng. Dưới đây là một số nhà cung cấp dịch vụ phân tích mà chúng tôi đề xuất.
+
+### PostHog
+
+PostHog là một giải pháp mã nguồn mở, đầy đủ tính năng và có thể tự host để mang lại phân tích chuyên sâu cho sản phẩm của bạn. Họ có SDK cho mọi thư viện/framework có thể tưởng tượng được.
+
+- [Trang chủ PostHog](https://posthog.com/)
+
+### Plausible
+
+Bạn đang cần một nền tảng phân tích ưu việt? Plausible là một trong những cách nhanh nhất để có được chúng. Siêu tối giản. Nó thậm chí còn có hẳn cả [plugin đơn giản cho Next.js](https://plausible.io/docs/proxy/guides/nextjs).
+
+- [Trang chủ Plausible](https://plausible.io/)
+
+### Umami
+
+Umami là một giải pháp thay thế mã nguồn mở, có thể tự host, đơn giản, nhanh chóng và tập trung vào quyền riêng tư cho Google Analytics. Bạn có thể triển khai nó rất dễ dàng lên Vercel, Railway, v.v. với PlanetScale làm cơ sở dữ liệu hoặc bạn cũng có thể sử dụng phiên bản đám mây của nó.
+
+- [Trang chủ Umami](https://umami.is/)
+- [GitHub Umami](https://github.com/umami-software/umami)
+- [Umami Cloud](https://cloud.umami.is/)
+
+## Khác
+
+### Next Bundle Analyzer
+
+Đôi khi có thể khó xác định những gì sẽ được bao gồm trong khi build (build output) ứng dụng của bạn. Next Bundle Analyzer là một cách dễ dàng để trực quan hóa và phân tích các gói JavaScript (JavaScript bundles) được tạo ra trong quá trình build sản phẩm của bạn.
+
+- [@next/bundle-analyzer trên npm](https://www.npmjs.com/package/@next/bundle-analyzer)
diff --git a/www/src/pages/vi/t3-collection.mdx b/www/src/pages/vi/t3-collection.mdx
new file mode 100644
index 0000000000..095b287069
--- /dev/null
+++ b/www/src/pages/vi/t3-collection.mdx
@@ -0,0 +1,29 @@
+---
+title: T3 Collection
+description: Dự án và công ty sử dụng T3 Stack
+layout: ../../layouts/docs.astro
+lang: vi
+isMdx: true
+---
+
+import Callout from "../../components/docs/callout.tsx";
+import CompanyList from "../../components/docs/companyList.tsx";
+import OpenSourceAppList from "../../components/docs/openSourceAppList.tsx";
+
+Bạn đã có sẵn một dự án sử dụng T3 Stack và muốn chia sẻ nó? Hãy chia sẻ nó bằng cách thêm nó vào danh sách!
+
+## Dự án mã nguồn mở được tạo bằng T3 Stack
+
+
+
+## Công ty sử dụng T3 Stack
+
+Chúng tôi rất muốn biết các công ty sử dụng T3 Stack cho ứng dụng của họ. Nếu công ty của bạn đang sử dụng T3 Stack và bạn muốn chia sẻ nó? Đừng ngần ngại đưa nó vào danh sách!
+
+
+
+
+ Bạn có một dự án thú vị sử dụng T3 Stack? Hãy tạo một [pull
+ request](https://github.com/t3-oss/create-t3-app/tree/next/www/src/components/docs/openSourceAppList.tsx)
+ và thêm nó vào danh sách!
+
diff --git a/www/src/pages/vi/usage/_next-auth-app-router.mdx b/www/src/pages/vi/usage/_next-auth-app-router.mdx
new file mode 100644
index 0000000000..4b51fe17a3
--- /dev/null
+++ b/www/src/pages/vi/usage/_next-auth-app-router.mdx
@@ -0,0 +1,210 @@
+import Callout from "../../../components/docs/callout.tsx";
+import Tabs from "../../../components/docs/tabs.astro";
+
+
+ Phiên bản mới nhất của NextAuth đã chuyển sang [Auth.js](https://authjs.dev/)
+
+
+## Lấy dữ liệu phiên từ phía server
+
+Đôi khi bạn có thể muốn lấy dữ liệu phiên trên server. Để làm điều đó, sử dụng hàm trợ giúp `auth` mà `create-t3-app` cung cấp.
+
+```tsx:app/page.tsx
+import { auth } from "~/server/auth";
+
+export default async function Home() {
+ const session = await auth();
+ ...
+}
+```
+
+## Thêm `user.id` vào phiên
+
+Create T3 App đã thiết lập sẵn [session callback](https://authjs.dev/guides/extending-the-session) trong cấu hình NextAuth.js để bao gồm ID của người dùng trong đối tượng `session`.
+
+```ts:server/auth/config.ts
+callbacks: {
+ session: ({ session, user }) => ({
+ ...session,
+ user: {
+ ...session.user,
+ id: user.id,
+ },
+ }),
+ },
+```
+
+Và đông thời `user.id` cũng đã được khai báo thông qua một file định kiểu để đảm bảo rằng `user.id` được định kiểu rõ ràng khi truy cập vào đối tượng `session`. Đọc thêm về [`Module Augmentation`](https://next-auth.js.org/getting-started/typescript#module-augmentation) trên tài liệu của NextAuth.js.
+
+```ts:server/auth/config.ts
+import { DefaultSession } from "next-auth";
+
+declare module "next-auth" {
+ interface Session extends DefaultSession {
+ user: {
+ id: string;
+ } & DefaultSession["user"];
+ }
+```
+
+Bước này có thể áp dụng để thêm bất kỳ dữ liệu nào khác vào đối tượng `session`, chẳng hạn như trường `role`, nhưng **không nên được sử dụng để lưu trữ dữ liệu nhạy cảm trên client**.
+
+## Usage with tRPC
+
+Khi sử dụng NextAuth.js với tRPC, bạn có thể tạo và tái sử dụng các procedures được bảo vệ kỹ càng bằng cách sử dụng [middleware](https://trpc.io/docs/v10/middlewares). Điều này cho phép bạn tạo ra các procedure mà chỉ có thể được dùng bởi người dùng đã đăng nhập. `create-t3-app` đã thiết lập tất cả điều này cho bạn, cho phép bạn dễ dàng truy cập vào đối tượng phiên (session object) trong các procedures được bảo vệ.
+
+Điều này có thể được thực hiện qua hai bước:
+
+1. Thêm phiên xác thực vào context của tRPC:
+
+```ts:server/api/trpc.ts
+import { auth } from "~/server/auth";
+import { db } from "~/server/db";
+
+export const createTRPCContext = async (opts: { headers: Headers }) => {
+ const session = await auth();
+
+ return {
+ db,
+ session,
+ ...opts,
+ };
+};
+```
+
+2. Tạo một tRPC middleware kiểm tra xem người dùng có được xác thực hay không. Sau đó, sử dụng middleware này trong `protectedProcedure`. Bất kỳ caller nào gọi đến các procedure này phải được xác thực, nếu không caller đó sẽ bị báo lỗi mà client có thể dùng để xử lý (ví dụ: hiển thị một trang đăng nhập).
+
+```ts:server/api/trpc.ts
+export const protectedProcedure = t.procedure
+ .use(({ ctx, next }) => {
+ if (!ctx.session?.user) {
+ throw new TRPCError({ code: "UNAUTHORIZED" });
+ }
+ return next({
+ ctx: {
+ session: { ...ctx.session, user: ctx.session.user },
+ },
+ });
+ });
+```
+
+Dữ liệu phiên ở đây là một sự biểu diễn tối giản và gọn nhẹ của người dùng và chỉ chứa một số trường. Khi sử dụng `protectedProcedures`, bạn có thể truy cập để lấy ID của người dùng để đạt được nhiều mục đích khác nhau, ví dụ như sử dụng ID để lấy thêm dữ liệu từ cơ sở dữ liệu.
+
+```ts:server/api/routers/user.ts
+const userRouter = router({
+ me: protectedProcedure.query(async ({ ctx }) => {
+ const user = await prisma.user.findUnique({
+ where: {
+ id: ctx.session.user.id,
+ },
+ });
+ return user;
+ }),
+});
+```
+
+## Sử dụng với các Database Providers
+
+
+
+ Để NextAuth.js có thể hoạt động với Prisma, bạn cần phải chuẩn bị khá nhiều
+ thủ tục [thiết lập ban đầu](https://authjs.dev/reference/adapter/prisma/).
+ Tuy nhiên, `create-t3-app` đã làm tất cả những điều này cho bạn. Nếu bạn
+ chọn cả Prisma và NextAuth.js khi khởi tạo dự án, bạn sẽ có ngay một hệ
+ thống xác thực hoàn chỉnh với tất cả các model cần thiết đã được cấu hình
+ sẵn. Ứng dụng mẫu mà chúng tôi cung cấp sẽ được cấu hình sẵn với nhà cung
+ cấp Discord OAuth, vì đây là một trong những provider dễ bắt đầu nhất – bạn
+ chỉ cần thêm các token vào file `.env` là có thể sử dụng ngay. Tuy nhiên,
+ bạn cũng có thể dễ dàng thêm các provider khác bằng cách làm theo [tài liệu
+ của NextAuth.js](https://next-auth.js.org/providers/). Lưu ý rằng một số
+ provider sẽ yêu cầu bạn thêm các trường bổ sung vào một số model nhất định.
+ Chúng tôi khuyến nghị bạn nên đọc kỹ tài liệu của provider mà bạn muốn sử
+ dụng để đảm bảo rằng bạn đã thêm đầy đủ các trường cần thiết.
+
+
+ Để NextAuth.js có thể hoạt động với Drizzle, bạn cần phải chuẩn bị khá nhiều
+ thủ tục [thiết lập ban
+ đầu](https://authjs.dev/getting-started/adapters/drizzle). Tuy nhiên,
+ `create-t3-app` đã làm tất cả những điều này cho bạn. Nếu bạn chọn cả
+ Drizzle và NextAuth.js khi khởi tạo dự án, bạn sẽ có ngay một hệ thống xác
+ thực hoàn chỉnh với tất cả các model cần thiết đã được cấu hình sẵn. Ứng
+ dụng mẫu mà chúng tôi cung cấp sẽ được cấu hình sẵn với nhà cung cấp Discord
+ OAuth, vì đây là một trong những provider dễ bắt đầu nhất – bạn chỉ cần thêm
+ các token vào file `.env` là có thể sử dụng ngay. Tuy nhiên, bạn cũng có thể
+ dễ dàng thêm các provider khác bằng cách làm theo [tài liệu của
+ Auth.js](https://authjs.dev/getting-started/authentication/oauth). Lưu ý
+ rằng một số provider sẽ yêu cầu bạn thêm các trường bổ sung vào một số model
+ nhất định. Chúng tôi khuyến nghị bạn nên đọc kỹ tài liệu của provider mà bạn
+ muốn sử dụng để đảm bảo rằng bạn đã thêm đầy đủ các trường cần thiết.
+
+
+
+### Thêm các trường mới vào model của bạn
+
+Khi thêm các trường mới vào bất kỳ model nào trong số `User`, `Account`, `Session`, or `VerificationToken` (đa số bạn chỉ cần sửa đổi model `User`), bạn cần lưu ý rằng [Prisma adapter](https://next-auth.js.org/adapters/prisma) tự động tạo các trường trên các model này khi người dùng mới đăng ký và đăng nhập. Do đó, khi thêm các trường mới vào các model này, bạn phải cung cấp giá trị mặc định cho chúng, vì adapter sẽ không thể nhận ra các trường này.
+
+Nếu bạn muốn thêm một trường `role` vào model `User`, bạn cần cung cấp một giá trị mặc định cho trường `role`. Điều này được thực hiện bằng cách thêm `@default` vào trường `role` trong model `User`:
+
+```diff:prisma/schema.prisma
++ enum Role {
++ USER
++ ADMIN
++ }
+
+ model User {
+ ...
++ role Role @default(USER)
+ }
+```
+
+## Sử dụng với Next.js middleware
+
+Với Next.js 12+, cách dễ nhất để bảo vệ các trang trong ứng dụng của bạn là sử dụng [middleware file](https://authjs.dev/getting-started/session-management/protecting?framework=express#nextjs-middleware). Bạn có thể tạo một file middleware.ts trong thư mục root của pages (hoặc app nếu bạn dùng App Router) với nội dung sau:
+
+```middleware.ts
+export { auth as middleware } from "@/auth"
+```
+
+Sau đó, định nghĩa các callback bảo vệ trong file auth.ts của bạn. Để biết thêm chi tiết, hãy xem [tài liệu tham khảo](https://authjs.dev/reference/nextjs#authorized).
+
+```app/auth.ts
+async authorized({ request, auth }) {
+ const url = request.nextUrl
+
+ if(request.method === "POST") {
+ const { authToken } = (await request.json()) ?? {}
+ // Nếu yêu cầu có một token xác thực hợp lệ, nó được xác thực
+ const valid = await validateAuthToken(authToken)
+ if(valid) return true
+ return NextResponse.json("Invalid auth token", { status: 401 })
+ }
+
+ // Chỉ các người dùng đã đăng nhập mới được quyền vào, nếu không hãy chuyển hướng đến trang đăng nhập
+ return !!auth.user
+}
+```
+
+
+ Bạn không nên chỉ dựa vào middleware để kiểm soát quyền truy cập. Hãy luôn đảm
+ bảo rằng phiên đăng nhập (session) được xác thực càng gần với nơi lấy dữ liệu
+ càng tốt.
+
+
+## Thiết lập Discord Provider mặc định
+
+1. Đi đến [phần Applications trong Discord Developer Portal](https://discord.com/developers/applications), và click vào "New Application"
+2. Trong menu settings, đi đến "OAuth2 => General"
+
+- Copy Client ID và dán nó vào `DISCORD_CLIENT_ID` trong `.env`.
+- Dưới Client Secret, click "Reset Secret" và copy chuỗi đó vào `DISCORD_CLIENT_SECRET` trong `.env`. Cẩn thận vì bạn sẽ không thể nhìn thấy chuỗi này lại nữa, và đặt lại nó sẽ làm cho chuỗi hiện tại hết hạn.
+- Click "Add Redirect" và dán vào `/api/auth/callback/discord` (ví dụ cho phát triển local: http://localhost:3000/api/auth/callback/discord)
+- Lưu thay đổi của bạn
+- Có thể, nhưng không được khuyến nghị, là sử dụng cùng một ứng dụng Discord cho cả phát triển và sản phẩm. Bạn cũng có thể xem xét [Mocking the Provider](https://github.com/trpc/trpc/blob/main/examples/next-prisma-websockets-starter/src/pages/api/auth/%5B...nextauth%5D.ts) trong quá trình phát triển.
+
+## Tài liệu hữu ích
+
+| Tài liệu | Đường dẫn |
+| ------------------------------------ | --------------------------------------- |
+| Tài liệu NextAuth.js | https://authjs.dev/ |
+| GitHub của NextAuth.js | https://github.com/nextauthjs/next-auth |
+| tRPC Kitchen Sink - sử dụng NextAuth | https://kitchen-sink.trpc.io/next-auth |
diff --git a/www/src/pages/vi/usage/_next-auth-pages.mdx b/www/src/pages/vi/usage/_next-auth-pages.mdx
new file mode 100644
index 0000000000..f804750822
--- /dev/null
+++ b/www/src/pages/vi/usage/_next-auth-pages.mdx
@@ -0,0 +1,216 @@
+import Callout from "../../../components/docs/callout.tsx";
+
+## Context Provider
+
+Trong điểm bắt đầu (entrypoint) của ứng dụng của bạn, bạn sẽ thấy rằng toàn bộ ứng dụng của bạn được bọc bởi một lớp [SessionProvider](https://next-auth.js.org/getting-started/client#sessionprovider):
+
+```tsx:pages/_app.tsx
+
+
+
+```
+
+Lớp context provider này cho phép ứng dụng của bạn truy cập dữ liệu phiên (session) từ bất cứ đâu trong ứng dụng của bạn, mà không cần phải truyền nó xuống như là props:
+
+```tsx:pages/users/[id].tsx
+import { useSession } from "next-auth/react";
+
+const User = () => {
+ const { data: session } = useSession();
+
+ if (!session) {
+ // Xử lý khi không có phiên hợp lí, ví dụ: hiển thị một component SignIn
+ return ;
+ }
+
+ return
Welcome {session.user.name}!
;
+};
+```
+
+## Lấy dữ liệu phiên ở phía server
+
+Đôi khi bạn có thể muốn lấy dữ liệu phiên đăng nhập ở phía server. Để làm điều đó, hãy sử dụng hàm `getServerAuthSession` mà `create-t3-app` cung cấp, và truyền nó xuống cho client sử dụng thông qua `getServerSideProps`:
+
+```tsx:pages/users/[id].tsx
+import { getServerAuthSession } from "../server/auth";
+import { type GetServerSideProps } from "next";
+
+export const getServerSideProps: GetServerSideProps = async (ctx) => {
+ const session = await getServerAuthSession(ctx);
+ return {
+ props: { session },
+ };
+};
+
+const User = () => {
+ const { data: session } = useSession();
+ // NOTE: `session` sẽ không có trạng thái loading vì nó đã được lấy trước ở phía server
+
+ ...
+}
+```
+
+## Thêm `user.id` vào trong phiên
+
+Create T3 App đã thiết lập sẵn [session callback](https://next-auth.js.org/configuration/callbacks#session-callback) trong cấu hình NextAuth.js để bao gồm luôn ID của người dùng trong đối tượng `session`.
+
+```ts:server/auth.ts
+callbacks: {
+ session({ session, user }) {
+ if (session.user) {
+ session.user.id = user.id;
+ }
+ return session;
+ },
+ },
+```
+
+Và đông thời `user.id` cũng đã được khai báo thông qua một file định kiểu để đảm bảo rằng `user.id` được định kiểu rõ ràng khi truy cập vào đối tượng `session`. Đọc thêm về [`Module Augmentation`](https://next-auth.js.org/getting-started/typescript#module-augmentation) trên tài liệu của NextAuth.js.
+
+```ts:server/auth.ts
+import { DefaultSession } from "next-auth";
+
+declare module "next-auth" {
+ interface Session {
+ user?: {
+ id: string;
+ } & DefaultSession["user"];
+ }
+}
+```
+
+Bước này có thể áp dụng để thêm bất kỳ dữ liệu nào khác vào đối tượng `session`, chẳng hạn như trường `role`, nhưng **không nên được sử dụng để lưu trữ dữ liệu nhạy cảm trên client**.
+
+## Sử dụng với tRPC
+
+Khi sử dụng NextAuth.js với tRPC, bạn có thể tạo và tái sử dụng các procedures được bảo vệ kỹ càng bằng cách sử dụng [middleware](https://trpc.io/docs/v10/middlewares). Điều này cho phép bạn tạo ra các procedure mà chỉ có thể được dùng bởi người dùng đã đăng nhập. `create-t3-app` đã thiết lập tất cả điều này cho bạn, cho phép bạn dễ dàng truy cập vào đối tượng phiên (session object) trong các procedures được bảo vệ.
+
+Điều này có thể được thực hiện qua hai bước:
+
+1. Lấy session từ request headers thông qua hàm [`getServerSession`](https://next-auth.js.org/configuration/nextjs#getServerSession). Lợi thế của việc sử dụng `getServerSession` thay vì `getSession` là nó là một hàm chỉ thực thi ở phía server và không gây ra các cuộc gọi fetch không cần thiết. `create-t3-app` tạo ra một hàm trợ giúp để tóm tắt API này, để bạn không cần phải nhập cả hai tùy chọn NextAuth.js cũng như hàm `getServerSession` mỗi khi cần truy cập vào phiên.
+
+```ts:server/auth.ts
+export const getServerAuthSession = (ctx: {
+ req: GetServerSidePropsContext["req"];
+ res: GetServerSidePropsContext["res"];
+}) => {
+ return getServerSession(ctx.req, ctx.res, authOptions);
+};
+```
+
+Bằng cách sử dụng hàm trợ giúp này, chúng ta có thể lấy phiên và truyền nó vào context của tRPC:
+
+```ts:server/api/trpc.ts
+import { getServerAuthSession } from "../auth";
+
+export const createContext = async (opts: CreateNextContextOptions) => {
+ const { req, res } = opts;
+ const session = await getServerAuthSession({ req, res });
+ return await createContextInner({
+ session,
+ });
+};
+```
+
+2. Tạo một tRPC middleware để kiểm tra xem người dùng có được xác thực hay không. Sau đó, chúng ta sử dụng middleware này trong một `protectedProcedure`. Bất kỳ caller nào gọi đến các procedure này phải được xác thực, nếu không caller đó sẽ bị báo lỗi mà client có thể dùng để xử lý (ví dụ: hiển thị một trang đăng nhập).
+
+```ts:server/api/trpc.ts
+export const protectedProcedure = t.procedure.use(({ ctx, next }) => {
+ if (!ctx.session?.user) {
+ throw new TRPCError({ code: "UNAUTHORIZED" });
+ }
+ return next({
+ ctx: {
+ // Session phải được đảm bảo là không null
+ session: { ...ctx.session, user: ctx.session.user },
+ },
+ });
+})
+```
+
+Dữ liệu phiên ở đây là một sự biểu diễn tối giản và gọn nhẹ của người dùng và chỉ chứa một số trường. Khi sử dụng `protectedProcedures`, bạn có thể truy cập để lấy ID của người dùng để đạt được nhiều mục đích khác nhau, ví dụ như sử dụng ID để lấy thêm dữ liệu từ cơ sở dữ liệu.
+
+```ts:server/api/routers/user.ts
+const userRouter = router({
+ me: protectedProcedure.query(async ({ ctx }) => {
+ const user = await prisma.user.findUnique({
+ where: {
+ id: ctx.session.user.id,
+ },
+ });
+ return user;
+ }),
+});
+```
+
+## Sử dụng với Prisma
+
+Để NextAuth.js có thể hoạt động với Prisma, bạn cần phải chuẩn bị khá nhiều thủ tục [thiết lập ban đầu](https://authjs.dev/reference/adapter/prisma/). Tuy nhiên, `create-t3-app` đã làm tất cả những điều này cho bạn. Nếu bạn chọn cả Prisma và NextAuth.js khi khởi tạo dự án, bạn sẽ có ngay một hệ thống xác thực hoàn chỉnh với tất cả các model cần thiết đã được cấu hình sẵn. Ứng dụng mẫu mà chúng tôi cung cấp sẽ được cấu hình sẵn với nhà cung cấp Discord OAuth, vì đây là một trong những provider dễ bắt đầu nhất – bạn chỉ cần thêm các token vào file `.env` là có thể sử dụng ngay. Tuy nhiên, bạn cũng có thể dễ dàng thêm các provider khác bằng cách làm theo [tài liệu của NextAuth.js](https://next-auth.js.org/providers/). Lưu ý rằng một số provider sẽ yêu cầu bạn thêm các trường bổ sung vào một số model nhất định. Chúng tôi khuyến nghị bạn nên đọc kỹ tài liệu của provider mà bạn muốn sử dụng để đảm bảo rằng bạn đã thêm đầy đủ các trường cần thiết.
+
+### Thêm các trường mới vào model của bạn
+
+Khi thêm các trường mới vào bất kỳ model nào trong số `User`, `Account`, `Session`, or `VerificationToken` (đa số bạn chỉ cần sửa đổi model `User`), bạn cần lưu ý rằng [Prisma adapter](https://next-auth.js.org/adapters/prisma) tự động tạo các trường trên các model này khi người dùng mới đăng ký và đăng nhập. Do đó, khi thêm các trường mới vào các model này, bạn phải cung cấp giá trị mặc định cho chúng, vì adapter sẽ không thể nhận ra các trường này.
+
+Nếu bạn muốn thêm một trường `role` vào model `User`, bạn cần cung cấp một giá trị mặc định cho trường `role`. Điều này được thực hiện bằng cách thêm `@default` vào trường `role` trong model `User`:
+
+```diff:prisma/schema.prisma
++ enum Role {
++ USER
++ ADMIN
++ }
+
+ model User {
+ ...
++ role Role @default(USER)
+ }
+```
+
+## Sử dụng với Next.js middleware
+
+Để sử dụng NextAuth.js với Next.js middleware, bạn cần sử dụng [xác thực phiên bằng JWT](https://next-auth.js.org/configuration/nextjs#caveats) cho xác thực. Điều này là do middleware chỉ có thể truy cập cookie phiên nếu nó là JWT. Theo mặc định, Create T3 App được cấu hình để sử dụng chiến lược **default**, kết hợp với Prisma làm adapter lưu trữ phiên trong cơ sở dữ liệu.
+
+
+ Lưu trữ phiên bằng cơ sở dữ liệu là cách tiếp cận được khuyến nghị và bạn nên
+ đọc thêm về JWTs trước khi chuyển sang xác thực phiên bằng JWT để tránh bất kỳ
+ vấn đề bảo mật nào.
+
+
+Sau khi chuyển sang chiến lược phiên bằng JWT, hãy đảm bảo cập nhật callback `session` trong `src/server/auth.ts`. Đối tượng `user` sẽ là `undefined`. Thay vào đó, hãy lấy ID của người dùng thông qua đối tượng `token`. Ví dụ:
+
+```diff:server/auth.ts
+ export const authOptions: NextAuthOptions = {
++ session: {
++ strategy: "jwt",
++ },
+ callbacks: {
+- session: ({ session, user }) => ({
++ session: ({ session, token }) => ({
+ ...session,
+ user: {
+ ...session.user,
+- id: user.id,
++ id: token.sub,
+ },
+ }),
+ },
+ }
+```
+
+## Thiết lập Discord Provider mặc định
+
+1. Đi đến [phần Applications trong Discord Developer Portal](https://discord.com/developers/applications), và click vào "New Application"
+2. Trong menu settings, đi đến "OAuth2 => General"
+
+- Copy Client ID và dán nó vào `DISCORD_CLIENT_ID` trong `.env`.
+- Dưới Client Secret, click "Reset Secret" và copy chuỗi đó vào `DISCORD_CLIENT_SECRET` trong `.env`. Cẩn thận vì bạn sẽ không thể nhìn thấy chuỗi này lại nữa, và đặt lại nó sẽ làm cho chuỗi hiện tại hết hạn.
+- Click "Add Redirect" và dán vào `/api/auth/callback/discord` (ví dụ cho phát triển local: http://localhost:3000/api/auth/callback/discord)
+- Lưu thay đổi của bạn
+- Có thể, nhưng không được khuyến nghị, là sử dụng cùng một ứng dụng Discord cho cả phát triển và sản phẩm. Bạn cũng có thể xem xét [Mocking the Provider](https://github.com/trpc/trpc/blob/main/examples/next-prisma-websockets-starter/src/pages/api/auth/%5B...nextauth%5D.ts) trong quá trình phát triển.
+
+## Tài liệu hữu ích
+
+| Tài liệu | Đường dẫn |
+| ------------------------------------ | --------------------------------------- |
+| Tài liệu NextAuth.js | https://next-auth.js.org/ |
+| GitHub của NextAuth.js | https://github.com/nextauthjs/next-auth |
+| tRPC Kitchen Sink - sử dụng NextAuth | https://kitchen-sink.trpc.io/next-auth |
diff --git a/www/src/pages/vi/usage/drizzle.mdx b/www/src/pages/vi/usage/drizzle.mdx
new file mode 100644
index 0000000000..d7589d3383
--- /dev/null
+++ b/www/src/pages/vi/usage/drizzle.mdx
@@ -0,0 +1,84 @@
+---
+title: Drizzle
+description: Cách sử dụng Drizzle
+layout: ../../../layouts/docs.astro
+lang: vi
+isMdx: true
+---
+
+Drizzle là một Headless Typescript ORM với [các truy vấn kiểu quan hệ](https://orm.drizzle.team/docs/rqb) và [các truy vấn kiểu SQL](https://orm.drizzle.team/docs/select). Nó có thể xử lý các cập nhật cơ sở dữ liệu và các mô hình, và đồng thời cung cấp một client nơi kiểu dữ liệu có mối liên hệ chặt chẽ với cơ sở dữ liệu. Mặt khác, Drizzle cũng cho ra mắt [Drizzle-Kit](https://orm.drizzle.team/drizzle-studio/overview), một bộ công cụ không thể thiếu nhằm giúp bạn làm việc với cơ sở dữ liệu của bạn.
+
+## Drizzle Client
+
+Drizzle Client được định nghĩa ở `src/server/db/index.ts`. Trong tệp này, bạn có thể định nghĩa URL kết nối cơ sở dữ liệu của bạn và kết nối schema của bạn với cơ sở dữ liệu.
+
+```ts:src/server/db/index.ts
+import { env } from "~/env";
+import * as schema from "./schema";
+import postgres from "postgres";
+
+
+const conn = postgres(env.DATABASE_URL)
+
+export const db = drizzle(conn, { schema });
+```
+
+Chúng tôi khuyên bạn nên bao gồm client của Drizzle trong context của tRPC:
+
+```ts:src/server/api/trpc.ts
+import { db } from "~/server/db";
+
+export const createTRPCContext = async (opts: { headers: Headers }) => {
+ const session = await auth();
+
+ return {
+ db,
+ session,
+ ...opts,
+ };
+};
+```
+
+## Schema
+
+Schema của Drizzle có thể được tìm thấy ở `src/server/db/schema.ts`. Đây là nơi bạn có thể định nghĩa schema của cơ sở dữ liệu và các mô hình của bạn, và kết nối chúng với Drizzle Client.
+
+Khi bạn chọn sử dụng NextAuth.js kết hợp với Drizzle, tệp schema được tạo và thiết lập cho bạn với các giá trị được Auth.js khuyến nghị như là `User`, `Session`, `Account`, và `VerificationToken`, tìm hiểu thêm tại [tài liệu Auth.js](https://authjs.dev/getting-started/adapters/drizzle).
+
+## Drizzle Kit
+
+Drizzle Kit là một bộ công cụ dòng lệnh (CLI) được thiết kế giúp bạn quản lý cơ sở dữ liệu của bạn. T3 Stack tự động bao gồm Drizzle Kit khi bạn chọn Drizzle làm ORM của mình.
+
+```json:package.json
+"scripts": {
+ ...
+ "db:generate": "drizzle-kit generate",
+ "db:migrate": "drizzle-kit migrate",
+ "db:push": "drizzle-kit push",
+ "db:studio": "drizzle-kit studio",
+ ...
+ },
+```
+
+### Giải thích các lệnh
+
+`db:generate`
+Tạo ra các kiểu TypeScript và mô hình từ schema của cơ sở dữ liệu của bạn, đảm bảo tính toàn vẹn của kiểu dữ liệu và dễ dàng tích hợp với Drizzle ORM.
+
+`db:migrate`
+Áp dụng các cập nhật chưa được áp dụng cho cơ sở dữ liệu của bạn, giữ cho schema của bạn đồng bộ với các thay đổi và cập nhật trong dự án của bạn.
+
+`db:push`
+Đẩy các thay đổi schema cục bộ trực tiếp đến cơ sở dữ liệu mà không cần các tệp cập nhật chuyển đổi. Điều này có thể hữu ích cho việc đồng bộ hóa nhanh chóng trong quá trình phát triển.
+
+`db:studio`
+Mở một giao diện trực quan để quản lý và kiểm tra các bảng, dữ liệu và mối quan hệ của cơ sở dữ liệu của bạn.
+
+## Tài liệu hữu ích
+
+| Tài liệu | Đường dẫn |
+| ------------------------------------- | --------------------------------------------------- |
+| Tài liệu của Drizzle | https://orm.drizzle.team/docs/overview |
+| GitHub của Drizzle | https://github.com/drizzle-team/drizzle-orm |
+| Adapter Drizzle của Auth.JS | https://authjs.dev/getting-started/adapters/drizzle |
+| Hướng dẫn migrate sử dụng Drizzle Kit | https://orm.drizzle.team/docs/kit-overview |
diff --git a/www/src/pages/vi/usage/env-variables.mdx b/www/src/pages/vi/usage/env-variables.mdx
new file mode 100644
index 0000000000..4e5e8f8f01
--- /dev/null
+++ b/www/src/pages/vi/usage/env-variables.mdx
@@ -0,0 +1,148 @@
+---
+title: Biến môi trường
+description: Bắt đầu với Create T3 App
+layout: ../../../layouts/docs.astro
+lang: vi
+isMdx: true
+---
+
+import Callout from "../../../components/docs/callout.tsx";
+
+Create T3 App sử dụng một thư viện tự tạo tên là [@t3-oss/env-nextjs](https://env.t3.gg) cùng với [zod](https://zod.dev) để xác thực biến môi trường trong thời gian chạy (runtime) _và_ thời gian xây dựng (buildtime) bằng cách cung cấp một logic đơn giản trong `src/env.js`.
+
+## env.js
+
+_TLDR; Nếu bạn muốn thêm một biến môi trường mới, bạn phải thêm một validator trong `src/env.js`, và sau đó thêm chúng vào trong `.env`_
+
+```ts:env.js
+import { createEnv } from "@t3-oss/env-nextjs";
+import { z } from "zod";
+
+export const env = createEnv({
+ server: {
+ NODE_ENV: z.enum(["development", "test", "production"]),
+ },
+ client: {
+ // NEXT_PUBLIC_CLIENTVAR: z.string(),
+ },
+ runtimeEnv: {
+ NODE_ENV: process.env.NODE_ENV,
+ },
+});
+```
+
+T3 Env sử dụng hàm `createEnv` để tạo schema và xác thực cả biến môi trường cho cả client-side và server-side.
+
+
+ Để biết thêm thông tin về cách `createEnv` hoạt động bên trong, hãy tham khảo
+ tài liệu của [T3 Env](https://env.t3.gg/docs/introduction)
+
+
+## Sử dụng biến môi trường
+
+Khi bạn muốn sử dụng biến môi trường của bạn, bạn có thể nhập chúng từ tập tin đã tạo `env.js` và sử dụng chúng như bạn thường làm. Nếu bạn nhập chúng trên client và cố gắng truy cập vào một biến môi trường server-side, bạn sẽ nhận được một lỗi thời gian chạy.
+
+```ts:pages/api/hello.ts
+import { env } from "../../env.js";
+
+// `env` đảm bảo typesafe và cung cấp tự động hoàn tất
+const dbUrl = env.DATABASE_URL;
+```
+
+```ts:pages/index.tsx
+import { env } from "../env.js";
+
+// ❌ Sẽ tạo ra một lỗi thời gian chạy
+const dbUrl = env.DATABASE_URL;
+
+// ✅ Đủ wow rồi đó
+const wsKey = env.NEXT_PUBLIC_WS_KEY;
+```
+
+## .env.example
+
+Vì tập tin `.env` mặc định không được commit vào version control, chúng tôi cũng đã bao gồm một tập tin `.env.example`, trong đó bạn có thể tùy chọn giữ một bản sao của tập tin `.env` của bạn mà không để lộ bất kì thông tin nào bí mật. Điều này không bắt buộc, nhưng chúng tôi khuyên bạn nên giữ file này để dễ dàng hơn cho người đóng góp bắt đầu với môi trường của họ.
+
+Một số framework và công cụ build, như Next.js, khuyên bạn nên lưu trữ bí mật trong tập tin `.env.local` và commit tập tin `.env` vào project. Chúng tôi không khuyến khích điều này, vì nó có thể làm cho việc commit bí mật vào project trở nên dễ dàng hơn. Thay vào đó, chúng tôi khuyên bạn nên lưu trữ bí mật trong `.env`, giữ tập tin `.env` của bạn trong `.gitignore` và chỉ commit tập tin `.env.example` vào project.
+
+## Thêm biến môi trường
+
+Để đảm bảo rằng quá trình build của bạn không thể hoành thành nếu không có các biến môi trường mà project cần, bạn sẽ cần thêm biến môi trường mới vào **hai** vị trí:
+
+📄 `.env`: Nhập biến môi trường của bạn như bạn dưới dạng `KEY=VALUE` trong tập tin `.env`
+
+📄 `env.js`: Thêm logic xác thực thích hợp cho các biến môi trường bằng cách định nghĩa một schema Zod bên trong `createEnv` cho mỗi biến, ví dụ: `KEY: z.string()`. Ngoài ra, hãy đảm bảo rằng bạn thêm chúng trong tùy chọn `runtimeEnv`, ví dụ: `KEY: process.env.KEY`
+
+
+ Tại sao tôi cần phân thêm biến môi trường trong `runtimeEnv`? Điều này là do
+ cách Next.js đóng gói biến môi trường trong các runtime nhất định. Bằng cách
+ này, bạn đảm bảo rằng biến sẽ không bao giờ bị loại bỏ khỏi bundle.
+
+
+Tùy chọn, bạn cũng có thể giữ tập tin `.env.example` cập nhật:
+
+📄 `.env.example`: Nhập biến môi trường của bạn, nhưng hãy đảm bảo rằng bạn không bao gồm giá trị nếu nó là bí mật, tức là `KEY=VALUE` hoặc `KEY=`
+
+### Ví dụ
+
+_Tôi muốn thêm biến môi trường của Twitter API vào biến môi trường server-side_
+
+1. Thêm biến môi trường vào `.env`:
+
+```
+TWITTER_API_TOKEN=1234567890
+```
+
+2. Thêm biến môi trường vào `env.js`:
+
+```ts
+import { createEnv } from "@t3-oss/env-nextjs";
+import { z } from "zod";
+
+export const env = createEnv({
+ server: {
+ TWITTER_API_TOKEN: z.string(),
+ },
+ // ...
+ runtimeEnv: {
+ // ...
+ TWITTER_API_TOKEN: process.env.TWITTER_API_TOKEN,
+ },
+});
+```
+
+3. _Tùy chọn:_ Thêm biến môi trường vào `.env.example` và đảm bảo rằng bạn không bao gồm giá trị bí mật trong tùy chọn `runtimeEnv`
+
+```bash
+TWITTER_API_TOKEN=
+```
+
+## Ép kiểu biến
+
+Tất cả các biến môi trường bạn thêm vào `.env` sẽ được nhập dưới dạng chuỗi, ngay cả khi giá trị của chúng được dự định đại diện cho một kiểu khác. Nếu bạn muốn sử dụng biến môi trường của bạn dưới dạng kiểu khác tại thời gian chạy, bạn có thể sử dụng `zod.coerce` để chuyển đổi chuỗi thành kiểu bạn muốn. Nó sẽ báo lỗi nếu ép kiểu không thành công.
+
+Thêm biến môi trường vào `.env`:
+
+```
+SOME_NUMBER=123
+SOME_BOOLEAN=true
+```
+
+Sau đó, xác thực chúng trong `env.js`:
+
+```ts
+import { createEnv } from "@t3-oss/env-nextjs";
+import { z } from "zod";
+
+export const env = createEnv({
+ server: {
+ SOME_NUMBER: z.coerce.number(),
+ SOME_BOOLEAN: z.coerce.boolean(),
+ },
+ // ...
+ runtimeEnv: {
+ SOME_NUMBER: process.env.SOME_NUMBER,
+ SOME_BOOLEAN: process.env.SOME_BOOLEAN,
+ },
+});
+```
diff --git a/www/src/pages/vi/usage/first-steps.md b/www/src/pages/vi/usage/first-steps.md
new file mode 100644
index 0000000000..67f47ada3d
--- /dev/null
+++ b/www/src/pages/vi/usage/first-steps.md
@@ -0,0 +1,53 @@
+---
+title: Bước đầu tiên
+description: Bắt đầu với T3 App của bạn
+layout: ../../../layouts/docs.astro
+lang: vi
+---
+
+Vậy là bạn đã khởi tạo thành công chiếc T3 App cho mình rồi đấy. Bây giờ là lúc để bạn có thể bắt đầu làm việc với nó.
+
+## Cơ sở dữ liệu
+
+### MySQL, PostgreSQL
+
+Nếu bạn chọn MySQL hoặc PostgreSQL làm cơ sở dữ liệu của mình, T3 App sẽ có một file `start-database.sh` viết bằng bash script mà có thể tạo một container dựa trên cơ sở dữ liệu đã chọn nhằm cho phép bạn phát triển cục bộ. Nếu bạn đã có một cơ sở dữ liệu, hãy cứ thoát khỏi file này và đặt chuỗi kết nối cơ sở dữ liệu của bạn vào `.env`. Trên macOS, bạn cũng có thể sử dụng [DBngin](https://dbngin.com/) nếu bạn không muốn sử dụng docker.
+
+### Prisma
+
+Nếu app của bạn sử dụng Prisma, hãy chắc chắn rằng bạn đã chạy lệnh `npx prisma db push` từ thư mục gốc của app. Lệnh này sẽ đồng bộ hóa schema của Prisma với cơ sở dữ liệu của bạn và sẽ tạo ra các kiểu TypeScript cho Prisma Client dựa trên schema của bạn. Lưu ý rằng bạn cần [khởi động lại server TypeScript](https://tinytip.co/tips/vscode-restart-ts/) sau khi làm điều này để nó có thể phát hiện ra các kiểu đã được tạo.
+
+### Drizzle
+
+Nếu app của bạn sử dụng Drizzle, hãy xem file `.env` để biết hướng dẫn cách tạo biến môi trường `DATABASE_URL`. Khi file env của bạn đã sẵn sàng, chạy lệnh `pnpm db:push` (hoặc lệnh tương đương cho các trình quản lý gói khác) để đẩy schema của bạn.
+
+## Xác thực
+
+Nếu app của bạn sử dụng NextAuth.js, chúng tôi cung cấp cho bạn một `DiscordProvider`. Đây là một trong những provider đơn giản nhất mà NextAuth.js cung cấp, tuy nhiên nó vẫn cần một chút cấu hình ban đầu từ phía bạn.
+
+Ngoài ra, nếu bạn muốn sử dụng một provider khác, bạn cũng có thể sử dụng một trong [nhiều provider](https://next-auth.js.org/providers/) mà NextAuth.js cung cấp.
+
+1. Bạn cần một tài khoản Discord, vì vậy hãy tạo cho mình một cái một nếu bạn chưa có.
+2. Đi đến https://discord.com/developers/applications và ấn "New Application" ở góc trên bên phải. Đặt tên cho ứng dụng của bạn và đồng ý với Điều khoản dịch vụ.
+3. Khi ứng dụng của bạn đã được tạo, đi đến "Settings → OAuth2 → General".
+4. Copy "Client ID" và thêm nó vào file `.env` dưới dạng `AUTH_DISCORD_ID`.
+5. Click "Reset Secret", copy secret mới, và thêm nó vào file `.env` dưới dạng `AUTH_DISCORD_SECRET`.
+6. Click "Add Redirect" và nhập `http://localhost:3000/api/auth/callback/discord`.
+ - Đối với triển khai sản phẩm, hãy làm theo các bước trước để tạo một ứng dụng Discord khác, nhưng lần này thay thế `http://localhost:3000` với URL mà bạn đang triển khai.
+7. Lưu thay đổi.
+
+Và giờ đây bạn đã có thể đăng nhập bằng Discord.
+
+## Cấu hình trình soạn thảo của bạn
+
+Các extension sau đây được khuyến nghị để mang lại một trải nghiệm phát triển tối ưu. Các liên kết dưới đây cung cấp hỗ trợ plugin cho trình chỉnh sửa cụ thể.
+
+- [Prisma Extension](https://www.prisma.io/docs/guides/development-environment/editor-setup)
+- [Tailwind CSS IntelliSense Extension](https://tailwindcss.com/docs/editor-setup)
+- [Prettier Extension](https://prettier.io/docs/en/editors.html)
+
+## Bước tiếp theo
+
+- Nếu app của bạn sử dụng tRPC, hãy xem `src/pages/index.tsx` và `src/server/api/routers/post.ts` để hiểu cách tRPC queries hoạt động.
+- Hãy xem xét các tài liệu của Create T3 App, cũng như các tài liệu của các thư viện mà app của bạn sử dụng.
+- Hãy tham gia [Discord](https://t3.gg/discord) của chúng tôi và cho chúng tôi một ngôi sao tại [GitHub](https://github.com/t3-oss/create-t3-app)! :)
diff --git a/www/src/pages/vi/usage/index.astro b/www/src/pages/vi/usage/index.astro
new file mode 100644
index 0000000000..4c31ec7bf1
--- /dev/null
+++ b/www/src/pages/vi/usage/index.astro
@@ -0,0 +1,24 @@
+---
+import IndexPage from "../../../components/docs/indexPage.astro";
+import { SIDEBAR, type Frontmatter } from "../../../config";
+import { getLanguageFromURL } from "../../../languages";
+import Layout from "../../../layouts/docs.astro";
+
+const frontmatter: Frontmatter = {
+ title: "Usage",
+ layout: "docs",
+ description: "Learn how to use the different technology from the T3 Stack.",
+};
+
+const lang = getLanguageFromURL(Astro.url.pathname);
+const sidebarEntries = SIDEBAR[lang]["Usage"]!;
+const files = await Astro.glob("./*.{md,mdx,astro}");
+---
+
+
+
+
diff --git a/www/src/pages/vi/usage/next-auth.mdx b/www/src/pages/vi/usage/next-auth.mdx
new file mode 100644
index 0000000000..70702398c3
--- /dev/null
+++ b/www/src/pages/vi/usage/next-auth.mdx
@@ -0,0 +1,18 @@
+---
+title: NextAuth.js
+description: Sử dụng NextAuth.js
+layout: ../../../layouts/docs.astro
+lang: vi
+isMdx: true
+---
+
+import Tabs from "../../../components/docs/tabs.astro";
+import AppRouter from "./_next-auth-app-router.mdx";
+import Pages from "./_next-auth-pages.mdx";
+
+Khi bạn muốn có cho mình một hệ thống xác thực hoàn thiện trong ứng dụng Next.js của bạn, NextAuth.js là một giải pháp tuyệt vời để mang đến sự phức tạp của bảo mật mà không cần tốn quá nhiều công sức để xây dựng. Nó cung cấp danh sách các nhà cung cấp bảo mật thứ 3 để thêm xác thực OAuth nhanh chóng và cung cấp các adapter dành cho nhiều cơ sở dữ liệu và ORM khác nhau.
+
+
+
+
+
diff --git a/www/src/pages/vi/usage/next-js.md b/www/src/pages/vi/usage/next-js.md
new file mode 100644
index 0000000000..78171fc94f
--- /dev/null
+++ b/www/src/pages/vi/usage/next-js.md
@@ -0,0 +1,37 @@
+---
+title: Next.js
+description: Sử dụng Next.js
+layout: ../../../layouts/docs.astro
+lang: vi
+---
+
+Next.js được xem như là một framework backend cho các ứng dụng React của bạn.
+
+
+
+
+
+Tham khảo [bài giảng của Theo về Next.js](https://www.youtube.com/watch?v=W4UhNo3HAMw) để hiểu rõ hơn về Next.js và cách nó hoạt động.
+
+## Tại sao tôi nên dùng Next.js?
+
+Chúng ta đều yêu React. Nó đã làm cho việc phát triển UI trở nên dễ dàng hơn bao giờ hết. Nhưng đồng thời nó cũng có thể dẫn chúng ta vào ngõ cụt. Next.js cung cấp một cách nhìn nhận về việc phát triển ứng dụng sử dụng React, mang nặng tính tối ưu hóa để tạo ra các ứng dụng sử dụng React. Từ routing đến định nghĩa API đến việc render hình ảnh, chúng tôi tin rằng Next.js sẽ giúp những nhà phát triển web đưa ra các quyết định tốt hơn.
+
+Sử dụng Next.js với [Vercel](https://vercel.com/) làm cho việc phát triển và triển khai ứng dụng web trở nên dễ dàng hơn bao giờ hết. Với gói miễn phí tuyệt vời và giao diện dễ sử dụng, Vercel cung cấp một giải pháp "point and click" để triển khai trang web của bạn (Chúng tôi ❤️ Vercel)
+
+## Lấy dữ liệu tĩnh/Server Props
+
+Một tính năng quan trọng của Next.js là khả năng đọc dữ liệu. Chúng tôi khuyến nghị bạn tham khảo [tài liệu chính thức](https://nextjs.org/docs/basic-features/data-fetching) để hiểu sự khác biệt giữa chúng và tìm ra cách sử dụng hiệu quả mỗi phương pháp . `getServerSideProps` thường gây ra nhiều phiền toái và áp dụng được với ít trường, bởi vì nó là một blocking call và có thể dẫn tới làm chậm trang web của bạn. [Incremental Static Regeneration](https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration) là một lựa chọn tốt hơn cho `getServerSideProps` khi dữ liệu của nó trả về là dữ liệu động và có thể được lấy từng phần.
+
+Nếu bạn cần sử dụng tính năng này, hãy tham khảo các liên kết sau: [Advanced tRPC - Callers, functions, and gSSP](https://www.youtube.com/watch?v=G2ZzmgShHgQ) và [SSG-Helpers](https://trpc.io/docs/v9/ssg-helpers)
+
+## Tài liệu hữu ích
+
+| Tài liệu | Đường dẫn |
+| --------------------------- | ---------------------------------- |
+| Tài liệu Next.js | https://nextjs.org/docs |
+| GitHub Next.js | https://github.com/vercel/next.js |
+| Blog Next.js | https://nextjs.org/blog |
+| Discord Next.js | https://nextjs.org/discord |
+| Twitter Next.js | https://twitter.com/nextjs |
+| Kênh Youtube Vercel/Next.js | https://www.youtube.com/c/VercelHQ |
diff --git a/www/src/pages/vi/usage/prisma.md b/www/src/pages/vi/usage/prisma.md
new file mode 100644
index 0000000000..33fd16af7d
--- /dev/null
+++ b/www/src/pages/vi/usage/prisma.md
@@ -0,0 +1,78 @@
+---
+title: Prisma
+description: Cách sử dụng Prisma
+layout: ../../../layouts/docs.astro
+lang: vi
+---
+
+Prisma là một ORM cho TypeScript, cho phép bạn định nghĩa schema và mô hình của cơ sở dữ liệu của bạn trong tệp `schema.prisma`, và sau đó tạo ra một client mà kiểu dữ liệu của bạn sẽ được liên kết chặt chẽ với cơ sở dữ liệu của bạn và có thể được sử dụng để tương tác với cơ sở dữ liệu của bạn từ backend.
+
+## Prisma Client
+
+Client của Prisma được đặt ở `src/server/db.ts`, được khởi tạo như là một biến toàn cục (được khuyến nghị là [best practice](https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices#problem) bởi đội ngũ tại Prisma) và được xuất ra để được sử dụng trong các route API của bạn. Chúng tôi đã bao gồm Prisma Client trong [Context](/en/usage/trpc#-serverapitrpcts) và khuyến nghị bạn sử dụng từ Context thay vì nhập nó riêng lẻ trong từng tệp.
+
+## Schema
+
+Bạn sẽ tìm thấy tệp schema của Prisma ở `/prisma/schema.prisma`. Đây là nơi bạn định nghĩa schema và mô hình của cơ sở dữ liệu của bạn, và được sử dụng khi tạo ra client của Prisma.
+
+### Với NextAuth.js
+
+Khi bạn chọn NextAuth.js kết hợp với Prisma, tệp schema được tạo và thiết lập cho bạn với các giá trị được Auth.js khuyến nghị như là `User`, `Session`, `Account`, và `VerificationToken`, tìm hiểu thêm tại [tài liệu Auth.js](https://next-auth.js.org/adapters/prisma).
+
+## Cơ sở dữ liệu mặc định
+
+Cơ sở dữ liệu mặc định là cơ sở dữ liệu SQLite, tuy đây là điều tốt để bạn có thể tập trung cho phát triển và tạo ra một proof-of-concept nhanh chóng, nhưng chúng tôi không khuyến nghị bạn làm điều này cho production cảu bạn. Bạn có thể thay đổi cơ sở dữ liệu để sử dụng bằng cách thay đổi `provider` trong khối `datasource` thành `postgresql` hoặc `mysql`, và sau đó cập nhật chuỗi kết nối trong biến môi trường để Prisma có thể kết nối với cơ sở dữ liệu của bạn.
+
+## Tạo dữ liệu cho cơ sở dữ liệu
+
+[Tạo dữ liệu cho cơ sở dữ liệu](https://www.prisma.io/docs/guides/database/seed-database) là một cách tốt để nhanh chóng điền đầy cơ sở dữ liệu với dữ liệu thử nghiệm để giúp bạn bắt đầu. Để thiết lập seeding, bạn sẽ cần tạo một tệp `seed.ts` trong thư mục `/prisma`, và sau đó thêm một script `seed` vào tệp `package.json` của bạn. Bạn cũng sẽ cần thêm vào một Typescript runner để thực thi script seed, chúng tôi đề xuất [tsx](https://github.com/esbuild-kit/tsx), một Typescript runner rất hiệu quả sử dụng esbuild và không yêu cầu bất kỳ cấu hình ESM, nhưng `ts-node` hoặc các runner khác cũng sẽ hoạt động tốt cho bước này.
+
+```jsonc:package.json
+{
+ "scripts": {
+ "db-seed": "NODE_ENV=development prisma db seed"
+ },
+ "prisma": {
+ "seed": "tsx prisma/seed.ts"
+ }
+}
+```
+
+```ts:prisma/seed.ts
+import { db } from "../src/server/db";
+
+async function main() {
+ const id = "cl9ebqhxk00003b600tymydho";
+ await db.example.upsert({
+ where: {
+ id,
+ },
+ create: {
+ id,
+ },
+ update: {},
+ });
+}
+
+main()
+ .then(async () => {
+ await db.$disconnect();
+ })
+ .catch(async (e) => {
+ console.error(e);
+ await db.$disconnect();
+ process.exit(1);
+ });
+```
+
+Sau đó, chỉ cần chạy `pnpm db-seed` (hoặc `npm`/`yarn`) để tạo dữ liệu cho cơ sở dữ liệu của bạn.
+
+## Tài liệu hữu ích
+
+| Tài liệu | Đường dẫn |
+| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Tài liệu của Prisma | https://www.prisma.io/docs/ |
+| GitHub của Prisma | https://github.com/prisma/prisma |
+| Khu thử nghiệm Prisma Migrate | https://playground.prisma.io/guides |
+| Prisma Adapter cho NextAuth.JS | https://next-auth.js.org/adapters/prisma |
+| Hướng dẫn kết nối cơ sở dữ liệu PlanetScale | https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale |
diff --git a/www/src/pages/vi/usage/tailwind.md b/www/src/pages/vi/usage/tailwind.md
new file mode 100644
index 0000000000..22902ab2e0
--- /dev/null
+++ b/www/src/pages/vi/usage/tailwind.md
@@ -0,0 +1,96 @@
+---
+title: Tailwind CSS
+description: Sử dụng Tailwind CSS
+layout: ../../../layouts/docs.astro
+lang: vi
+---
+
+## Tailwind CSS là gì?
+
+Tailwind CSS là một framework CSS nhỏ gọn, [tập trung vào utility](https://tailwindcss.com/docs/utility-first) nhằm cho phép bạn xây dựng thiết kế tùy chỉnh mà không cần chuyển đổi context giữa CSS thông thường. Nó là một framework CSS và không cung cấp bất kỳ thành phần tiền xây dựng hoặc logic nào, và cung cấp [một tập hợp khác biệt](https://www.youtube.com/watch?v=CQuTF-bkOgc) so với một các thư viện khác như Material UI.
+
+Nó làm cho CSS trở nên vô cùng dễ dàng và nhanh chóng để viết, như được chứng minh bởi ví dụ sau:
+
+CSS thông thường:
+
+1. Viết CSS, thường trong một file riêng
+
+```css
+.my-class {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ background-color: #fff;
+ border: 1px solid #e2e8f0;
+ border-radius: 0.25rem;
+ padding: 1rem;
+}
+```
+
+2. Import CSS vào component của bạn
+
+```jsx
+import "./my-class.css";
+```
+
+3. Thêm class vào HTML
+
+```html
+
...
+```
+
+Tương đương trong Tailwind:
+
+1. Chỉ viết classes trong HTML của bạn
+
+```html
+
+ ...
+
+```
+
+Khi sử dụng cùng với React Components, nó mang đến sức mạnh để xây dựng UI một cách nhanh chóng.
+
+Tailwind CSS có một hệ thống thiết kế tích hợp sẵn, được tạo ra từ box với một palette màu sắc được chọn cẩn thận, các kích thước cho các kiểu như width/height và padding/margin cho một thiết kế đồng nhất, cũng như các điểm cắt cho tạo ra các bố cục hài hòa. Hệ thống này được thiết kế này để có thể dễ dàng tùy chỉnh và mở rộng để tạo ra các công cụ mà bạn cần.
+
+
+
+
+
+Tru Narla, hay được biết đến dưới tên một người dùng Twitter là [mewtru](https://twitter.com/trunarla), đã cho chúng ta một bài nói chuyện tuyệt vời về [cách xây dựng một hệ thống thiết kế sử dụng Tailwind CSS](https://www.youtube.com/watch?v=T-Zv73yZ_QI).
+
+## Sử dụng
+
+Hãy đảm bảo rằng bạn đã cài đặt các plugin editor cho Tailwind CSS để cải thiện trải nghiệm viết Tailwind CSS.
+
+### Extensions và Plugins
+
+- [VSCode Extension](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss)
+- [JetBrains Integration](https://www.jetbrains.com/help/webstorm/tailwind-css.html#ws_css_tailwind_install)
+- [Neovim LSP](https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md#tailwindcss)
+
+### Định dạng
+
+Tailwind CSS classes có thể dễ dàng trở nên lộn xộn, vì vậy việc cần có một định dạng cho các classes là điều cần thiết. [Tailwind CSS Prettier Plugin](https://github.com/tailwindlabs/prettier-plugin-tailwindcss) sắp xếp các classes trong [thứ tự được đề xuất](https://tailwindcss.com/blog/automatic-class-sorting-with-prettier#how-classes-are-sorted) để các classes phù hợp với bundle CSS được xuất ra. Khi chọn Tailwind trong CLI, chúng tôi sẽ cài đặt và cấu hình nó cho bạn.
+
+### Áp dụng điều kiện
+
+Thêm classes bằng cách sử dụng ternaries có thể trở nên rất lộn xộn và khó đọc. Các package này giúp sắp xếp các classes của bạn khi sử dụng một số logic điều kiện.
+
+- [clsx](https://github.com/lukeed/clsx)
+- [classnames](https://github.com/JedWatson/classnames)
+
+## Tài liệu hữu ích
+
+| Tài liệu | Đường dẫn |
+| --------------------------- | -------------------------------------------------------- |
+| Tài liệu củaTailwind | https://tailwindcss.com/docs/editor-setup/ |
+| Tailwind Cheat Sheet | https://nerdcave.com/tailwind-cheat-sheet/ |
+| awesome-tailwindcss | https://github.com/aniftyco/awesome-tailwindcss/ |
+| Cộng đồng Tailwind | https://github.com/tailwindlabs/tailwindcss/discussions/ |
+| Server Discord của Tailwind | https://tailwindcss.com/discord/ |
+| Kênh Youtube của Tailwind | https://www.youtube.com/tailwindlabs/ |
+| Playground của Tailwind | https://play.tailwindcss.com/ |
diff --git a/www/src/pages/vi/usage/trpc.md b/www/src/pages/vi/usage/trpc.md
new file mode 100644
index 0000000000..d9f2d52829
--- /dev/null
+++ b/www/src/pages/vi/usage/trpc.md
@@ -0,0 +1,382 @@
+---
+title: tRPC
+description: Cách sử dụng tRPC
+layout: ../../../layouts/docs.astro
+lang: vi
+---
+
+tRPC cho phép chúng ta viết API có tính toàn vẹn của kiểu dữ liệu (typesafe) mà không cần qua các bước tạo code (code generation) hoặc runtime bloat. Nó sử dụng inference của TypeScript để suy ra định nghĩa kiểu của router API của bạn và cho phép bạn gọi các thủ tục API của bạn từ frontend mà vẫn đảm bảo tính toàn vẹn của kiểu dữ liệu và auto-completion. Khi sử dụng tRPC, frontend và backend của bạn gần nhau hơn bao giờ hết, cho phép bạn có trải nghiệm lập trình (developer experience) tuyệt vời.
+
+
+
+
+ "Tôi tạo tRPC để cho phép mọi người lập trình nhanh hơn bằng cách loại bỏ API layer truyền thống, trong khi vẫn đảm bảo rằng ứng dụng của chúng ta sẽ không bị phá vỡ khi chúng ta lập trình ứng dụng một cách nhanh chóng."
+
+
+Contributor của tRPC, [trashh_dev](https://twitter.com/trashh_dev), đã có [một bài giảng tuyệt vời tại Next.js Conf](https://www.youtube.com/watch?v=2LYM8gf184U) về tRPC. Chúng tôi khuyên bạn nên tham khảo qua video trước nếu bạn chưa từng sử dụng tRPC.
+
+Với tRPC, bạn viết các hàm TypeScript trên backend, và sau đó gọi chúng từ frontend. Một tRPC procedure đơn giản có thể được định nghĩa như sau:
+
+```ts:server/api/routers/user.ts
+const userRouter = createTRPCRouter({
+ getById: publicProcedure.input(z.string()).query(({ ctx, input }) => {
+ return ctx.prisma.user.findFirst({
+ where: {
+ id: input,
+ },
+ });
+ }),
+});
+```
+
+Đây là một tRPC procedure (tương đương với một route handler trong backend truyền thống), nó bắt đầu bằng cách kiểm tra đầu vào bằng thư viện Zod (đồng thời cũng là thư viện validation mà chúng tôi sử dụng cho [biến môi trường](./env-variables)) - trong trường hợp này, nó đảm bảo rằng đầu vào là một chuỗi. Nếu đầu vào không phải là một chuỗi, nó sẽ báo lỗi ngay.
+
+Sau đó, chúng ta có một hàm resolver, có thể là [query](https://trpc.io/docs/client/react/useQuery), [mutation](https://trpc.io/docs/v11/client/react/useMutation), hoặc một [subscription](https://trpc.io/docs/v11/subscriptions). Trong ví dụ của chúng tôi, hàm resolver này gọi tới cơ sở dữ liệu bằng cách sử dụng [prisma](./prisma) client và trả về người dùng có `id` khớp với id mà chúng tôi đã truyền vào.
+
+Bạn định nghĩa các procedures trong `routers` mà đại diện cho một tập hợp các procedures liên quan với nhau và có cùng namespace. Bạn có thể có một router cho `users`, một cho `posts`, và một router khác cho `messages`. Sau đó, các router này có thể được gộp lại thành một `appRouter` duy nhất:
+
+```ts:server/api/root.ts
+const appRouter = createTRPCRouter({
+ users: userRouter,
+ posts: postRouter,
+ messages: messageRouter,
+});
+
+export type AppRouter = typeof appRouter;
+```
+
+Chú ý rằng chúng ta chỉ cần xuất (export) kiểu dữ liệu của router của chúng ta, điều này có nghĩa là chúng ta chẳng cần phải import bất kỳ một đoạn code server nào ở phía client.
+
+Bây giờ, chúng ta sẽ thử gọi một procedure của chúng ta trên frontend. tRPC có cung cấp một wrapper cho `@tanstack/react-query` cho phép bạn sử dụng toàn bộ sức mạnh của các hooks mà nó cung cấp, nhưng với lợi ích thêm là các cuộc gọi API của bạn sẽ được tự động định kiểu và suy ra. Chúng ta có thể gọi các procedures của chúng ta từ frontend như sau:
+
+```tsx:pages/users/[id].tsx
+import { useRouter } from "next/router";
+import { api } from "../../utils/api";
+
+const UserPage = () => {
+ const { query } = useRouter();
+ const userQuery = api.users.getById.useQuery(query.id);
+
+ return (
+
+
{userQuery.data?.name}
+
+ );
+};
+```
+
+Bạn sẽ nhận thấy ngay lập tức việc autocompletion và tính toàn vẹn kiểu dữ liệu làm cho việc lập trình trở nên tuyệt vời hơn bao giờ hết. Ngay khi bạn viết `api.`, các routers của bạn sẽ xuất hiện trong autocomplete, và khi bạn chọn một router, các procedures của nó cũng sẽ xuất hiện. Bạn cũng sẽ nhận được một lỗi TypeScript nếu đầu vào của bạn không khớp với validator mà bạn đã định nghĩa ở phía backend.
+
+## Xử lý lỗi
+
+Mặc định, `create-t3-app` đã thiết lập một [error formatter](https://trpc.io/docs/v11/server/error-formatting) cho phép bạn suy ra các lỗi Zod nếu bạn nhận được lỗi validation ở phía backend.
+
+Ví dụ:
+
+```tsx
+function MyComponent() {
+ const { mutate, error } = api.post.create.useMutation();
+
+ return (
+
+ );
+}
+```
+
+## Các file
+
+tRPC yêu cầu rất nhiều boilerplate mà `create-t3-app` đã thiết lập cho bạn. Hãy cùng chúng tôi đi qua các file đã được tạo:
+
+### 📄 `pages/api/trpc/[trpc].ts`
+
+Đây được gọi là điểm xuất phát cho API của bạn và để thêm vào các router của tRPC. Thông thường, bạn sẽ không phải lo lắng với file này nhiều, nhưng nếu cần thiết, ví dụ như khi bạn muốn sử dụng các middleware như CORS hoặc tương tự, hãy biết rằng hàm `createNextApiHandler` là một [Next.js API handler](https://nextjs.org/docs/api-routes/introduction) nhận vào một đối tượng [request](https://developer.mozilla.org/en-US/docs/Web/API/Request) và [response](https://developer.mozilla.org/en-US/docs/Web/API/Response). Điều này có nghĩa là bạn có thể bọc `createNextApiHandler` trong bất kỳ middleware nào bạn muốn. Xem [ví dụ](#sử-dụng-cors) dưới đây để biết cách thêm CORS.
+
+### 📄 `server/api/trpc.ts`
+
+File này được chia thành hai phần: khởi tạo context và khởi tạo tRPC:
+
+1. Đây là nơi chúng ta định nghĩa context mà tRPC procedures sẽ có thể truy cập. Context là nơi mà tất cả các procedures của tRPC sẽ có thể truy cập để sử dụng những dữ liệu được "đựng" trong đó. Chính vì thế, đây là nơi tuyệt vời để đặt các thứ như kết nối cơ sở dữ liệu, thông tin xác thực, v.v. Trong `create-t3-app`, chúng tôi sử dụng hai hàm, để cho phép sử dụng một tập con của context khi chúng ta không có đối tượng request.
+
+- `createInnerTRPCContext`: Đây là nơi bạn định nghĩa context mà không phụ thuộc vào request, ví dụ như kết nối cơ sở dữ liệu. Bạn có thể sử dụng hàm này cho [integration testing](#sample-integration-test) hoặc [ssg-helpers](https://trpc.io/docs/v10/client/nextjs/server-side-helpers) khi bạn không có đối tượng request.
+
+- `createTRPCContext`: Đây là nơi bạn định nghĩa context mà phụ thuộc vào request, ví dụ như thông tin phiên người dùng. Bạn yêu cầu phiên người dùng bằng cách sử dụng đối tượng `opts.req`, và sau đó chuyển phiên người dùng xuống hàm `createInnerTRPCContext` để tạo context cuối cùng.
+
+2. Chúng ta khởi tạo tRPC và định nghĩa các procedures có thể tái sử dụng và [middlewares](https://trpc.io/docs/v11/server/middlewares). Theo quy ước, bạn không nên xuất toàn bộ đối tượng `t` mà thay vào đó, tạo các procedures và middlewares để có thể tái sử dụng chúng.
+
+Chúng tôi sử dụng `superjson` để làm [data transformer](https://trpc.io/docs/v10/server/data-transformers). Điều này có nghĩa là dữ liệu của bạn sẽ được bảo toàn khi chúng đến client, vì vậy nếu bạn gửi một đối tượng `Date`, client sẽ trả về một đối tượng `Date` và không phải là một chuỗi, như là trường hợp với hầu hết các APIs.
+
+### 📄 `server/api/routers/*.ts`
+
+Đây là nơi bạn định nghĩa các routes và procedures của API của bạn. Theo quy ước, bạn nên [tạo các routers riêng biệt](https://trpc.io/docs/v11/server/routers) cho các procedures liên quan.
+
+### 📄 `server/api/root.ts`
+
+Ở đây chúng ta thực hiện [gộp](https://trpc.io/docs/v11/server/merging-routers) tất cả các routers con được định nghĩa trong `routers/**` thành một router duy nhất.
+
+### 📄 `utils/api.ts`
+
+Đây là điểm xuất phát cho tRPC ở phía frontend. Đây là nơi bạn sẽ import **type definition** của router và tạo client tRPC của bạn cùng với các hooks react-query. Vì chúng tôi đã sử dụng `superjson` làm data transformer ở phía backend, chúng tôi cần sử dụng nó ở phía frontend. Điều này sẽ giúp cho việc dữ liệu được chuyển đổi từ backend sẽ được giải mã ở phía frontend.
+
+Bạn sẽ định nghĩa các [links](https://trpc.io/docs/v11/client/links) ở đây, điều này xác định luồng request từ client đến server. Chúng tôi sử dụng [`httpBatchLink`](https://trpc.io/docs/v11/client/links/httpBatchLink) mà cho phép [request batching](https://cloud.google.com/compute/docs/api/how-tos/batch), cũng như một [`loggerLink`](https://trpc.io/docs/v10/links/loggerLink) mà xuất ra các log request hữu ích trong quá trình phát triển.
+
+Cuối cùng, chúng tôi xuất ra một [helper type](https://trpc.io/docs/client/vanilla/infer-types) mà bạn có thể sử dụng để suy ra kiểu dữ liệu của bạn ở phía frontend.
+
+
+
+
+
+Một contributor khác của Create T3 App, [Christopher Ehrlich](https://twitter.com/ccccjjjjeeee), đã làm một video về [luồng dữ liệu trong tRPC](https://www.youtube.com/watch?v=x4mu-jOiA0Q). Video này được khuyến khích nếu bạn đã sử dụng tRPC nhưng vẫn còn mơ hồ về cách nó hoạt động.
+
+## Làm sao để gọi API từ bên ngoài?
+
+Với các API thông thường, bạn có thể gọi các endpoint của mình bằng bất kỳ HTTP client nào như `curl`, `Postman`, `fetch` hoặc trực tiếp từ trình duyệt của bạn. Với tRPC, điều này hơi khác. Nếu bạn muốn gọi các procedures mà không cần sử dụng client tRPC, có hai cách được khuyến nghị:
+
+### Khởi tạo một external procedure
+
+Nếu bạn muốn khởi tạo một procedure mà bạn có thể gọi từ bên ngoài, bạn có thể đang tìm kiếm [server side calls](https://trpc.io/docs/server/server-side-calls). Điều này sẽ cho phép bạn tạo một endpoint Next.js thông thường, nhưng sử dụng phần resolver của procedure tRPC của bạn.
+
+```ts:pages/api/users/[id].ts
+import { type NextApiRequest, type NextApiResponse } from "next";
+import { appRouter, createCaller } from "../../../server/api/root";
+import { createTRPCContext } from "../../../server/api/trpc";
+
+const userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {
+ // Tạo context và caller
+ const ctx = await createTRPCContext({ req, res });
+ const caller = createCaller(ctx);
+ try {
+ const { id } = req.query;
+ const user = await caller.user.getById(id);
+ res.status(200).json(user);
+ } catch (cause) {
+ if (cause instanceof TRPCError) {
+ // Một lỗi tRPC đã xảy ra
+ const httpCode = getHTTPStatusCodeFromError(cause);
+ return res.status(httpCode).json(cause);
+ }
+ // Một lỗi khác đã xảy ra
+ console.error(cause);
+ res.status(500).json({ message: "Lỗi máy chủ nội bộ" });
+ }
+};
+
+export default userByIdHandler;
+```
+
+### Khởi tạo tất cả các procedures như các REST endpoints
+
+Nếu bạn muốn khởi tạo tất cả các procedures mà bạn có thể gọi từ bên ngoài, bạn có thê tham khảo các plugins xây dựng bởi cộng đồng [trpc-openapi](https://github.com/jlalmes/trpc-openapi/tree/master). Bằng cách cung cấp một số thông tin meta-data cho các procedures của bạn, bạn có thể tạo ra một API REST tương thích với OpenAPI từ router tRPC của bạn.
+
+### Đây chỉ là các HTTP Requests
+
+tRPC sử dụng giao thức HTTP, vì vậy bạn đều có thể gọi các procedures của tRPC bằng các HTTP requests thông thường. Tuy nhiên, cú pháp có thể khá phức tạp do tRPC sử dụng [kiểu định nghĩa giao thức RPC](https://trpc.io/docs/rpc) riêng biệt. Nếu bạn muốn tìm hiểu, bạn có thể kiểm tra các request và responses của tRPC trong tab mạng của trình duyệt của bạn, nhưng chúng tôi khuyến khích bạn nên làm điều này với mục đích học hỏi và sử dụng một trong các giải pháp được đề cập ở trên.
+
+## So sánh với Next.js API endpoint
+
+Hãy so sánh một endpoint Next.js API với một procedure tRPC. Ví dụ chúng ta muốn lấy một đối tượng user từ cơ sở dữ liệu và trả nó cho frontend. Chúng ta có thể viết một endpoint Next.js API như sau:
+
+```ts:pages/api/users/[id].ts
+import { type NextApiRequest, type NextApiResponse } from "next";
+import { prisma } from "../../../server/db";
+
+const userByIdHandler = async (req: NextApiRequest, res: NextApiResponse) => {
+ if (req.method !== "GET") {
+ return res.status(405).end();
+ }
+
+ const { id } = req.query;
+
+ if (!id || typeof id !== "string") {
+ return res.status(400).json({ error: "Invalid id" });
+ }
+
+ const examples = await prisma.example.findFirst({
+ where: {
+ id,
+ },
+ });
+
+ res.status(200).json(examples);
+};
+
+export default userByIdHandler;
+```
+
+```ts:pages/users/[id].tsx
+import { useState, useEffect } from "react";
+import { useRouter } from "next/router";
+
+const UserPage = () => {
+ const router = useRouter();
+ const { id } = router.query;
+
+ const [user, setUser] = useState(null);
+ useEffect(() => {
+ fetch(`/api/user/${id}`)
+ .then((res) => res.json())
+ .then((data) => setUser(data));
+ }, [id]);
+};
+```
+
+So sánh với ví dụ tRPC ở trên và bạn có thể thấy một số lợi ích của tRPC:
+
+- Thay vì phải tạo ra một URL cho mỗi route, điều này có thể trở nên khó khăn khi gỡ lỗi nếu bạn chuyển đổi điều gì đó, với tRPC, router của bạn là một đối tượng với autocomplete.
+- Bạn không cần phải xác định phương thức HTTP nào đã được sử dụng.
+- Bạn không cần phải xác định rằng request query hoặc body chứa dữ liệu đúng, vì Zod sẽ xử lý điều này.
+- Thay vì tạo ra một response, bạn có thể throws lỗi và trả về một giá trị hoặc đối tượng như bạn làm trong bất kỳ hàm TypeScript nào khác.
+- Gọi procedure ở phía frontend sẽ cung cấp đầy đủ autocompletion và tính toàn vẹn kiểu dữ liệu.
+
+## Các snippet hữu ích
+
+Dưới đây là một số snippet mà có thể hữu ích cho bạn.
+
+### Sử dụng CORS
+
+Nếu bạn cần sử dụng API của bạn từ một domain khác, ví dụ như trong một monorepo bao gồm một app React Native, bạn có thể cần phải sử dụng CORS:
+
+```ts:pages/api/trpc/[trpc].ts
+import { type NextApiRequest, type NextApiResponse } from "next";
+import { createNextApiHandler } from "@trpc/server/adapters/next";
+import { appRouter } from "~/server/api/root";
+import { createTRPCContext } from "~/server/api/trpc";
+import cors from "nextjs-cors";
+
+const handler = async (req: NextApiRequest, res: NextApiResponse) => {
+ // Sử dụng CORS
+ await cors(req, res);
+
+ // Tạo và gọi handler tRPC
+ return createNextApiHandler({
+ router: appRouter,
+ createContext: createTRPCContext,
+ })(req, res);
+};
+
+export default handler;
+```
+
+### Cập nhật tối ưu (Optimistic updates)
+
+Cập nhật tối ưu (optimistic updates) là khi chúng ta cập nhật UI trước khi cuộc gọi API hoàn tất. Điều này cho phép người dùng có trải nghiệm tốt hơn vì họ không phải chờ cuộc gọi API hoàn tất trước khi UI phản ánh kết quả hành động của họ. Tuy nhiên, các ứng dụng có giá trị dữ liệu chính xác cao nên tránh sử dụng cập nhật tối ưu vì chúng không biểu hiện của trạng thái backend. Bạn có thể đọc thêm trên [tài liệu của React Query](https://tanstack.com/query/latest/docs/framework/react/guides/optimistic-updates).
+
+```tsx
+const MyComponent = () => {
+ const listPostQuery = api.post.list.useQuery();
+
+ const utils = api.useUtils();
+ const postCreate = api.post.create.useMutation({
+ async onMutate(newPost) {
+ // Hủy bỏ cuộc gọi API (để chúng không ghi đè lên cập nhật tối ưu của chúng ta)
+ await utils.post.list.cancel();
+
+ // Lấy dữ liệu từ cache
+ const prevData = utils.post.list.getData();
+
+ // Cập nhật dữ liệu tối ưu với bài viết mới
+ utils.post.list.setData(undefined, (old) => [...old, newPost]);
+
+ // Trả về dữ liệu trước đó để chúng ta có thể quay lại nó nếu điều gì đó sai
+ return { prevData };
+ },
+ onError(err, newPost, ctx) {
+ // Nếu cuộc gọi mutation thất bại, sử dụng giá trị từ onMutate
+ utils.post.list.setData(undefined, ctx.prevData);
+ },
+ onSettled() {
+ // Đồng bộ với server một lần mutation đã hoàn tất
+ utils.post.list.invalidate();
+ },
+ });
+};
+```
+
+### Ví dụ về tích hợp kiểm thử
+
+Dưới đây là một ví dụ về kiểm thử sử dụng [Vitest](https://vitest.dev) để kiểm tra xem router tRPC của bạn đang hoạt động như mong đợi, phân tích kiểu đầu vào đúng, và dữ liệu trả về phù hợp với kỳ vọng.
+
+```ts
+import { type inferProcedureInput } from "@trpc/server";
+import { expect, test } from "vitest";
+
+import { appRouter, type AppRouter } from "~/server/api/root";
+import { createInnerTRPCContext } from "~/server/api/trpc";
+
+test("example router", async () => {
+ const ctx = await createInnerTRPCContext({ session: null });
+ const caller = appRouter.createCaller(ctx);
+
+ type Input = inferProcedureInput;
+ const input: Input = {
+ text: "test",
+ };
+
+ const example = await caller.example.hello(input);
+
+ expect(example).toMatchObject({ greeting: "Hello test" });
+});
+```
+
+Nếu procedure của bạn được bảo vệ, bạn có thể truyền vào một đối tượng `session` giả khi bạn tạo context:
+
+```ts
+test("protected example router", async () => {
+ const ctx = await createInnerTRPCContext({
+ session: {
+ user: { id: "123", name: "John Doe" },
+ expires: "1",
+ },
+ });
+ const caller = appRouter.createCaller(ctx);
+
+ // ...
+});
+```
+
+## Tài liệu hữu ích
+
+| Tài liệu | Đường dẫn |
+| -------------------- | ----------------------------------------------- |
+| Tài liệu tRPC | https://www.trpc.io |
+| Ví dụ về tRPC | https://github.com/trpc/trpc/tree/next/examples |
+| Tài liệu React Query | https://tanstack.com/query/latest/docs |
diff --git a/www/src/pages/vi/usage/typescript.md b/www/src/pages/vi/usage/typescript.md
new file mode 100644
index 0000000000..839e46cac5
--- /dev/null
+++ b/www/src/pages/vi/usage/typescript.md
@@ -0,0 +1,67 @@
+---
+title: TypeScript
+description: Cách sử dụng TypeScript
+layout: ../../../layouts/docs.astro
+lang: vi
+---
+
+
+
+
+ "Build safety nets, not guard rails" - "Dựng lưới an toàn, chớ xây lan can"
+
+
+Cho dù bạn có là lập trình viên tay mơ hay là lập trình viên có kinh nghiệm, chúng tôi nghĩ rằng TypeScript là một "người bạn" không thể thiếu. Mặc dù nó có thể khiến bạn gặp một chút khó khăn khi bắt đầu, nhưng giống như nhiều công cụ hữu ích khác, Typescript sẽ là công cụ khiến nhiều lập trình viên không bao giờ muốn "đường ai nấy đi" khi đã biết tận dụng sức mạnh của nó.
+
+Typescript phản hồi gần như tức thì khi bạn viết code bằng cách định nghĩa kiểu dữ liệu dự kiến, vì thế điểm mạnh của nó là tự cập nhật autocompletion theo những thay đổi mới nhất trong trình soạn thảo mã của bạn, hoặc có thể cảnh báo bạn với dòng gạch màu đỏ lòm nếu bạn đang cố gắng truy cập vào một thuộc tính không tồn tại hoặc đang cố gắng truyền một giá trị có kiểu sai, thứ khiến bạn sẽ phải tốn hàng giờ đồng hồ để "debug" sau đó.
+
+Chính vì thế, Typescript là công cụ giúp cho lập trình viên có nhiều năng suất hơn bao giờ hết; cung cấp tài liệu cho code bạn đang viết hoặc sử dụng trực tiếp trong trình soạn thảo của bạn, và có phản hồi ngay lập tức khi bạn làm sai một cái gì đó, giống như bún đậu thì phải chấm với mắm tôm chứ không phải tương ớt vậy.
+
+## Suy luận kiểu dữ liệu (Type Inference)
+
+Mặc dù nhiều lập trình viên TypeScript mới thường lo lắng về việc _định nghĩa kiểu dữ liệu_ TypeScript một cách chuẩn chỉ, nhưng lợi ích thực sự của Typescript nằm ở chỗ nó không yêu cầu bạn phải thay đổi code của mình để thay đổi kiểu dữ liệu, hay còn gọi là suy luận kiểu dữ liệu (Type Inference). Suy luận kiểu dữ liệu có nghĩa là nếu bạn đã định nghĩa một kiểu dữ liệu, kiểu dữ liệu đó sẽ đi theo trong suốt luồng của ứng dụng mà không cần phải khai báo lại ở những nơi khác. Điều này có nghĩa là, ví dụ, một khi bạn đã định nghĩa kiểu của các tham số mà một hàm nhận vào, phần còn lại của hàm thường sẽ được đảm bảo an toàn về kiểu dữ liệu mà không cần thêm bất kỳ code TypeScript cụ thể nào. Các nhà phát triển thư viện đã phải bỏ ra rất nhiều công sức để duy trì các kiểu dữ liệu cho thư viện của họ, điều này có nghĩa là chúng ta với tư cách là nhà phát triển ứng dụng có thể hưởng lợi từ cả suy luận kiểu dữ liệu và "tài liệu" được tích hợp trong trình soạn thảo code mà các kiểu này cung cấp.
+
+
+
+
+
+Xem thêm video của Theo về cách [bạn có thể sử dụng TypeScript sai](https://www.youtube.com/watch?v=RmGHnYUqQ4k).
+
+## Các ứng dụng mạnh mẽ của suy luận kiểu dữ liệu
+
+### Zod
+
+[Zod](https://github.com/colinhacks/zod) là một thư viện kiểm tra dữ liệu được xây dựng trên TypeScript. Viết một schema đại diện cho một nguồn thật sự duy nhất cho dữ liệu của bạn, và Zod sẽ đảm bảo rằng dữ liệu của bạn hợp lệ trong suốt ứng dụng của bạn, thậm chí cả khi đi qua ranh giới mạng và API bên ngoài.
+
+### Tanstack Query
+
+[Tanstack Query](https://tanstack.com/query/v4/) cung cấp cho bạn các truy vấn và thao tác sửa đổi theo kiểu khai báo, được quản lý tự động và luôn được cập nhật, từ đó trực tiếp cải thiện trải nghiệm của cả lập trình viên và người dùng.
+
+## Tài liệu hữu ích
+
+| Tài liệu | Đường dẫn |
+| ----------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
+| Cẩm nang TypeScript | https://www.typescriptlang.org/docs/handbook/ |
+| TypeScript dành cho tân thủ | https://github.com/total-typescript/beginners-typescript-tutorial |
+| Luyện tập typing chuẩn Typescript | https://github.com/type-challenges/type-challenges |
+| Kênh Youtube của người được mệnh danh là Rodney Mullen của TypeScript (Matt Pocock) | https://www.youtube.com/c/MattPocockUk/videos |
diff --git a/www/src/pages/vi/why.md b/www/src/pages/vi/why.md
new file mode 100644
index 0000000000..7e5917bbd0
--- /dev/null
+++ b/www/src/pages/vi/why.md
@@ -0,0 +1,50 @@
+---
+title: Tại sao lại là CT3A?
+description: Tại sao bạn nên chọn Create T3 App cho dự án tiếp theo của mình
+layout: ../../layouts/docs.astro
+lang: vi
+---
+
+Chúng tôi tạo ra Create T3 App vì [Theo](https://twitter.com/t3dotgg) từ chối việc có một template cho các công nghệ yêu thích của anh ấy. Được truyền cảm hứng từ create-next-app, [CLI của Astro](https://astro.build), và một tình yêu to bự dành cho tính toàn vẹn của kiểu dữ liệu (typesafety), đội ngũ Create T3 App đã làm việc chăm chỉ để tạo nên một nền móng vững chắc nhất có thể dành cho các dự án T3 Stack mới.
+
+Nếu bạn thích việc sử dụng Next.js một cách typesafe, đây chính là điểm bắt đầu của bạn. Nếu bạn tò mò về bất kỳ lựa chọn công nghệ cụ thể nào mà chúng tôi đã thực hiện, hãy bình tĩnh, lấy một ly cà phê và cùng đọc tiếp nhé :)
+
+## Tại sao lại là TypeScript?
+
+JavaScript đã khó rồi. Tại sao lại thêm nhiều các quy tắc rắc rối hơn hơn?
+
+Chúng tôi tin chắc rằng trải nghiệm mà TypeScript mang lại sẽ giúp bạn trở thành một lập trình viên tốt hơn. Nó cung cấp phản hồi trực tiếp khi bạn viết mã bằng cách xác định các kiểu dữ liệu bạn muốn, và nó cung cấp tính năng tự động hoàn thành (autocompletion) hữu ích trong trình soạn thảo (IDE) của bạn hoặc báo lỗi cho bạn bằng các đường lượn sóng màu đỏ nếu bạn đang cố gắng truy cập một thuộc tính không tồn tại hoặc cố gắng truyền một giá trị có kiểu sai, điều mà có thể khiến bạn phải đau đầu gỡ lỗi sau này nếu như không có chúng. Cho dù bạn là người mới làm quen với phát triển web hay một chuyên gia dày dạn kinh nghiệm, "sự nghiêm ngặt" của TypeScript sẽ mang lại trải nghiệm lập trình tuyệt vời hơn, nhất quán hơn so với JS thuần túy.
+
+Typesafety giúp bạn nhanh hơn. Nếu bạn chưa bị thuyết phục, có thể bạn [đang sử dụng TypeScript sai cách...](https://www.youtube.com/watch?v=RmGHnYUqQ4k)
+
+## Tại sao lại là Next.js?
+
+Chúng tôi yêu React. Nó đã làm cho việc phát triển giao diện người dùng trở nên dễ tiếp cận theo những cách mà chúng tôi chưa bao giờ tưởng tượng được trước đây. Nhưng nó cũng có thể dẫn các bạn đi vào những con đường vô tận mà không có lối ra.
+
+Next.js cung cấp một cách tiếp cận nhẹ nhàng, nhưng cực kì được tối ưu hóa cao để tạo các ứng dụng bằng React. Từ hệ thống định tuyến (Routing) đến định nghĩa API (API Routes) đến kết xuất hình ảnh (Image Rendering), chúng tôi tin tưởng Next.js sẽ là "bạn đồng hành" tuyệt vời cho các nhà phát triển đưa ra những quyết định tốt.
+
+## Tại sao lại là tRPC/Prisma/Tailwind/etc?
+
+Mặc dù mục tiêu chúng tôi là giữ mọi thứ đơn giản nhất có thể, chúng tôi thấy rằng những công nghệ này thường được sử dụng trong mọi dự án mà chúng tôi xây dựng. `create-t3-app` làm rất tốt việc cho phép bạn chọn và sử dụng những công nghệ bạn cần.
+
+### tRPC
+
+tRPC là người viết tiếp sứ mệnh của GraphQL về việc kết nối liền mạch với client dựa trên một server typesafe mà không cần phải có các boilerplate code. Nó tận dụng kiểu dữ liệu của TypeScript một cách thông minh nhằm nâng cao trải nghiệm phát triển ứng dụng.
+
+### Prisma
+
+Prisma và SQL cũng giống như TypeScript và JS. Nó đã tạo ra một trải nghiệm phát triển chưa từng tồn tại trước đây. Bằng cách tạo ra các kiểu từ một file schema do người dùng định nghĩa và có tính tương thích cao với [nhiều cơ sở dữ liệu](https://www.prisma.io/docs/concepts/database-connectors), Prisma đảm bảo tính toàn vẹn dữ liệu (typesafety) từ đầu đến cuối từ cơ sở dữ liệu đến ứng dụng của bạn.
+
+Prisma cung cấp cả một [bộ công cụ](https://www.prisma.io/docs/concepts/overview/should-you-use-prisma#-you-want-a-tool-that-holistically-covers-your-database-workflows) giúp việc tương tác hàng ngày với cơ sở dữ liệu của bạn trở nên dễ dàng hơn. Đáng chú ý, Prisma Client chịu trách nhiệm truy vấn và làm cho SQL trở nên dễ dàng đến mức bạn sẽ hầu như không nhận thấy mình đang làm việc với cơ sở dữ liệu, và Prisma Studio là một GUI tiện lợi cho cơ sở dữ liệu của bạn bằng cách cho phép bạn đọc và thao tác dữ liệu trực tiếp mà không cần viết mã.
+
+### Tailwind CSS
+
+Tailwind giống như "CSS ở chế độ chill".
+
+Bằng cách cung cấp các khối xây dựng dưới dạng các gam màu mặc định hiện đại, khoảng cách và các yếu tố cơ bản khác, Tailwind giúp dễ dàng tạo ra một ứng dụng đẹp mắt. Và không giống như các thư viện component khác, nó giúp bạn đưa ứng dụng của mình lên một tầm cao mới và tạo ra thứ gì đó đẹp đẽ và độc đáo.
+
+Ngoài ra, với cách tiếp cận giống như inline, Tailwind khuyến khích bạn tạo kiểu mà không cần lo lắng về việc đặt tên lớp, tổ chức tệp hoặc bất kỳ vấn đề nào khác không liên quan trực tiếp đến vấn đề bạn đang cố gắng giải quyết.
+
+### NextAuth.js
+
+Khi bạn muốn có một hệ thống xác thực trong ứng dụng NextJS của mình, NextAuth.js là một giải pháp tuyệt vời để giải quyết sự phức tạp của bảo mật mà không gặp rắc rối khi phải tự xây dựng nó. Nó đi kèm với một dãy các nhà cung cấp xác thực thứ 3 để bạn có thể thêm xác thực OAuth một cách nhanh chóng và đồng thời cung cấp các adapter cho nhiều cơ sở dữ liệu và ORM.