# Rencana Pengembangan Website Profil Desa Suka Baru
### (Laravel + Admin Panel) — Dokumen Instruksi untuk AI Coding Agent

> Dokumen ini adalah instruksi kerja detail yang bisa langsung diikuti oleh AI coding agent (Antigravity) langkah demi langkah untuk membangun website profil desa dari nol sampai siap deploy.

---

## 1. Ringkasan Proyek

**Nama proyek:** Website Profil & Informasi Desa Suka Baru
**Lokasi:** Kecamatan Marga Sakti Sebelat, Kabupaten Bengkulu Utara, Provinsi Bengkulu
**Framework:** Laravel (versi terbaru, gunakan Laravel 11)
**Tujuan:** Website profil desa yang ringan (hosting murah/shared hosting sanggup jalankan), punya panel admin agar konten (berita, foto, potensi desa, data statistik) bisa diupdate sendiri oleh perangkat desa tanpa harus edit kode.

**Prinsip desain teknis (WAJIB dipatuhi agent):**
- Jangan pakai package yang berat / butuh resource besar. Hindari solusi yang butuh queue worker, redis, atau server terpisah kecuali benar-benar perlu.
- Struktur sederhana, tidak over-engineered. Ini bukan aplikasi kompleks — cukup CRUD + halaman statis dinamis.
- Semua gambar wajib dikompres/di-resize otomatis saat upload (lihat bagian optimasi).
- Desain: **biru + putih**, profesional, bukan warna-warni. Navigasi harus rapi dan jelas (lihat bagian 6).

---

## 2. Tech Stack

| Kebutuhan | Pilihan | Alasan |
|---|---|---|
| Backend | Laravel 11 | Standar, banyak dukungan hosting |
| Database | MySQL / MariaDB | Kompatibel semua shared hosting |
| Frontend styling | Tailwind CSS | Ringan, mudah kontrol warna biru-putih |
| Autentikasi admin | Laravel Breeze (Blade stack) | Paling ringan, tanpa Node SPA kompleks |
| Peta interaktif | Leaflet.js + OpenStreetMap | Gratis, tanpa API key, ringan (vs Google Maps yang butuh billing) |
| Upload & resize gambar | Intervention/Image | Kompres otomatis agar hosting tetap ringan |
| Editor konten berita | Trix Editor (bawaan Laravel) atau TipTap ringan | Cukup untuk isi berita, tidak perlu CKEditor berat |
| Hosting target | Shared hosting (cPanel) atau VPS kecil | Sesuai requirement "tidak berat untuk hosting" |

**Jangan gunakan** Filament/Nova/Livewire penuh untuk admin panel kecuali diminta lain — cukup Blade + Controller CRUD biasa agar ringan dan mudah dipelihara oleh siapa pun.

---

## 3. Struktur Menu Final Website

```
Beranda | Profil ▾ | Data Desa | Potensi | Peta Desa | Berita ▾ | Kontak
              ├─ Tentang Desa         ├─ Berita
              ├─ Kondisi Geografis    └─ Pengumuman
              └─ Pemerintahan
```

Menu **Profil** dan **Berita** memakai dropdown submenu. Galeri **tidak** jadi menu utama — ditampilkan sebagai section di halaman Beranda dan/atau Potensi (sesuai ketentuan).

---

## 4. Skema Database

### 4.1 Tabel `village_profiles` (data settingan umum desa, 1 baris saja / singleton)
| Kolom | Tipe | Keterangan |
|---|---|---|
| id | bigint | |
| nama_desa | string | "Desa Suka Baru" |
| kecamatan | string | "Marga Sakti Sebelat" |
| kabupaten | string | "Bengkulu Utara" |
| provinsi | string | "Bengkulu" |
| slogan | string | |
| foto_utama | string (path) | foto hero beranda |
| sambutan_kepala_desa | text | |
| foto_kepala_desa | string (path) | |
| sejarah_singkat | text | |
| asal_usul | text | |
| visi | text | |
| misi | text | |
| motto | string | |
| letak_geografis | text | |
| luas_wilayah | string | |
| ketinggian | string | |
| batas_wilayah | text | |
| kondisi_umum_wilayah | text | |
| timestamps | | |

