Untuk aplikasi skala menengah hingga besar dengan Next.js (App Router), Drizzle ORM, TanStack Form, dan Zod, pendekatan terbaik adalah Feature-Based Architecture (berbasis fitur).
Struktur ini mencegah folder menumpuk dan menjaga logika database, validasi skema, serta UI form tetap dekat satu sama lain.
Rekomendasi Struktur Direktori:
src/
├── app/ # Next.js App Router (Hanya routing & layout)
│ ├── (auth)/ # Route group untuk autentikasi
│ │ ├── login/
│ │ │ └── page.tsx
│ │ └── register/
│ │ └── page.tsx
│ ├── (dashboard)/ # Route group untuk halaman utama
│ │ ├── products/
│ │ │ └── page.tsx
│ │ └── layout.tsx
│ ├── api/ # API Routes / Webhooks (jika butuh)
│ ├── layout.tsx
│ └── page.tsx
│
├── db/ # Semua konfigurasi Drizzle ORM
│ ├── index.ts # Inisialisasi koneksi database (db client)
│ ├── schema/ # Definisi tabel database (dipisah per domain)
│ │ ├── users.ts
│ │ ├── products.ts
│ │ └── index.ts # Export semua schema untuk Drizzle client
│ ├── migrations/ # File migrasi otomatis dari drizzle-kit
│ └── seed.ts # Script untuk dummy data awal
│
├── features/ # Inti logika bisnis (Dipisah per fitur)
│ ├── auth/
│ │ ├── actions/ # Server Actions khusus auth
│ │ ├── components/ # UI & TanStack Form (misal: LoginForm.tsx)
│ │ └── schemas/ # Validasi Zod khusus auth
│ └── products/
│ ├── actions/ # Server Actions (createProduct, updateProduct)
│ ├── components/ # Komponen UI (ProductForm.tsx, ProductTable.tsx)
│ ├── queries/ # Fungsi fetch data dari Drizzle (getProducts)
│ └── schemas/ # Skema Zod (createProductSchema, dll.)
│
├── components/ # Komponen UI global / reusable
│ ├── ui/ # Komponen dasar (Button, Input, Modal - misal shadcn/ui)
│ └── form/ # Wrapper/field reusable untuk TanStack Form
│
├── lib/ # Utilitas & konfigurasi pihak ketiga
│ ├── utils.ts # Helper umum (format tanggal, mata uang, cn)
│ └── safe-action.ts # Wrapper Server Action (opsional, misal next-safe-action)
│
├── types/ # TypeScript global types/interfaces
└── env.ts # Validasi environment variables (menggunakan Zod)
Alasan & Praktik Terbaik untuk Stack Ini
• Pemisahan db/schema/: Memecah skema Drizzle ke dalam beberapa file (seperti users.ts dan products.ts) mencegah satu file membengkak hingga ribuan baris. File db/schema/index.ts bertugas menggabungkan semuanya agar relasi antar tabel tetap terbaca oleh Drizzle.
• Sinkronisasi Zod & Drizzle: Di dalam folder features/[nama-fitur]/schemas/, Anda bisa memanfaatkan paket drizzle-zod. Paket ini memungkinkan Anda membuat skema validasi Zod langsung dari definisi tabel Drizzle sehingga tidak perlu menulis ulang aturan tipe data.
• Integrasi TanStack Form & Server Actions: Letakkan komponen form (Client Component) di features/[nama-fitur]/components/. Gunakan skema Zod dari folder schemas/ untuk validasi client-side di TanStack Form, lalu kirim datanya ke fungsi di folder actions/ (Server Action) yang juga memvalidasi ulang data dengan skema Zod yang sama sebelum menyimpannya via Drizzle.
• Komponen Form Reusable (components/form/): TanStack Form sangat fleksibel namun cenderung verbose (banyak kode berulang). Buatlah komponen pembungkus seperti TextField.tsx atau SelectField.tsx di folder components/form/ untuk merangkum state error dan label input agar kode di dalam folder features/ tetap bersih. • Folder app/ yang Ramping: Usahakan file page.tsx di dalam app/ hanya bertugas mengambil data awal (memanggil fungsi dari queries/) dan merender komponen utama dari folder features/.
