import React, { useState, useEffect, useRef } from 'react'; import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout'; import { Head } from '@inertiajs/react'; const NAV = [ { id: 'intro', label: 'Pendahuluan', icon: }, { id: 'quickstart', label: 'Quick Start', icon: }, { id: 'stack', label: 'Tech Stack', icon: }, { id: 'auth', label: 'Autentikasi', icon: }, { id: 'roles', label: 'Roles & Permission', icon: }, { id: 'features', label: 'Fitur Lengkap', icon: }, { id: 'api', label: 'REST API', icon: }, { id: '2fa', label: 'Two-Factor Auth', icon: }, { id: 'settings', label: 'System Settings', icon: }, { id: 'structure', label: 'Struktur Folder', icon: }, ]; function Badge({ children, color = 'gray' }: { children: React.ReactNode; color?: string }) { const colors: Record = { green: 'bg-emerald-50 text-emerald-700 border border-emerald-200', blue: 'bg-blue-50 text-blue-700 border border-blue-200', amber: 'bg-amber-50 text-amber-700 border border-amber-200', red: 'bg-red-50 text-red-700 border border-red-200', gray: 'bg-gray-50 text-gray-600 border border-gray-200', purple: 'bg-purple-50 text-purple-700 border border-purple-200', }; return ( {children} ); } function CodeBlock({ children, lang = 'bash' }: { children: string; lang?: string }) { const [copied, setCopied] = useState(false); const copy = () => { navigator.clipboard.writeText(children); setCopied(true); setTimeout(() => setCopied(false), 2000); }; return (
{lang}
                {children}
            
); } function SectionHeader({ id, title, badge, badgeColor }: { id: string; title: string; badge?: string; badgeColor?: string }) { return (

{title}

{badge && {badge}}
); } function Endpoint({ method, path, desc, auth = true }: { method: string; path: string; desc: string; auth?: boolean }) { const methodColor: Record = { GET: 'bg-blue-100 text-blue-700', POST: 'bg-emerald-100 text-emerald-700', PATCH: 'bg-amber-100 text-amber-700', DELETE: 'bg-red-100 text-red-700', PUT: 'bg-purple-100 text-purple-700', }; return (
{method} {path} {desc} {auth && 🔒 Auth}
); } export default function DocsIndex() { const [activeSection, setActiveSection] = useState('intro'); const contentRef = useRef(null); useEffect(() => { const ids = NAV.map(n => n.id); const observer = new IntersectionObserver( (entries) => { const visible = entries .filter(e => e.isIntersecting) .sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top); if (visible.length > 0) setActiveSection(visible[0].target.id); }, { rootMargin: '-20% 0px -70% 0px', threshold: 0 } ); ids.forEach(id => { const el = document.getElementById(id); if (el) observer.observe(el); }); return () => observer.disconnect(); }, []); const scrollTo = (id: string) => { document.getElementById(id)?.scrollIntoView({ behavior: 'smooth', block: 'start' }); }; return (

Dokumentasi

Panduan lengkap biiproject kit v2

v2.0
{/* Sticky Sidebar Nav */} {/* Content */}
{/* ── PENDAHULUAN ── */}

biiproject kit v2 adalah starter kit enterprise berbasis Laravel 13 + React (Inertia.js) yang dirancang untuk mempercepat pembangunan aplikasi web dengan fitur manajemen pengguna, hak akses berbasis peran, monitoring aktivitas, notifikasi, dan konfigurasi sistem yang lengkap.

{[ { label: 'Users & Roles', icon: '👥' }, { label: 'Activity Logs', icon: '📋' }, { label: 'System Settings', icon: '⚙️' }, { label: 'Two-Factor Auth', icon: '🔒' }, { label: 'REST API v1', icon: '🔌' }, { label: 'Dark Mode', icon: '🌙' }, { label: 'Notifikasi', icon: '🔔' }, { label: 'Mobile Ready', icon: '📱' }, ].map(f => (
{f.icon}
{f.label}
))}
{/* ── QUICK START ── */}

1. Clone & Install

{`git clone https://github.com/your-org/biiskit.git cd biiskit composer install npm install`}

2. Konfigurasi Environment

{`cp .env.example .env php artisan key:generate # Edit .env sesuai konfigurasi database DB_CONNECTION=pgsql DB_HOST=127.0.0.1 DB_PORT=5432 DB_DATABASE=biiskit DB_USERNAME=your_user DB_PASSWORD=your_password`}

3. Migrasi & Seeder

{`php artisan migrate --seed`}

Seeder akan membuat 3 akun default: superadmin, admin, dan user.

4. Jalankan Server

{`# Terminal 1 — Laravel php artisan serve # Terminal 2 — Vite dev server npm run dev`}

Akses aplikasi di http://localhost:8000 — redirect otomatis ke halaman login.

{/* ── TECH STACK ── */}
{[ { layer: 'Backend', items: ['Laravel 13', 'PHP 8.3', 'PostgreSQL', 'Laravel Sanctum', 'Spatie Permission', 'Spatie Activity Log'] }, { layer: 'Frontend', items: ['React 18', 'Inertia.js v2', 'TypeScript', 'Tailwind CSS v4', 'Vite 6', 'Chart.js'] }, { layer: 'Keamanan', items: ['RBAC (Role-Based Access Control)', 'Two-Factor Auth (TOTP)', 'Sanctum API Tokens', 'Gate::before super-admin bypass', 'Bcrypt Password Hashing'] }, { layer: 'DevOps', items: ['PostgreSQL + Redis (Docker ready)', 'Laravel Queue (database)', 'Cache: database driver', 'Pest PHP testing suite'] }, ].map(s => (
{s.layer}
{s.items.map(i => (
{i}
))}
))}
{/* ── AUTENTIKASI ── */}

Akun Bawaan (Seeder)

{[ { email: 'superadmin@biiskit.com', pw: 'password', role: 'super-admin', color: 'red' }, { email: 'admin@biiskit.com', pw: 'password', role: 'admin', color: 'amber' }, { email: 'user@biiskit.com', pw: 'password', role: 'user', color: 'blue' }, ].map(u => ( ))}
Email Password Role
{u.email} {u.pw} {u.role}

Alur Login Web

{['Form Login', '→', 'Auth Check', '→', '2FA Challenge?', '→', 'Email Verified?', '→', 'Dashboard'].map((s, i) => ( {s} ))}

2FA Challenge hanya muncul jika user telah mengaktifkan Two-Factor Auth di /settings#2fa.

Login via API

{`POST /api/v1/login Content-Type: application/json { "email": "admin@biiskit.com", "password": "password" } // Response { "token": "1|abc123...", "user": { "id": 1, "email": "admin@biiskit.com", ... } }`}
{/* ── ROLES & PERMISSIONS ── */}

Menggunakan spatie/laravel-permission. Role super-admin mendapat akses penuh via Gate::before bypass — tidak perlu assign permission satu per satu.

{[ { perm: 'user.view', u: true, a: true, s: true }, { perm: 'user.create', u: false, a: true, s: true }, { perm: 'user.edit', u: false, a: true, s: true }, { perm: 'user.delete', u: false, a: true, s: true }, { perm: 'user.restore', u: false, a: true, s: true }, { perm: 'user.force-delete', u: false, a: false, s: true }, { perm: 'user.export', u: false, a: true, s: true }, { perm: 'user.import', u: false, a: true, s: true }, { perm: 'role.view', u: false, a: true, s: true }, { perm: 'role.create', u: false, a: true, s: true }, { perm: 'role.delete', u: false, a: true, s: true }, { perm: 'role.manage', u: false, a: true, s: true }, { perm: 'notifications.view', u: false, a: true, s: true }, { perm: 'notifications.send', u: false, a: true, s: true }, { perm: 'activity-logs.view', u: false, a: true, s: true }, { perm: 'activity-logs.delete', u: false, a: false, s: true }, { perm: 'settings.view', u: false, a: false, s: true }, { perm: 'settings.edit', u: false, a: false, s: true }, { perm: 'settings.test-email', u: false, a: false, s: true }, { perm: 'documentation.view', u: false, a: false, s: true }, ].map(row => ( {[row.u, row.a, row.s].map((v, i) => ( ))} ))}
Permission user admin super-admin
{row.perm} {v ? : }

Pengecekan Permission di Controller

{`// Via Policy (model instance) $this->authorize('update', $user); // Via Gate string (tanpa model) $this->authorize('user.delete'); // Via Blade / React (shared props) // auth.permissions = ['user.view', 'user.create', ...]`}
{/* ── FITUR LENGKAP ── */}
{[ { title: 'Manajemen Pengguna', icon: '👥', items: [ 'CRUD lengkap (tambah, edit, hapus, restore)', 'Soft delete dengan arsip & purge permanen', 'Bulk archive / restore / force-delete', 'Filter by status, role, pencarian nama/email', 'Sorting multi-kolom + pagination', 'Export ke Excel (.xlsx)', 'Import user massal via Excel/CSV', 'Assign multi-role per user', ], }, { title: 'Roles & Permission Manager', icon: '🛡️', items: [ 'Kelola role dari UI (tambah / hapus role)', 'Assign/revoke permission per role via toggle', 'Super-admin bypass via Gate::before', '3 role default: super-admin, admin, user', ], }, { title: 'Notifikasi', icon: '🔔', items: [ 'Kirim notifikasi (email / in-app)', 'Target: all users, role tertentu, atau user spesifik', 'Log pengiriman dengan status (sent/failed)', 'Badge counter di topbar (unread last 7 hari)', 'Pagination history notifikasi', ], }, { title: 'Activity Logs', icon: '📋', items: [ 'Log otomatis via spatie/laravel-activitylog', 'Filter by user, event, tanggal', 'Bulk delete logs', 'Tampilan subject & properties berubah', ], }, { title: 'Dashboard', icon: '📊', items: [ 'Statistik total users, admin, active, inactive', 'Chart pendaftaran user 30 hari terakhir (Chart.js)', 'Tabel aktivitas terbaru', 'Quick actions (tambah user, lihat logs)', ], }, { title: 'Account Settings', icon: '👤', items: [ 'Tab Profile: nama, email, telepon, bio, avatar upload', 'Tab Security & Password: ganti password', 'Tab Two-Factor Auth: aktifkan/nonaktifkan TOTP 2FA', 'Tab Danger Zone: hapus akun permanen', 'Tab aktif persisten saat reload (via URL hash)', ], }, { title: 'UI/UX', icon: '🎨', items: [ 'Dark mode toggle (persisted di localStorage)', 'Sidebar responsif + burger menu mobile', 'Breadcrumb dinamis di topbar', 'Flash messages (success / error)', 'Animasi masuk halaman (anim-down, anim-up, anim-left)', 'Tab state persisten via URL hash (#tab-name)', 'Custom scrollbar', 'Error pages: 403, 404, 500', ], }, ].map(feature => (
{feature.icon}
{feature.title}
{feature.items.map(item => (
{item}
))}
))}
{/* ── REST API ── */}

Base URL

{'http://your-domain.com/api/v1'}

Authentication Header

{'Authorization: Bearer {your-sanctum-token}'}

Endpoints

Auth
Users
App Config
{/* ── 2FA ── */}

Sistem mendukung dual-modality 2FA: TOTP (Google Authenticator) dan Email Verification OTP. Integrasi 2FA dirancang dengan prioritas keamanan ketat dan kontrol administrasi global.

📱 Google Authenticator / TOTP
  • Protokol standar industri RFC 6238
  • Dilengkapi 8 Recovery Codes cadangan sekali pakai
  • Dapat di-scan instan via QR Code
✉️ Email OTP 2FA
  • Pengiriman kode 6-digit dinamis langsung ke email user
  • Masa berlaku kode terbatas (TTL 10 menit)
  • Mencegah aktivasi jika SMTP Mailer belum tervalidasi

Alur Aktivasi Keamanan 2FA

{[ { step: '1', title: 'Verifikasi SMTP / Mail Delivery', desc: 'Sebelum mengaktifkan Email 2FA, pastikan SMTP Mailer di System Settings terkonfigurasi dengan benar dan di-tes sukses handshake-nya.' }, { step: '2', title: 'Pilih Metode di Pengaturan Pengguna', desc: 'Akses halaman Account Settings (/settings) → tab "Two-Factor Auth" untuk memilih metode yang diinginkan.' }, { step: '3', title: 'Konfirmasi Kode OTP / Autentikator', desc: 'Masukkan kode validasi perdana untuk memastikan setup sinkron dengan sistem sebelum metode di-lock.' }, { step: '4', title: 'Global Admin Override (Force Disable)', desc: 'Apabila administrator menonaktifkan metode 2FA secara global di System Settings, bypass otomatis akan di-enforce di login screen.' }, ].map(s => (
{s.step}
{s.title}
{s.desc}
))}
{/* ── SYSTEM SETTINGS ── */}

Dapat diakses oleh pengguna dengan role super-admin atau memiliki permission settings.view. Perubahan konfigurasi membutuhkan permission settings.edit. Tersedia di /system-settings.

{[ { tab: 'General & Branding', items: ['Nama aplikasi', 'Logo upload', 'Teks logo fallback', 'Registrasi publik on/off', 'Verifikasi email on/off', 'Global TOTP 2FA toggle (Aktif/Nonaktif)', 'Global Email 2FA toggle (Aktif/Nonaktif)'] }, { tab: 'Security & OAuth', items: ['Password minimum panjang', 'Wajib huruf besar/kecil/angka/simbol', 'Google OAuth (Client ID & Secret)', 'GitHub OAuth (Client ID & Secret)'] }, { tab: 'Email / SMTP', items: ['Host & port SMTP', 'Enkripsi (TLS/SSL)', 'Username & password SMTP', 'From name & address', 'Test kirim email handshake real-time (butuh settings.test-email)'] }, { tab: 'Mobile App Control', items: ['Versi terbaru & minimum Android', 'URL Play Store', 'Mode maintenance mobile app', 'Pesan maintenance kustom'] }, ].map(t => (
{t.tab}
{t.items.map(i => (
{i}
))}
))}
{/* ── STRUKTUR FOLDER ── */}
{`biiskit/ ├── app/ │ ├── Http/ │ │ ├── Controllers/ # Web + API controllers │ │ │ └── Api/V1/ # REST API v1 controllers │ │ ├── Middleware/ │ │ │ └── HandleInertiaRequests.php # Shared props (auth, settings) │ │ └── Requests/ # Form request validation │ ├── Models/ │ │ ├── User.php # SoftDeletes + HasRoles + HasPermissions │ │ ├── Setting.php # System settings key-value store │ │ └── NotificationLog.php # Notifikasi log │ └── Policies/ │ └── UserPolicy.php # Gate policies untuk user CRUD │ ├── database/ │ ├── migrations/ # PostgreSQL migrations │ └── seeders/ │ └── DatabaseSeeder.php # Roles, permissions, demo users │ ├── resources/js/ │ ├── Layouts/ │ │ ├── AuthenticatedLayout.tsx # Wrapper utama + mobile sidebar │ │ └── components/ │ │ ├── Sidebar.tsx # Nav dengan permission check │ │ └── Topbar.tsx # Breadcrumb + notif bell + dark mode │ ├── Pages/ │ │ ├── Auth/ # Login, Register, Password reset │ │ ├── Dashboard/ # Dashboard dengan chart │ │ ├── Users/ # Index, Show (CRUD) │ │ ├── Roles/ # Roles & permission manager │ │ ├── Notifications/ # Kirim & history notifikasi │ │ ├── ActivityLogs/ # Log aktivitas │ │ ├── Settings/ # Account settings (profile, password, 2FA, danger zone) │ │ ├── TwoFactor/ # 2FA challenge page (login flow, no auth) │ │ ├── SystemSettings/ # Sistem config (super-admin) │ │ ├── Docs/ # Halaman dokumentasi ini │ │ └── Errors/ # 403, 404, 500 pages │ └── Components/ │ ├── DataTable.tsx # Reusable sortable table │ └── FlashMessage.tsx # Success/error flash │ ├── routes/ │ ├── web.php # Web routes (Inertia) │ └── api.php # API routes (Sanctum) │ └── tests/ ├── Feature/ # Feature tests (Pest) └── Unit/ # Unit tests`}
); }