### 4.2 Tabel `statistics` (statistik desa — dipakai di Beranda & Data Desa)
| Kolom | Tipe | Keterangan |
|---|---|---|
| id | bigint | |
| jumlah_penduduk | integer | |
| laki_laki | integer | |
| perempuan | integer | |
| jumlah_kk | integer | |
| jumlah_dusun | integer | |
| jumlah_rt | integer | |
| luas_wilayah_ha | decimal | |
| tingkat_pendidikan | text (json/deskripsi) | opsional, bisa disederhanakan jadi text |
| timestamps | | |

> Catatan penting: dokumen asal punya dua angka penduduk/KK berbeda (5.247 jiwa/1.542 KK di Beranda vs ±1.500 jiwa/333 KK di Data Desa, keduanya ditandai "Contoh"). **Agent harus pakai satu sumber data ini (tabel `statistics`) untuk kedua halaman**, sehingga tidak ada data ganda yang bisa berbeda. Nilai aslinya nanti diisi admin lewat panel admin.

### 4.3 Tabel `officials` (perangkat desa)
| Kolom | Tipe | Keterangan |
|---|---|---|
| id | bigint | |
| nama | string | |
| jabatan | string | Kepala Desa, Sekretaris Desa, Kasi Pemerintahan, Kasi Sosial, Kasi Pelayanan, Kaur Umum, Kaur Perencanaan, Kaur Keuangan |
| foto | string (path, nullable) | |
| urutan | integer | untuk sorting tampilan |
| timestamps | | |

### 4.4 Tabel `potentials` (potensi desa — kartu-kartu)
| Kolom | Tipe | Keterangan |
|---|---|---|
| id | bigint | |
| kategori | enum | pertanian, perkebunan, umkm, pariwisata, peternakan |
| nama | string | |
| deskripsi | text | |
| foto | string (path) | |
| lokasi | string, nullable | |
| timestamps | | |

### 4.5 Tabel `posts` (berita & pengumuman jadi satu tabel, dibedakan kolom `tipe`)
| Kolom | Tipe | Keterangan |
|---|---|---|
| id | bigint | |
| tipe | enum | berita, pengumuman |
| judul | string | |
| slug | string, unique | |
| foto | string (path) | |
| isi | text (long) | |
| tanggal | date | |
| penulis | string, nullable | |
| timestamps | | |

### 4.6 Tabel `galleries`
| Kolom | Tipe | Keterangan |
|---|---|---|
| id | bigint | |
| kategori | enum | kegiatan_desa, masyarakat, alam_lingkungan, potensi_desa, pemerintahan, wisata |
| judul | string, nullable | |
| foto | string (path) | |
| timestamps | | |

### 4.7 Tabel `map_points` (titik-titik Peta Desa)
| Kolom | Tipe | Keterangan |
|---|---|---|
| id | bigint | |
| nama | string | |
| jenis | enum | batas_desa, dusun, kantor_desa, jalan_utama, fasilitas_umum, objek_wisata |
| deskripsi | text, nullable | |
| latitude | decimal(10,7) | |
| longitude | decimal(10,7) | |
| icon | string, nullable | nama icon untuk marker |
| timestamps | | |

### 4.8 Tabel `contacts` (singleton, info kontak)
| Kolom | Tipe | Keterangan |
|---|---|---|
| id | bigint | |
| nama_kantor | string | |
| alamat | text | |
| telepon | string | |
| whatsapp | string | |
| email | string | |
| jam_pelayanan | string | |
| latitude | decimal(10,7) | untuk tombol "Lihat Lokasi di Maps" |
| longitude | decimal(10,7) | |
| timestamps | | |

### 4.9 Tabel `users` (admin — bawaan Laravel, tambah kolom `role` jika perlu multi-admin nanti)

