Struktur Folder Best Practice untuk Next.js App Router

Dokumentasi ini menjelaskan struktur folder yang umum dipakai di industri untuk project Next.js App Router, termasuk penempatan Prisma, komponen, dan pemisahan Server/Client Component.


Struktur Folder yang Direkomendasikan

nama-project/
├── app/                          # Routing & halaman (App Router)
│   ├── (auth)/                   # Route group — tidak muncul di URL
│   │   ├── login/
│   │   │   └── page.tsx
│   │   └── register/
│   │       └── page.tsx
│   ├── (dashboard)/
│   │   ├── users/
│   │   │   ├── page.tsx          # /users
│   │   │   ├── loading.tsx
│   │   │   └── error.tsx
│   │   └── roles/
│   │       └── page.tsx          # /roles
│   ├── api/                      # API Routes (kalau perlu endpoint REST)
│   │   └── users/
│   │       └── route.ts
│   ├── generated/                # Hasil generate Prisma Client
│   │   └── prisma/
│   ├── layout.tsx                # Root layout
│   ├── globals.css
│   └── page.tsx                  # Homepage (/)
│
├── components/                   # Semua komponen React yang reusable
│   ├── ui/                       # Komponen kecil generik (Button, Input, Card)
│   │   ├── Button.tsx
│   │   └── Card.tsx
│   └── features/                 # Komponen spesifik per fitur
│       ├── users/
│       │   └── UserTable.tsx
│       └── roles/
│           └── RoleTable.tsx
│
├── lib/                          # Utilitas, koneksi eksternal
│   ├── prisma.ts                 # Singleton Prisma Client
│   ├── auth.ts                   # Helper autentikasi
│   └── utils.ts                  # Helper umum (format tanggal, dll)
│
├── types/                        # TypeScript types/interfaces custom
│   └── index.ts
│
├── hooks/                        # Custom React Hooks
│   └── useDebounce.ts
│
├── prisma/
│   ├── schema.prisma
│   └── migrations/
│
├── public/                       # Asset statis (gambar, favicon)
│
├── .env
├── next.config.js
├── tsconfig.json
└── package.json

Penjelasan Tiap Bagian

1. app/ — Khusus Routing

Prinsip penting: app/ sebaiknya cuma isi halaman & routing, bukan tempat menumpuk semua logic. Kalau satu page.tsx mulai panjang dan campur banyak hal (fetch data + tabel + form + tombol), pecah komponennya keluar ke components/.

Contoh yang tadinya terlalu panjang:

// app/roles/page.tsx — semua nempel di sini
export default async function RolesPage() {
  const roles = await prisma.role.findMany({ include: {...} })
  return (
    <div>
      {/* 50 baris JSX tabel di sini */}
    </div>
  )
}

Jadi lebih rapi begini:

// app/roles/page.tsx
import { prisma } from '@/lib/prisma'
import RoleTable from '@/components/features/roles/RoleTable'

export default async function RolesPage() {
  const roles = await prisma.role.findMany({
    include: { rolecat: true, appmenunew: true },
  })
  return <RoleTable roles={roles} />
}
// components/features/roles/RoleTable.tsx
export default function RoleTable({ roles }) {
  return (
    <table>
      {roles.map((role) => (
        <tr key={role.idrole}>{/* ... */}</tr>
      ))}
    </table>
  )
}

Page-nya jadi tipis — cuma tanggung jawab ambil data + kirim ke komponen tampilan. Ini bikin kode gampang dibaca dan gampang di-test.

2. Route Groups (nama) — Mengelompokkan Tanpa Mempengaruhi URL

Folder dengan kurung seperti (auth) atau (dashboard) tidak muncul di URL, cuma untuk pengelompokan visual di kode:

  • app/(dashboard)/users/page.tsx → tetap jadi /users, bukan /dashboard/users

Berguna kalau ada banyak halaman dan mau dikelompokkan berdasarkan layout atau fitur, tanpa mengubah struktur URL.

3. components/ui/ vs components/features/

  • ui/ → komponen kecil, generik, dipakai berulang di banyak tempat (Button, Modal, Input)
  • features/ → komponen yang spesifik untuk satu fitur/domain tertentu (UserTable cuma dipakai di halaman user)

4. lib/ — Semua yang Berhubungan dengan Koneksi/Utilitas Eksternal

Prisma client, koneksi API eksternal, helper autentikasi — semua yang "menghubungkan" aplikasi ke dunia luar ditaruh di sini.

5. Client Component Dipisah dari Server Component

components/features/docscat/
├── DocsCatList.tsx      ← Server Component (fetch data)
└── Counter.tsx          ← Client Component ('use client')

Penamaan File — Konvensi Umum

Jenis Konvensi Contoh
Komponen React PascalCase UserTable.tsx, Counter.tsx
Halaman/routing lowercase (fixed oleh Next.js) page.tsx, layout.tsx
Utilitas/hooks camelCase useDebounce.ts, formatDate.ts
Folder route kebab-case app/user-profile/page.tsx

Soal src/ — Perlu atau Tidak?

Ini valid, cuma pilihan gaya:

Tanpa src/ Dengan src/
app/, lib/, components/ langsung di root Semua masuk src/app/, src/lib/, dll
File config (next.config.js, .env) campur sama folder kode File config lebih terpisah jelas dari kode aplikasi

Tidak ada yang "lebih benar" — cuma soal preferensi kebersihan project. Untuk project baru dengan banyak file config custom, src/ sering direkomendasikan biar root folder tidak berantakan.


Prinsip Utama yang Perlu Diingat

  1. Jangan taruh semua logic di page.tsx — pecah ke komponen
  2. Pisahkan Server Component dan Client Component secara eksplisit per file
  3. Group berdasarkan fitur, bukan berdasarkan tipe file semata (kecuali components/ui)
  4. lib/ untuk semua koneksi eksternal, biar gampang di-mock kalau nanti butuh testing