---

## 5. Struktur Folder Project (ringkas)

```
app/
  Http/
    Controllers/
      Admin/
        DashboardController.php
        VillageProfileController.php
        StatisticController.php
        OfficialController.php
        PotentialController.php
        PostController.php
        GalleryController.php
        MapPointController.php
        ContactController.php
      Public/
        HomeController.php
        ProfileController.php
        DataController.php
        PotentialController.php
        MapController.php
        PostController.php
        ContactController.php
  Models/
    VillageProfile.php
    Statistic.php
    Official.php
    Potential.php
    Post.php
    Gallery.php
    MapPoint.php
    Contact.php
resources/
  views/
    layouts/
      app.blade.php        (layout publik)
      admin.blade.php      (layout admin)
    partials/
      navbar.blade.php
      footer.blade.php
      admin-sidebar.blade.php
    public/
      home.blade.php
      profile/tentang.blade.php
      profile/geografis.blade.php
      profile/pemerintahan.blade.php
      data-desa.blade.php
      potensi.blade.php
      peta.blade.php
      berita/index.blade.php
      berita/show.blade.php
      pengumuman/index.blade.php
      kontak.blade.php
    admin/
      dashboard.blade.php
      village-profile/edit.blade.php
      statistics/edit.blade.php
      officials/index.blade.php + form.blade.php
      potentials/index.blade.php + form.blade.php
      posts/index.blade.php + form.blade.php
      galleries/index.blade.php + form.blade.php
      map-points/index.blade.php + form.blade.php
      contact/edit.blade.php
routes/
  web.php       (route publik)
  admin.php     (route admin, di-include di web.php dengan prefix/middleware)
```

---

## 6. Panduan Desain (WAJIB diikuti persis)

- **Palet warna:**
  - Primary: Biru tua `#1E3A8A` (untuk navbar, tombol utama, heading penting)
  - Secondary: Biru cerah `#2563EB` (hover state, aksen, link aktif)
  - Background: Putih `#FFFFFF` dan abu sangat muda `#F8FAFC` untuk selang-seling section
  - Teks: Abu gelap `#1E293B` (bukan hitam pekat, biar lebih profesional)
  - **Tidak ada warna lain** (tanpa merah, hijau, kuning mencolok) kecuali warna status kecil di admin panel (misal badge error/sukses).
- **Tipografi:** Satu font sans-serif profesional (misal `Inter` atau `Poppins` dari Google Fonts), maksimal 2 ukuran heading + 1 body.
- **Navigasi (navbar):**
  - Sticky di atas (tetap terlihat saat scroll).
  - Logo/nama desa di kiri, menu di kanan, rata sejajar.
  - Menu aktif diberi garis bawah/warna biru cerah agar user tahu sedang di halaman mana.
  - Dropdown submenu (Profil, Berita) muncul on-hover di desktop, on-click accordion di mobile.
  - Mobile: hamburger menu dengan slide-in panel, tetap rapi (bukan menu numpuk).
  - Footer sederhana: info kontak singkat, jam pelayanan, link menu, hak cipta.
- **Kartu (card) untuk Potensi, Berita, Galeri:** shadow tipis, sudut membulat (rounded-lg), foto rasio konsisten (misal 4:3), spacing konsisten antar kartu (grid gap rapi).
- **Halaman harus responsive** — mobile-first, cek di breakpoint 375px, 768px, 1280px.

---

## 7. LANGKAH-LANGKAH IMPLEMENTASI

Ikuti fase secara berurutan. Setiap fase harus selesai dan bisa di-test sebelum lanjut ke fase berikutnya.

### FASE 0 — Persiapan & Instalasi Project

1. Buat project Laravel baru:
   ```bash
   composer create-project laravel/laravel website-desa-suka-baru
   cd website-desa-suka-baru
   ```
2. Setup file `.env`: konfigurasi `DB_DATABASE`, `DB_USERNAME`, `DB_PASSWORD` sesuai MySQL lokal.
3. Install Tailwind CSS (via Laravel Vite plugin default sudah cukup, tinggal konfigurasi):
   ```bash
   npm install
   npm install -D tailwindcss postcss autoprefixer
   npx tailwindcss init -p
   ```
4. Set warna kustom di `tailwind.config.js`:
   ```js
   theme: {
     extend: {
       colors: {
         primary: '#1E3A8A',
         secondary: '#2563EB',
         'bg-soft': '#F8FAFC',
         'text-main': '#1E293B',
       },
       fontFamily: {
         sans: ['Inter', 'sans-serif'],
       },
     },
   },
   ```
5. Install Laravel Breeze (Blade stack) untuk sistem login admin:
   ```bash
   composer require laravel/breeze --dev
   php artisan breeze:install blade
   npm install && npm run build
   ```
6. Install package untuk resize/kompres gambar otomatis:
   ```bash
   composer require intervention/image
   ```
7. Jalankan `php artisan serve` dan pastikan halaman default Breeze tampil tanpa error sebelum lanjut.

### FASE 1 — Database: Migration

1. Buat semua migration sesuai skema di Bagian 4:
   ```bash
   php artisan make:model VillageProfile -m
   php artisan make:model Statistic -m
   php artisan make:model Official -m
   php artisan make:model Potential -m
   php artisan make:model Post -m
   php artisan make:model Gallery -m
   php artisan make:model MapPoint -m
   php artisan make:model Contact -m
   ```
2. Isi masing-masing file migration sesuai tabel kolom yang sudah ditentukan di Bagian 4 (gunakan tipe data yang sesuai, tambahkan `nullable()` untuk kolom yang boleh kosong).
3. Tambahkan kolom `role` (string, default `admin`) ke migration `users` bawaan jika ingin siapkan multi-admin di masa depan (opsional, boleh dilewati untuk versi awal).
4. Jalankan migration:
   ```bash
   php artisan migrate
   ```
5. Buat seeder untuk data awal desa (`VillageProfileSeeder`, `StatisticSeeder`, `OfficialSeeder`, `ContactSeeder`) diisi dengan data dari dokumen ketentuan (nama desa, kecamatan, kepala desa Edi Putra Jaya, sekretaris desa Saputra, dst). Ini supaya website tidak kosong saat pertama kali dibuka.
6. Jalankan:
   ```bash
   php artisan db:seed
   ```

### FASE 2 — Models & Relasi

1. Definisikan `$fillable` di setiap model sesuai kolom masing-masing tabel.
2. Untuk `VillageProfile` dan `Contact`, buat pola **singleton** — tambahkan method static `current()` yang mengambil baris pertama (`firstOrCreate([], [...default])`) supaya di controller cukup panggil `VillageProfile::current()`.
3. Tambahkan accessor pada model `Post`, `Potential`, `Gallery`, `Official` untuk URL foto lengkap (misal `getFotoUrlAttribute()` yang mengembalikan `Storage::url($this->foto)`).
4. Tambahkan scope pada `Post`: `scopeBerita($q)` dan `scopePengumuman($q)` untuk filter berdasarkan kolom `tipe`.

### FASE 3 — Autentikasi Admin

1. Breeze sudah menyediakan login/register/logout. **Nonaktifkan register publik** (hapus link & route register) — admin hanya dibuat manual lewat `php artisan tinker` atau seeder, jangan sampai sembarang orang bisa daftar jadi admin.
2. Buat middleware `EnsureUserIsAdmin` (atau pakai role check sederhana) untuk melindungi semua route `/admin/*`.
3. Buat 1 akun admin default lewat seeder `AdminUserSeeder` (email & password sementara, wajib diganti setelah instalasi pertama).
4. Test: buka `/admin`, pastikan redirect ke login jika belum auth, dan bisa masuk dashboard setelah login.

### FASE 4 — Admin Panel (CRUD)

Untuk **setiap modul** di bawah ini, buat: Controller (resource), route (resource, prefix `admin`, middleware admin), view index (tabel list + tombol tambah/edit/hapus), view form (create & edit, boleh 1 file dipakai bareng).

1. **Dashboard admin** — ringkasan jumlah berita, potensi, galeri, dan shortcut ke tiap modul.
2. **Profil Desa** (form edit, bukan CRUD list karena singleton) — semua field dari tabel `village_profiles`.
3. **Statistik** (form edit, singleton) — semua field dari tabel `statistics`.
4. **Perangkat Desa** (`officials`) — CRUD penuh + upload foto + drag-order atau input `urutan` manual.
5. **Potensi Desa** (`potentials`) — CRUD penuh, field kategori pakai dropdown (pertanian/perkebunan/umkm/pariwisata/peternakan), upload foto.
6. **Berita & Pengumuman** (`posts`) — CRUD penuh, field `tipe` pakai radio/dropdown (berita/pengumuman), editor teks untuk `isi` (pakai Trix), upload foto, auto-generate `slug` dari judul.
7. **Galeri** (`galleries`) — CRUD, upload foto (bisa multi-upload sekaligus), dropdown kategori.
8. **Peta Desa** (`map_points`) — CRUD titik peta: input nama, jenis (dropdown), latitude/longitude (sediakan mini-map Leaflet di form admin supaya admin bisa klik untuk ambil koordinat, bukan input manual angka yang membingungkan).
9. **Kontak** (form edit, singleton) — semua field tabel `contacts`, termasuk klik-pilih lokasi di mini-map untuk ambil lat/long.

**Setiap upload foto WAJIB melalui proses berikut (pakai Intervention/Image):**
- Resize maksimal lebar 1200px (jaga rasio).
- Kompres kualitas ~75-80%.
- Simpan ke `storage/app/public/...` lalu pastikan `php artisan storage:link` sudah dijalankan.

### FASE 5 — Halaman Publik (Frontend)

Bangun tiap halaman sesuai isi dokumen ketentuan, ambil data dari database (bukan hardcode):

1. **Beranda** (`/`)
   - Foto utama desa (hero, full-width)
   - Nama desa, kecamatan & kabupaten
   - Slogan desa
   - Sambutan singkat kepala desa (potong teks + link "selengkapnya" ke halaman Profil jika panjang)
   - Statistik singkat (ambil dari tabel `statistics`, tampilkan sebagai 4-5 angka besar dengan label)
   - Potensi unggulan (ambil 3-4 data teratas dari `potentials`)
   - Berita terbaru (ambil 3 `posts` tipe berita terbaru)
   - Tombol CTA menuju halaman Peta Desa
   - (Opsional sesuai ketentuan) section galeri singkat di bagian bawah

2. **Profil Desa** — 3 sub-halaman (bisa 1 halaman dengan tab, atau 3 route terpisah — pilih 3 route terpisah agar SEO lebih baik dan sesuai submenu dropdown):
   - `/profil/tentang` — sejarah singkat, asal-usul, visi & misi, motto
   - `/profil/geografis` — letak desa, luas wilayah, ketinggian, batas wilayah, kondisi umum wilayah
   - `/profil/pemerintahan` — daftar perangkat desa (Kepala Desa Edi Putra Jaya, Sekretaris Desa Saputra, Kasi Pemerintahan, Kasi Sosial, Kasi Pelayanan, Kaur Umum, Kaur Perencanaan, Kaur Keuangan) + foto struktur organisasi jika ada

3. **Data Desa** (`/data-desa`)
   - Dashboard statistik sederhana: kartu-kartu angka (jumlah penduduk, laki-laki, perempuan, jumlah KK, jumlah dusun, jumlah RT, luas wilayah)
   - Section data sosial-ekonomi (mata pencaharian, tingkat pendidikan, potensi ekonomi) — boleh tampil sebagai teks terstruktur atau chart sederhana pakai Chart.js (ringan, CDN, tanpa build tambahan)

4. **Potensi Desa** (`/potensi`)
   - Grid kartu potensi, filter berdasarkan kategori (Pertanian, Perkebunan/Kehutanan, UMKM, Pariwisata, Peternakan/Perikanan)
   - Setiap kartu: foto, nama, deskripsi singkat, lokasi (jika ada) → klik untuk detail

5. **Peta Desa** (`/peta`)
   - Embed peta Leaflet full-width, load semua `map_points` sebagai marker dengan icon berbeda per `jenis`
   - Klik marker menampilkan popup: nama, jenis, deskripsi singkat
   - Fitur zoom & geser bawaan Leaflet — tidak perlu bangun GIS custom

6. **Berita** (`/berita`) & **Pengumuman** (`/pengumuman`)
   - List card: foto + judul + tanggal + ringkasan isi (excerpt), pagination
   - Halaman detail (`/berita/{slug}`): foto, judul, tanggal, isi lengkap

7. **Galeri** — ditempatkan sebagai section di Beranda dan/atau halaman Potensi (sesuai ketentuan, bukan menu utama terpisah). Tampilkan grid foto dengan filter kategori + lightbox saat foto diklik (pakai library ringan seperti `GLightbox` via CDN).

8. **Kontak** (`/kontak`)
   - Nama kantor desa, alamat lengkap, nomor telepon, WhatsApp (bikin jadi link `wa.me/`), email, jam pelayanan
   - Tombol "Lihat Lokasi di Maps" → buka Google Maps via link koordinat (`https://www.google.com/maps?q=lat,long`), tidak perlu embed Google Maps API (hemat biaya & load)
   - Peta kecil Leaflet menampilkan lokasi kantor desa

### FASE 6 — Layout, Navbar, Footer

1. Buat `layouts/app.blade.php` sebagai layout utama halaman publik: include navbar, `@yield('content')`/slot, footer, meta tags SEO dasar (title dinamis per halaman, meta description).
2. Buat `partials/navbar.blade.php` sesuai spesifikasi Bagian 6 (sticky, dropdown, responsive hamburger).
3. Buat `partials/footer.blade.php`: info kontak singkat (ambil dari tabel `contacts`), link menu, copyright otomatis tahun berjalan.
4. Buat `layouts/admin.blade.php` terpisah: sidebar menu admin (Dashboard, Profil Desa, Statistik, Perangkat Desa, Potensi, Berita, Pengumuman, Galeri, Peta, Kontak, Logout), tetap pakai palet biru-putih yang sama tapi versi lebih fungsional (tabel, form).

### FASE 7 — Peta Desa (Leaflet Setup)

1. Load Leaflet via CDN di layout (CSS + JS), tidak perlu install via npm agar ringan:
   ```html
   <link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
   <script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
   ```
2. Buat partial `map.blade.php` yang bisa dipakai ulang di halaman Peta Desa maupun halaman Kontak (parameter: center lat/long, zoom, daftar marker).
3. Set center peta default ke koordinat Desa Suka Baru / Kecamatan Marga Sakti Sebelat (agent perlu cari/estimasi koordinat area ini, atau kosongkan dan minta admin isi via panel admin).
4. Icon marker dibedakan warna/bentuk sederhana per `jenis` (misal: kantor desa = biru tua, objek wisata = biru cerah, fasilitas umum = abu-abu) — tetap dalam palet biru-putih, jangan pakai warna-warni.

### FASE 8 — Optimasi Performa (penting untuk hosting ringan)

1. Semua gambar upload wajib lewat proses resize+kompres (Fase 4).
2. Gunakan lazy-loading (`loading="lazy"`) pada semua tag `<img>` di halaman publik kecuali hero image.
3. Compile & minify asset produksi:
   ```bash
   npm run build
   ```
4. Aktifkan cache Laravel sebelum deploy:
   ```bash
   php artisan config:cache
   php artisan route:cache
   php artisan view:cache
   ```
5. Pastikan query list (berita, potensi, galeri) pakai pagination, jangan load semua data sekaligus.
6. Index kolom yang sering di-filter/sort (`tipe`, `kategori`, `tanggal`, `slug`) di migration.

### FASE 9 — Testing & QA

1. Cek semua halaman publik tampil benar di 3 breakpoint (mobile, tablet, desktop).
2. Cek semua form admin: validasi input wajib (nama, judul tidak boleh kosong; foto format jpg/png/webp max ukuran tertentu misal 2MB sebelum dikompres).
3. Cek alur CRUD lengkap tiap modul admin: tambah → tampil di publik → edit → hapus → hilang dari publik.
4. Cek route `/admin/*` benar-benar terkunci tanpa login.
5. Cek semua link WhatsApp, email, dan tombol Maps berfungsi dan membuka tujuan yang benar.
6. Cek broken image / placeholder default jika field foto masih kosong (jangan biarkan tampil ikon rusak).

### FASE 10 — Deployment

1. Siapkan `.env` production: `APP_ENV=production`, `APP_DEBUG=false`, isi kredensial database hosting.
2. Upload project ke hosting (shared hosting: upload isi folder `public/` sebagai document root, sisanya di luar `public_html`; atau ikuti panduan hosting spesifik untuk Laravel).
3. Jalankan di server:
   ```bash
   composer install --optimize-autoloader --no-dev
   php artisan migrate --force
   php artisan storage:link
   php artisan config:cache
   ```
4. Setup cron job jika nanti butuh scheduler (untuk versi awal ini kemungkinan belum perlu).
5. Test seluruh checklist Fase 9 ulang di environment production.
6. Ganti password admin default segera setelah deploy.

---

## 8. Checklist Akhir Sebelum Serah Terima

- [ ] Semua 7 menu utama (Beranda, Profil, Data Desa, Potensi, Peta Desa, Berita, Kontak) berfungsi dan berisi data asli desa (bukan lorem ipsum)
- [ ] Panel admin bisa login dan mengelola: Profil Desa, Statistik, Perangkat Desa, Potensi, Berita, Pengumuman, Galeri, Peta, Kontak
- [ ] Warna konsisten biru-putih di semua halaman (publik & admin)
- [ ] Navigasi rapi & responsive, dropdown submenu berjalan baik di desktop & mobile
- [ ] Semua foto ter-kompres otomatis saat upload
- [ ] Peta desa menampilkan titik-titik sesuai ketentuan (batas desa, dusun, kantor desa, jalan utama, fasilitas umum, objek wisata) dan bisa zoom/geser/klik
- [ ] Halaman kontak punya tombol WhatsApp aktif dan tombol "Lihat Lokasi di Maps"
- [ ] Password admin default sudah diganti
- [ ] Cache production sudah dijalankan, `APP_DEBUG=false`

---

## 9. Catatan Data yang Perlu Dilengkapi Klien (perangkat desa)

Data berikut di dokumen sumber masih kosong/tidak lengkap dan perlu dikonfirmasi sebelum go-live (isi lewat panel admin, jangan di-hardcode di kode):

- Foto perangkat desa: Sekretaris Desa (Saputra) dan Kasi Sosial belum ada nama/foto lengkap di dokumen sumber
- Batas wilayah lengkap arah utara, selatan, timur, barat belum tersedia
- Ketinggian dan luas wilayah desa (angka pasti) belum tercantum
- **Data penduduk berbeda antara Beranda (5.247 jiwa / 1.542 KK) dan Data Desa (±1.500 jiwa / 333 KK)** — keduanya ditandai "Contoh" di dokumen asal. Perlu satu angka final dari klien, karena di sistem ini hanya ada satu sumber data (tabel `statistics`) yang dipakai di kedua halaman
- Foto struktur organisasi pemerintahan
- Data UMKM (produk unggulan) belum dirinci
- Koordinat pasti kantor desa dan titik-titik peta lainnya

