<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:version="2.0"><channel><title>Ngopidulur</title><description>Ngopi sambil baca tulisan random</description><link>https://ngopidulur.my.id/</link><language>en</language><item><title>Transport Project Doc</title><link>https://ngopidulur.my.id/blog/transport-project-doc/</link><guid isPermaLink="true">https://ngopidulur.my.id/blog/transport-project-doc/</guid><description>Ini adalah dokumentasi untuk Aplikasi Transport</description><content:encoded>&lt;h1&gt;Dokumentasi Project — Sankyu Transport Management System&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;Dokumentasi lengkap untuk developer: tech stack, arsitektur, development, deployment, troubleshooting, dan coding conventions.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Daftar Isi&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#1-tech-stack&quot;&gt;1. Tech Stack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#2-architecture&quot;&gt;2. Architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#3-development-setup&quot;&gt;3. Development Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#4-database--migrations&quot;&gt;4. Database &amp;amp; Migrations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#5-api-reference&quot;&gt;5. API Reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#6-deployment&quot;&gt;6. Deployment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#7-troubleshooting&quot;&gt;7. Troubleshooting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#8-coding-conventions&quot;&gt;8. Coding Conventions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;1. Tech Stack&lt;/h2&gt;
&lt;h3&gt;Backend — &lt;code&gt;node_backend/&lt;/code&gt;&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Kategori&lt;/th&gt;
&lt;th&gt;Teknologi&lt;/th&gt;
&lt;th&gt;Versi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Runtime&lt;/td&gt;
&lt;td&gt;Node.js&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Framework&lt;/td&gt;
&lt;td&gt;Express.js&lt;/td&gt;
&lt;td&gt;^4.18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bahasa&lt;/td&gt;
&lt;td&gt;JavaScript (CommonJS)&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database Utama&lt;/td&gt;
&lt;td&gt;MySQL&lt;/td&gt;
&lt;td&gt;via &lt;code&gt;mysql2&lt;/code&gt; ^3.9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database Sekunder&lt;/td&gt;
&lt;td&gt;MongoDB&lt;/td&gt;
&lt;td&gt;via &lt;code&gt;mongoose&lt;/code&gt; ^9.1 (legacy)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Autentikasi&lt;/td&gt;
&lt;td&gt;JWT&lt;/td&gt;
&lt;td&gt;&lt;code&gt;jsonwebtoken&lt;/code&gt; ^9.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Upload File&lt;/td&gt;
&lt;td&gt;Multer&lt;/td&gt;
&lt;td&gt;^2.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Excel Import/Export&lt;/td&gt;
&lt;td&gt;&lt;code&gt;xlsx&lt;/code&gt; ^0.18, &lt;code&gt;exceljs&lt;/code&gt; ^4.4&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Migrasi DB&lt;/td&gt;
&lt;td&gt;dbmate&lt;/td&gt;
&lt;td&gt;^2.32 (dev)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GPS Integration&lt;/td&gt;
&lt;td&gt;Wialon API&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reverse Geocoding&lt;/td&gt;
&lt;td&gt;Geoapify API&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;Dependency Utama Backend&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &amp;quot;cors&amp;quot;: &amp;quot;^2.8.5&amp;quot;,
  &amp;quot;dotenv&amp;quot;: &amp;quot;^16.4.5&amp;quot;,
  &amp;quot;exceljs&amp;quot;: &amp;quot;^4.4.0&amp;quot;,
  &amp;quot;express&amp;quot;: &amp;quot;^4.18.2&amp;quot;,
  &amp;quot;jsonwebtoken&amp;quot;: &amp;quot;^9.0.2&amp;quot;,
  &amp;quot;mongoose&amp;quot;: &amp;quot;^9.1.4&amp;quot;,
  &amp;quot;multer&amp;quot;: &amp;quot;^2.0.2&amp;quot;,
  &amp;quot;mysql2&amp;quot;: &amp;quot;^3.9.7&amp;quot;,
  &amp;quot;xlsx&amp;quot;: &amp;quot;^0.18.5&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Frontend — &lt;code&gt;tailadmin-vuejs-1.0.0/&lt;/code&gt;&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Kategori&lt;/th&gt;
&lt;th&gt;Teknologi&lt;/th&gt;
&lt;th&gt;Versi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Framework&lt;/td&gt;
&lt;td&gt;Vue 3&lt;/td&gt;
&lt;td&gt;^3.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bahasa&lt;/td&gt;
&lt;td&gt;TypeScript&lt;/td&gt;
&lt;td&gt;~5.7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build Tool&lt;/td&gt;
&lt;td&gt;Vite&lt;/td&gt;
&lt;td&gt;^6.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CSS Framework&lt;/td&gt;
&lt;td&gt;Tailwind CSS&lt;/td&gt;
&lt;td&gt;^4.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UI Template&lt;/td&gt;
&lt;td&gt;TailAdmin Vue Pro&lt;/td&gt;
&lt;td&gt;2.0.1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Router&lt;/td&gt;
&lt;td&gt;Vue Router&lt;/td&gt;
&lt;td&gt;^4.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maps&lt;/td&gt;
&lt;td&gt;Leaflet + MarkerCluster&lt;/td&gt;
&lt;td&gt;^1.9&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Icons&lt;/td&gt;
&lt;td&gt;Lucide Vue Next, Heroicons&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Charts&lt;/td&gt;
&lt;td&gt;ApexCharts (vue3-apexcharts)&lt;/td&gt;
&lt;td&gt;^1.8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Date Picker&lt;/td&gt;
&lt;td&gt;Vue Datepicker, Flatpickr&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linting&lt;/td&gt;
&lt;td&gt;ESLint + Prettier&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Type Check&lt;/td&gt;
&lt;td&gt;vue-tsc&lt;/td&gt;
&lt;td&gt;^2.2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;Dependency Utama Frontend&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &amp;quot;vue&amp;quot;: &amp;quot;^3.5.13&amp;quot;,
  &amp;quot;vue-router&amp;quot;: &amp;quot;^4.5.0&amp;quot;,
  &amp;quot;leaflet&amp;quot;: &amp;quot;^1.9.4&amp;quot;,
  &amp;quot;leaflet.markercluster&amp;quot;: &amp;quot;^1.5.3&amp;quot;,
  &amp;quot;tailwindcss&amp;quot;: &amp;quot;^4.0.0&amp;quot;,
  &amp;quot;apexcharts&amp;quot;: &amp;quot;^4.4.0&amp;quot;,
  &amp;quot;lucide-vue-next&amp;quot;: &amp;quot;^0.474.0&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Documentation — &lt;code&gt;docs/&lt;/code&gt;&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Kategori&lt;/th&gt;
&lt;th&gt;Teknologi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Static Site Generator&lt;/td&gt;
&lt;td&gt;VitePress ^1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Port Development&lt;/td&gt;
&lt;td&gt;5174&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;External Services&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Fungsi&lt;/th&gt;
&lt;th&gt;Catatan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Wialon&lt;/td&gt;
&lt;td&gt;GPS tracking, geofence, trip history&lt;/td&gt;
&lt;td&gt;Token di backend &lt;code&gt;.env&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Geoapify&lt;/td&gt;
&lt;td&gt;Reverse geocoding (koordinat → alamat)&lt;/td&gt;
&lt;td&gt;API key di backend &lt;code&gt;.env&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MySQL&lt;/td&gt;
&lt;td&gt;Database utama (data operasional)&lt;/td&gt;
&lt;td&gt;Local atau remote&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MongoDB&lt;/td&gt;
&lt;td&gt;Database sekunder (fitur legacy)&lt;/td&gt;
&lt;td&gt;Opsional&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Ports Default&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Service&lt;/th&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Backend (Express)&lt;/td&gt;
&lt;td&gt;3000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frontend (Vite dev)&lt;/td&gt;
&lt;td&gt;5173&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Docs (VitePress)&lt;/td&gt;
&lt;td&gt;5174&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MySQL&lt;/td&gt;
&lt;td&gt;3306&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;2. Architecture&lt;/h2&gt;
&lt;h3&gt;Gambaran Umum&lt;/h3&gt;
&lt;p&gt;Sistem ini menggunakan arsitektur &lt;strong&gt;monorepo&lt;/strong&gt; dengan dua aplikasi utama:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;┌─────────────────────┐     HTTP/JSON      ┌──────────────────────┐
│   Vue 3 Frontend    │ ◄────────────────► │   Express Backend    │
│  (SPA + Vite)       │     /api/*          │   (Node.js)          │
└─────────────────────┘                     └──────────┬───────────┘
                                                       │
                                            ┌──────────┼───────────┐
                                            │          │           │
                                       ┌────▼───┐ ┌───▼────┐ ┌───▼────────┐
                                       │ MySQL  │ │MongoDB │ │ Wialon API │
                                       │(utama) │ │(legacy)│ │ (GPS)      │
                                       └────────┘ └────────┘ └────────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Backend Architecture&lt;/h3&gt;
&lt;h4&gt;Layer Pattern&lt;/h4&gt;
&lt;p&gt;Backend mengikuti pola &lt;strong&gt;Route → Service → Database&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Request
  │
  ▼
middleware/auth.js        ← JWT verification
middleware/rbac.js        ← Role-based access control
  │
  ▼
routes/&amp;lt;domain&amp;gt;.js        ← HTTP handling, validation, response
  │
  ▼
services/&amp;lt;domain&amp;gt;.js      ← Business logic, external API calls
  │
  ▼
db.js (MySQL pool)        ← Direct SQL queries via mysql2/promise
models/&amp;lt;model&amp;gt;.js         ← Mongoose models (MongoDB, legacy)
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Route Registration&lt;/h4&gt;
&lt;p&gt;Semua route didaftarkan di &lt;code&gt;server.js&lt;/code&gt; dengan prefix &lt;code&gt;/api/&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;app.use(&amp;quot;/api/trucks&amp;quot;, truckRouter);
app.use(&amp;quot;/api/sales-costs&amp;quot;, salesCostRouter);
app.use(&amp;quot;/api/wialon&amp;quot;, wialonRouter);
// ...
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Authentication Flow&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;User login via &lt;code&gt;POST /api/auth/login&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Backend memverifikasi kredensial dan mengembalikan JWT token&lt;/li&gt;
&lt;li&gt;Frontend menyimpan token dan mengirimnya di header &lt;code&gt;Authorization: Bearer &amp;lt;token&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Middleware &lt;code&gt;authenticateToken&lt;/code&gt; memverifikasi token di setiap request&lt;/li&gt;
&lt;li&gt;Middleware &lt;code&gt;restrictCsAccess&lt;/code&gt; membatasi akses role CS ke route tertentu&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Role-Based Access Control&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;Akses&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;admin&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Semua endpoint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cs&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Hanya &lt;code&gt;GET /schedule-pengiriman&lt;/code&gt;, &lt;code&gt;GET /auth/me&lt;/code&gt;, &lt;code&gt;PUT /auth/me&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;Database Connection&lt;/h4&gt;
&lt;p&gt;MySQL menggunakan connection pool (&lt;code&gt;mysql2/promise&lt;/code&gt;):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const pool = mysql.createPool({
  host: process.env.DB_HOST,
  user: process.env.DB_USER,
  password: process.env.DB_PASS,
  database: process.env.DB_NAME || &amp;quot;trucking&amp;quot;,
  connectionLimit: 10
});
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Query dilakukan langsung tanpa ORM:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const [rows] = await pool.query(&amp;quot;SELECT * FROM truck WHERE is_active = 1&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;External Integration: Wialon&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;Backend                          Wialon API
  │                                  │
  ├── Login (token) ────────────────►│
  │◄──── Session ID ────────────────┤
  │                                  │
  ├── search_items (units) ─────────►│
  │◄──── Unit positions ────────────┤
  │                                  │
  ├── get_zones_by_unit ────────────►│
  │◄──── Geofence membership ──────┤
  │                                  │
  ├── unit/get_trips ───────────────►│
  │◄──── Trip history ─────────────┤
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Session di-reuse selama TTL belum habis&lt;/li&gt;
&lt;li&gt;Semua komunikasi Wialon hanya dari backend (token tidak pernah ke frontend)&lt;/li&gt;
&lt;li&gt;Response Wialon bisa nested — selalu gunakan normalizer&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Geofence Tracking (Background Service)&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;geofenceTrackingService.js
  │
  ├── Load active Sales Cost candidates
  ├── Load route-step → geofence mappings
  ├── Poll Wialon zone membership (interval)
  │
  └── If truck in mapped zone &amp;amp; not yet recorded:
      └── INSERT into sales_cost_route_history
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Berjalan otomatis saat server start&lt;/li&gt;
&lt;li&gt;Interval dikonfigurasi via &lt;code&gt;GEOFENCE_TRACKING_INTERVAL_MS&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Hanya mencatat first-entry per step (no duplicates)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Frontend Architecture&lt;/h3&gt;
&lt;h4&gt;Component Hierarchy&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;App.vue
  └── Router View
       ├── views/Master/*        ← CRUD pages
       ├── views/Transaksi/*     ← Transaction pages
       ├── views/Monitoring/*    ← GPS &amp;amp; mileage
       ├── views/DataTransport/* ← Reports
       └── views/Auth/*          ← Login
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;API Communication&lt;/h4&gt;
&lt;p&gt;Frontend berkomunikasi dengan backend melalui:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Development&lt;/strong&gt;: Vite proxy (&lt;code&gt;/api&lt;/code&gt; → &lt;code&gt;http://127.0.0.1:3000&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Production&lt;/strong&gt;: Direct ke &lt;code&gt;VITE_API_URL&lt;/code&gt; (e.g., &lt;code&gt;https://sankyu-transport.fun&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;// src/config/api.js
export const API_ORIGIN = import.meta.env.VITE_API_URL || window.location.origin
export const API_BASE = `${API_ORIGIN}/api`
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;State Management&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Tidak menggunakan Vuex/Pinia global store&lt;/li&gt;
&lt;li&gt;State dikelola per-component atau via composables&lt;/li&gt;
&lt;li&gt;Data dari API di-fetch langsung di views menggunakan service wrappers&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Map Architecture (Monitoring)&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;TruckLocationMap.vue
  ├── Left Panel: Leaflet Map (markers, clusters)
  ├── Middle Panel: Vehicle Detail (shown on selection)
  └── Right Panel: Fleet List (scrollable, searchable)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Auto-refresh setiap 30 detik&lt;/li&gt;
&lt;li&gt;Reverse geocode hanya untuk truck yang dipilih (bukan semua)&lt;/li&gt;
&lt;li&gt;Cache di localStorage dengan TTL 24 jam&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Data Flow Patterns&lt;/h3&gt;
&lt;h4&gt;Soft Delete Pattern&lt;/h4&gt;
&lt;p&gt;Trucks dan drivers menggunakan &lt;code&gt;is_active&lt;/code&gt; flag:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Active (is_active = 1):
  ✓ Muncul di dropdown operasional
  ✓ Muncul di GPS/map views
  ✓ Bisa digunakan untuk transaksi baru

Inactive (is_active = 0):
  ✓ Tetap muncul di Master Data (admin)
  ✓ Tetap muncul di historical records
  ✗ Tidak muncul di dropdown operasional
  ✗ Tidak muncul di GPS/map views
  ✗ Tidak bisa digunakan untuk transaksi baru
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Date Handling&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Penting:&lt;/strong&gt; MySQL &lt;code&gt;DATE&lt;/code&gt; values harus diperlakukan sebagai local date.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Jangan gunakan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;new Date(&amp;#39;YYYY-MM-DD&amp;#39;)&lt;/code&gt; (akan di-parse sebagai UTC)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;toISOString().slice(0, 10)&lt;/code&gt; (bisa bergeser 1 hari)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Gunakan:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// Backend: preserve local calendar parts
const [year, month, day] = dateString.split(&amp;#39;-&amp;#39;);

// Frontend: parse to local Date
new Date(year, month - 1, day);
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;File Upload Pattern&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;Frontend (multipart/form-data)
  │
  ▼
multer middleware (disk storage)
  │
  ▼
node_backend/upload/&amp;lt;category&amp;gt;/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Kategori upload: &lt;code&gt;doc-data-truck&lt;/code&gt;, &lt;code&gt;doc-data-chasis&lt;/code&gt;, &lt;code&gt;doc-supir&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;3. Development Setup&lt;/h2&gt;
&lt;h3&gt;Prerequisites&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Software&lt;/th&gt;
&lt;th&gt;Versi Minimum&lt;/th&gt;
&lt;th&gt;Catatan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Node.js&lt;/td&gt;
&lt;td&gt;18+&lt;/td&gt;
&lt;td&gt;LTS recommended&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;npm&lt;/td&gt;
&lt;td&gt;9+&lt;/td&gt;
&lt;td&gt;Bundled with Node.js&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MySQL&lt;/td&gt;
&lt;td&gt;8.0+&lt;/td&gt;
&lt;td&gt;Atau MariaDB 10.6+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Git&lt;/td&gt;
&lt;td&gt;2.30+&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MongoDB&lt;/td&gt;
&lt;td&gt;6.0+&lt;/td&gt;
&lt;td&gt;Opsional (fitur legacy)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Langkah 1: Clone Repository&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;git clone &amp;lt;repo-url&amp;gt; transport_v1.04
cd transport_v1.04
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Langkah 2: Setup Backend&lt;/h3&gt;
&lt;h4&gt;Install Dependencies&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;cd node_backend
npm install
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Konfigurasi Environment&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;Copy-Item .env.example .env
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Edit &lt;code&gt;node_backend/.env&lt;/code&gt; dan isi nilai yang sesuai:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Database MySQL
DB_HOST=localhost
DB_PORT=3306
DB_USER=root
DB_PASS=your_password
DB_NAME=trucking

# Authentication
JWT_SECRET=your_random_secret_string

# Server
PORT=3000

# Wialon GPS (minta ke admin)
WIALON_BASE_URL=https://hst-api.wialon.com/wialon/ajax.html
WIALON_TOKEN=your_wialon_token
WIALON_LOGIN_FLAGS=13
WIALON_SESSION_TTL_MS=2700000
WIALON_TIMEOUT_MS=20000

# Geoapify Reverse Geocoding
GEOAPIFY_API_KEY=your_geoapify_api_key
GEOAPIFY_BASE_URL=https://api.geoapify.com/v1/geocode/reverse
GEOAPIFY_TIMEOUT_MS=6000

# Cache TTL
REVERSE_GEOCODE_CACHE_TTL_MS=86400000
WIALON_MONTHLY_DISTANCE_CACHE_TTL_MS=600000

# Geofence Tracking
GEOFENCE_TRACKING_INTERVAL_MS=60000
DEFAULT_FINISH_GEOFENCE_NAME=Sankyu
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 Tip:&lt;/strong&gt; Untuk development lokal tanpa GPS, cukup isi &lt;code&gt;DB_*&lt;/code&gt;, &lt;code&gt;JWT_SECRET&lt;/code&gt;, dan &lt;code&gt;PORT&lt;/code&gt;. Fitur Wialon dan Geoapify akan gagal gracefully tanpa crash.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;Setup Database&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Perangkat Baru (Database Kosong):&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;npm run migrate
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Perintah ini akan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Membuat database &lt;code&gt;trucking&lt;/code&gt; jika belum ada&lt;/li&gt;
&lt;li&gt;Menjalankan semua migration files di &lt;code&gt;db/migrations/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Database Existing (Sudah Ada Data):&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;npm run migrate:adopt-existing
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Perintah ini akan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Melengkapi schema yang kurang (tabel tracking baru)&lt;/li&gt;
&lt;li&gt;Menandai semua migration sebagai sudah diterapkan&lt;/li&gt;
&lt;li&gt;Tidak menghapus data yang sudah ada&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Jalankan Backend&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;npm start
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Backend akan berjalan di &lt;code&gt;http://localhost:3000&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Langkah 3: Setup Frontend&lt;/h3&gt;
&lt;h4&gt;Install Dependencies&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;cd tailadmin-vuejs-1.0.0
npm install
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Jalankan Frontend&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Frontend akan berjalan di &lt;code&gt;http://localhost:5173&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;ℹ️ Info:&lt;/strong&gt; Vite dev server otomatis mem-proxy request &lt;code&gt;/api/*&lt;/code&gt; ke backend di port 3000. Pastikan backend sudah berjalan sebelum mengakses frontend.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Langkah 4: Setup Documentation (Opsional)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;cd docs
npm install
npm run dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Docs akan berjalan di &lt;code&gt;http://localhost:5174&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Verifikasi Setup&lt;/h3&gt;
&lt;p&gt;Checklist untuk memastikan setup berhasil:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&gt; Backend berjalan tanpa error di terminal&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&gt; &lt;code&gt;http://localhost:3000/api/auth/login&lt;/code&gt; merespons (POST)&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&gt; Frontend bisa diakses di &lt;code&gt;http://localhost:5173&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&gt; Login berhasil dengan kredensial yang valid&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&gt; Dashboard menampilkan data&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Development Workflow&lt;/h3&gt;
&lt;p&gt;Buka 2 terminal terpisah:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Terminal 1 — Backend:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;cd node_backend
npm start
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Terminal 2 — Frontend:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;cd tailadmin-vuejs-1.0.0
npm run dev
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Hot Reload&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Frontend&lt;/strong&gt;: Vite HMR otomatis reload saat file berubah&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Backend&lt;/strong&gt;: Tidak ada hot reload bawaan. Restart manual dengan &lt;code&gt;Ctrl+C&lt;/code&gt; lalu &lt;code&gt;npm start&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;💡 Tip:&lt;/strong&gt; Untuk auto-restart backend, install &lt;code&gt;nodemon&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;npm install -g nodemon
nodemon server.js
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;h4&gt;Akses dari Device Lain di LAN&lt;/h4&gt;
&lt;p&gt;Frontend Vite sudah dikonfigurasi listen di &lt;code&gt;0.0.0.0:5173&lt;/code&gt;. Akses dari device lain:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;http://&amp;lt;IP-HOST&amp;gt;:5173
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Build Check (Frontend)&lt;/h4&gt;
&lt;p&gt;Sebelum commit, pastikan build tidak error:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;cd tailadmin-vuejs-1.0.0
npm run build-only
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Linting &amp;amp; Formatting&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;cd tailadmin-vuejs-1.0.0
npm run lint       # ESLint auto-fix
npm run format     # Prettier format
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;4. Database &amp;amp; Migrations&lt;/h2&gt;
&lt;h3&gt;Overview&lt;/h3&gt;
&lt;p&gt;Sistem menggunakan &lt;strong&gt;MySQL&lt;/strong&gt; sebagai database utama dan &lt;strong&gt;MongoDB&lt;/strong&gt; untuk fitur legacy. Schema MySQL dikelola menggunakan &lt;strong&gt;dbmate&lt;/strong&gt; yang dibungkus dalam custom Node.js scripts.&lt;/p&gt;
&lt;h3&gt;Struktur File&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;node_backend/
├── db.js                  # MySQL connection pool
├── db/
│   ├── migrations/        # SQL migration files (timestamp-ordered)
│   │   ├── 20260401010000_baseline_from_trucking_dump.sql
│   │   ├── 20260401011000_add_tracking_foreign_keys.sql
│   │   ├── 20260401012000_add_area_finish_geofence.sql
│   │   ├── 20260424010000_add_truck_is_active.sql
│   │   └── 20260424011000_add_driver_is_active.sql
│   ├── schema.sql         # Generated schema snapshot
│   └── README.md          # Migration CLI documentation
├── scripts/
│   ├── run-dbmate.js      # dbmate wrapper
│   ├── build-baseline-migration.js
│   ├── adopt-existing-migrations.js
│   └── dump-schema.js
└── models/                # Mongoose models (MongoDB legacy)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Migration Commands&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Command&lt;/th&gt;
&lt;th&gt;Fungsi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run migrate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Jalankan semua pending migrations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run migrate:down&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Rollback migration terakhir&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run migrate:status&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lihat status migration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run migrate:new -- &amp;lt;name&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Buat file migration baru&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run migrate:dump&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Generate &lt;code&gt;db/schema.sql&lt;/code&gt; dari database aktif&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run migrate:adopt-existing&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Tandai migrations sebagai applied (DB existing)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run migrate:baseline:build&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Build baseline migration dari SQL dump&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Workflow: Membuat Perubahan Schema Baru&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Buat file migration:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;cd node_backend
npm run migrate:new -- add_column_xyz
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Edit file yang dihasilkan di &lt;code&gt;db/migrations/&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;-- migrate:up
ALTER TABLE truck ADD COLUMN xyz VARCHAR(100) NULL;

-- migrate:down
ALTER TABLE truck DROP COLUMN xyz;
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Jalankan migration:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;npm run migrate
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;(Opsional) Update schema snapshot:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;npm run migrate:dump
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Commit file migration ke git&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Naming Convention Migration&lt;/h3&gt;
&lt;p&gt;Format: &lt;code&gt;YYYYMMDDHHMMSS_deskripsi_singkat.sql&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Contoh:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;20260401010000_baseline_from_trucking_dump.sql&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;20260424010000_add_truck_is_active.sql&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Tabel Utama&lt;/h3&gt;
&lt;h4&gt;&lt;code&gt;truck&lt;/code&gt;&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Kolom&lt;/th&gt;
&lt;th&gt;Tipe&lt;/th&gt;
&lt;th&gt;Catatan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;INT AUTO_INCREMENT&lt;/td&gt;
&lt;td&gt;Primary key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;no_polisi&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;VARCHAR&lt;/td&gt;
&lt;td&gt;Nomor plat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;jenis_kendaraan&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;VARCHAR&lt;/td&gt;
&lt;td&gt;Tipe kendaraan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;wialon_unit_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;VARCHAR(64) NULL&lt;/td&gt;
&lt;td&gt;Mapping ke Wialon unit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;is_active&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;TINYINT(1) DEFAULT 1&lt;/td&gt;
&lt;td&gt;Soft delete flag&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;&lt;code&gt;driver&lt;/code&gt;&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Kolom&lt;/th&gt;
&lt;th&gt;Tipe&lt;/th&gt;
&lt;th&gt;Catatan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;INT AUTO_INCREMENT&lt;/td&gt;
&lt;td&gt;Primary key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nama_supir&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;VARCHAR&lt;/td&gt;
&lt;td&gt;Nama driver&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;is_active&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;TINYINT(1) DEFAULT 1&lt;/td&gt;
&lt;td&gt;Soft delete flag&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;&lt;code&gt;sales_cost&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Tabel transaksi utama yang menghubungkan truck, driver, customer, area, dan data biaya.&lt;/p&gt;
&lt;h4&gt;&lt;code&gt;area&lt;/code&gt;&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Kolom&lt;/th&gt;
&lt;th&gt;Tipe&lt;/th&gt;
&lt;th&gt;Catatan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;INT AUTO_INCREMENT&lt;/td&gt;
&lt;td&gt;Primary key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;kode_area&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;VARCHAR&lt;/td&gt;
&lt;td&gt;Kode area&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nama_area&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;VARCHAR&lt;/td&gt;
&lt;td&gt;Generated dari route steps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;finish_geofence_resource_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;VARCHAR NULL&lt;/td&gt;
&lt;td&gt;Wialon resource ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;finish_geofence_zone_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;VARCHAR NULL&lt;/td&gt;
&lt;td&gt;Wialon zone ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;finish_geofence_zone_name&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;VARCHAR NULL&lt;/td&gt;
&lt;td&gt;Nama geofence finish&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;&lt;code&gt;area_route_step&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Menyimpan urutan langkah route per area dengan mapping ke Wialon geofence.&lt;/p&gt;
&lt;h4&gt;&lt;code&gt;sales_cost_route_history&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Menyimpan riwayat kunjungan geofence aktual per Sales Cost delivery.&lt;/p&gt;
&lt;h4&gt;&lt;code&gt;schema_migrations&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Tabel internal dbmate untuk tracking migration yang sudah diterapkan.&lt;/p&gt;
&lt;h3&gt;Connection Pool&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// db.js
const pool = mysql.createPool({
  host: process.env.DB_HOST,
  user: process.env.DB_USER,
  password: process.env.DB_PASS,
  database: process.env.DB_NAME || &amp;quot;trucking&amp;quot;,
  waitForConnections: true,
  connectionLimit: 10,
  queueLimit: 0
});
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Penggunaan di Route/Service&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const pool = require(&amp;quot;../db&amp;quot;);

// Query biasa
const [rows] = await pool.query(&amp;quot;SELECT * FROM truck WHERE is_active = 1&amp;quot;);

// Query dengan parameter (prepared statement)
const [rows] = await pool.query(&amp;quot;SELECT * FROM truck WHERE id = ?&amp;quot;, [truckId]);

// Insert
const [result] = await pool.query(
  &amp;quot;INSERT INTO truck (no_polisi, jenis_kendaraan) VALUES (?, ?)&amp;quot;,
  [noPolisi, jenisKendaraan]
);
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Keamanan:&lt;/strong&gt; Selalu gunakan parameterized queries (&lt;code&gt;?&lt;/code&gt; placeholder). Jangan pernah string concatenation untuk values.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;MongoDB (Legacy)&lt;/h3&gt;
&lt;p&gt;MongoDB digunakan untuk beberapa fitur lama. Model didefinisikan di &lt;code&gt;node_backend/models/&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Koneksi MongoDB opsional — jika &lt;code&gt;MONGO_URI&lt;/code&gt; tidak diset di &lt;code&gt;.env&lt;/code&gt;, server tetap berjalan tanpa MongoDB.&lt;/p&gt;
&lt;h3&gt;Backup &amp;amp; Restore&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;# Export schema
npm run migrate:dump

# Full backup
mysqldump -u root -p trucking &amp;gt; backup_trucking.sql

# Restore
mysql -u root -p trucking &amp;lt; backup_trucking.sql
npm run migrate:adopt-existing
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Tips Database&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Selalu buat migration&lt;/strong&gt; untuk perubahan schema — jangan edit database langsung&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Commit migration files&lt;/strong&gt; ke git agar semua developer sinkron&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Jangan edit migration yang sudah di-apply&lt;/strong&gt; — buat migration baru untuk koreksi&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Test migration down&lt;/strong&gt; sebelum push untuk memastikan rollback berfungsi&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gunakan &lt;code&gt;is_active&lt;/code&gt; flag&lt;/strong&gt; untuk soft delete, bukan &lt;code&gt;DELETE FROM&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Date handling&lt;/strong&gt;: Simpan sebagai &lt;code&gt;DATE&lt;/code&gt; type, parse sebagai local date (bukan UTC)&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;5. API Reference&lt;/h2&gt;
&lt;p&gt;Semua endpoint menggunakan prefix &lt;code&gt;/api/&lt;/code&gt; dan berkomunikasi via JSON. Autentikasi menggunakan JWT Bearer token di header &lt;code&gt;Authorization&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Authentication&lt;/h3&gt;
&lt;h4&gt;Login&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-http&quot;&gt;POST /api/auth/login
Content-Type: application/json

{
  &amp;quot;username&amp;quot;: &amp;quot;admin&amp;quot;,
  &amp;quot;password&amp;quot;: &amp;quot;password123&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Response:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &amp;quot;token&amp;quot;: &amp;quot;eyJhbGciOiJIUzI1NiIs...&amp;quot;,
  &amp;quot;user&amp;quot;: { &amp;quot;id&amp;quot;: 1, &amp;quot;username&amp;quot;: &amp;quot;admin&amp;quot;, &amp;quot;level&amp;quot;: &amp;quot;admin&amp;quot; }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Get Current User&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-http&quot;&gt;GET /api/auth/me
Authorization: Bearer &amp;lt;token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Update Profile&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-http&quot;&gt;PUT /api/auth/me
Authorization: Bearer &amp;lt;token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Master Data&lt;/h3&gt;
&lt;h4&gt;Trucks&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Deskripsi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/trucks&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List trucks (default: active only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/trucks?include_inactive=1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List semua trucks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/trucks?status=active&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Filter active&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/trucks?status=inactive&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Filter inactive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/trucks&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Create truck&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PUT&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/trucks/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Update truck&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PATCH&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/trucks/:id/status&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Toggle active/inactive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/trucks/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Hard delete truck&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;Drivers&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Deskripsi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/drivers&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List drivers (default: active only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/drivers?include_inactive=1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List semua drivers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/drivers&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Create driver&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PUT&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/drivers/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Update driver&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PATCH&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/drivers/:id/status&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Toggle active/inactive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/drivers/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Hard delete driver&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;Customers&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Deskripsi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/customers&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List customers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/customers&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Create customer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PUT&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/customers/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Update customer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/customers/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Delete customer&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;Areas&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Deskripsi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/areas&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List areas (includes route_steps)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/areas/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Get area detail + route config&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/areas&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Create area (with kode_area, route_steps)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PUT&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/areas/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Update area + regenerate nama_area&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/areas/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Delete area&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;Warehouses&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Deskripsi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/warehouses&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List warehouses&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/warehouses&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Create warehouse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PUT&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/warehouses/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Update warehouse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/warehouses/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Delete warehouse&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;Subcontractors&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Deskripsi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/subconts&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List subcontractors&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/subconts&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Create subcontractor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PUT&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/subconts/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Update subcontractor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/subconts/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Delete subcontractor&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;Admins&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Deskripsi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/admins&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List admin users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/admins&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Create admin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PUT&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/admins/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Update admin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/admins/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Delete admin&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Transactions&lt;/h3&gt;
&lt;h4&gt;Sales Cost&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Deskripsi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/sales-costs&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List sales costs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/sales-costs/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Detail (includes route_steps, route_history)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/sales-costs/:id/print&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Print single SPK&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/sales-costs&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Create sales cost&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PUT&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/sales-costs/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Update sales cost&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/sales-costs/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Delete sales cost&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;ℹ️ Info:&lt;/strong&gt; Sales Cost reject inactive trucks/drivers untuk create dan import. Edit existing record memperbolehkan keep current inactive truck/driver, tapi reject ganti ke inactive lain.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;Repairs&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Deskripsi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/repairs&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List repairs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/repairs&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Create repair&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PUT&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/repairs/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Update repair&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/repairs/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Delete repair&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;Subcontractor Transactions&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Deskripsi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/subcontractor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List subcontractor transactions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/subcontractor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Create transaction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PUT&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/subcontractor/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Update transaction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/subcontractor/:id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Delete transaction&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;GPS &amp;amp; Monitoring (Wialon)&lt;/h3&gt;
&lt;h4&gt;Truck Locations&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-http&quot;&gt;GET /api/wialon/trucks/location
Authorization: Bearer &amp;lt;token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Response per truck:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &amp;quot;id&amp;quot;: 1,
  &amp;quot;no_polisi&amp;quot;: &amp;quot;B 1234 XYZ&amp;quot;,
  &amp;quot;lat&amp;quot;: -6.123456,
  &amp;quot;lon&amp;quot;: 106.789012,
  &amp;quot;speed&amp;quot;: 45,
  &amp;quot;gps_status&amp;quot;: &amp;quot;moving&amp;quot;,
  &amp;quot;driver_name&amp;quot;: &amp;quot;Budi&amp;quot;,
  &amp;quot;operational_status&amp;quot;: &amp;quot;transaksi&amp;quot;,
  &amp;quot;transaksi&amp;quot;: {},
  &amp;quot;repair&amp;quot;: null,
  &amp;quot;last_transaction&amp;quot;: {}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Catatan:&lt;/strong&gt; Hanya mengembalikan trucks dengan &lt;code&gt;is_active = 1&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;Reverse Geocoding&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-http&quot;&gt;GET /api/wialon/reverse-geocode?lat=-6.123&amp;amp;lon=106.789
Authorization: Bearer &amp;lt;token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Hanya request untuk 1 truck yang dipilih (bukan semua)&lt;/li&gt;
&lt;li&gt;Cached 24 jam di backend dan frontend localStorage&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Monthly Mileage&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-http&quot;&gt;GET /api/wialon/trucks/monthly-distance?month=2026-01
Authorization: Bearer &amp;lt;token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Monthly Mileage Export&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-http&quot;&gt;GET /api/wialon/trucks/monthly-distance/export?month=2026-01
Authorization: Bearer &amp;lt;token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Returns: &lt;code&gt;.xlsx&lt;/code&gt; file&lt;/p&gt;
&lt;h4&gt;Auto-Map Trucks to Wialon&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-http&quot;&gt;POST /api/wialon/trucks/auto-map
Authorization: Bearer &amp;lt;token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Geofence List&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-http&quot;&gt;GET /api/wialon/geofences
Authorization: Bearer &amp;lt;token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Other Endpoints&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Deskripsi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/dashboard&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Dashboard summary data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/data-trucks&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Data truck reports&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/data-chasis&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Data chasis reports&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/data-supir&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Data driver reports&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/monitoring-kendaraan&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Vehicle monitoring summary&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/master/import&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Import master data dari Excel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/master/template&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Download import template&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/notifications&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;List notifications&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/schedule-pengiriman&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Schedule pengiriman (accessible by CS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/address-book&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Address book&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Error Responses&lt;/h3&gt;
&lt;p&gt;Semua error mengikuti format:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-json&quot;&gt;{
  &amp;quot;message&amp;quot;: &amp;quot;Deskripsi error dalam Bahasa Indonesia&amp;quot;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Status Code&lt;/th&gt;
&lt;th&gt;Arti&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;400&lt;/td&gt;
&lt;td&gt;Bad Request — validasi gagal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;401&lt;/td&gt;
&lt;td&gt;Unauthorized — token tidak valid/expired&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;403&lt;/td&gt;
&lt;td&gt;Forbidden — role tidak punya akses&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;404&lt;/td&gt;
&lt;td&gt;Not Found — resource tidak ditemukan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;500&lt;/td&gt;
&lt;td&gt;Internal Server Error — error di server&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Authentication Header&lt;/h3&gt;
&lt;p&gt;Semua endpoint (kecuali &lt;code&gt;/api/auth/login&lt;/code&gt;) memerlukan:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-http&quot;&gt;Authorization: Bearer &amp;lt;jwt_token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;6. Deployment&lt;/h2&gt;
&lt;h3&gt;Arsitektur Production&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;Internet
  │
  ▼
[Reverse Proxy / Domain]
  │
  ├── https://sankyu-transport.fun (Frontend)
  │     └── Static files (Vite build output)
  │
  └── https://sankyu-transport.fun/api/* (Backend)
        └── Node.js Express (port 3000)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Prerequisites Production&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Software&lt;/th&gt;
&lt;th&gt;Versi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Node.js&lt;/td&gt;
&lt;td&gt;18+ LTS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MySQL&lt;/td&gt;
&lt;td&gt;8.0+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;npm&lt;/td&gt;
&lt;td&gt;9+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Git&lt;/td&gt;
&lt;td&gt;2.30+&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Opsional:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MongoDB 6.0+ (jika fitur legacy digunakan)&lt;/li&gt;
&lt;li&gt;PM2 atau systemd (process manager)&lt;/li&gt;
&lt;li&gt;Nginx atau Caddy (reverse proxy)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Deploy Backend&lt;/h3&gt;
&lt;h4&gt;1. Clone &amp;amp; Install&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git clone &amp;lt;repo-url&amp;gt; /opt/transport
cd /opt/transport/node_backend
npm install --production
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;2. Konfigurasi Environment&lt;/h4&gt;
&lt;p&gt;Buat file &lt;code&gt;.env&lt;/code&gt; dengan nilai production:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;DB_HOST=localhost
DB_PORT=3306
DB_USER=transport_user
DB_PASS=&amp;lt;strong_password&amp;gt;
DB_NAME=trucking

JWT_SECRET=&amp;lt;random_64_char_string&amp;gt;
PORT=3000

WIALON_BASE_URL=https://hst-api.wialon.com/wialon/ajax.html
WIALON_TOKEN=&amp;lt;production_wialon_token&amp;gt;
WIALON_LOGIN_FLAGS=13
WIALON_SESSION_TTL_MS=2700000
WIALON_TIMEOUT_MS=20000

GEOAPIFY_API_KEY=&amp;lt;production_api_key&amp;gt;
GEOAPIFY_BASE_URL=https://api.geoapify.com/v1/geocode/reverse
GEOAPIFY_TIMEOUT_MS=6000

REVERSE_GEOCODE_CACHE_TTL_MS=86400000
WIALON_MONTHLY_DISTANCE_CACHE_TTL_MS=600000
GEOFENCE_TRACKING_INTERVAL_MS=60000
DEFAULT_FINISH_GEOFENCE_NAME=Sankyu
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;🔒 Keamanan:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gunakan password MySQL yang kuat dan user dedicated (bukan root)&lt;/li&gt;
&lt;li&gt;Generate &lt;code&gt;JWT_SECRET&lt;/code&gt; yang random dan panjang&lt;/li&gt;
&lt;li&gt;Jangan commit &lt;code&gt;.env&lt;/code&gt; ke git&lt;/li&gt;
&lt;li&gt;Batasi akses file &lt;code&gt;.env&lt;/code&gt; hanya untuk user yang menjalankan service&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h4&gt;3. Setup Database&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npm run migrate
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;4. Jalankan dengan Process Manager&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Menggunakan PM2:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npm install -g pm2

# Start
pm2 start server.js --name transport-backend

# Auto-start on reboot
pm2 startup
pm2 save

# Monitor
pm2 status
pm2 logs transport-backend
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Menggunakan systemd:&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ini&quot;&gt;# /etc/systemd/system/transport-backend.service
[Unit]
Description=Transport Backend API
After=network.target mysql.service

[Service]
Type=simple
User=transport
WorkingDirectory=/opt/transport/node_backend
ExecStart=/usr/bin/node server.js
Restart=on-failure
RestartSec=10
Environment=NODE_ENV=production

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo systemctl enable transport-backend
sudo systemctl start transport-backend
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Deploy Frontend&lt;/h3&gt;
&lt;h4&gt;1. Build&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cd /opt/transport/tailadmin-vuejs-1.0.0
npm install
npm run build-only
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output build ada di folder &lt;code&gt;dist/&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;ℹ️ Info:&lt;/strong&gt; &lt;code&gt;npm run build-only&lt;/code&gt; skip type-check untuk build lebih cepat. Gunakan &lt;code&gt;npm run build&lt;/code&gt; jika ingin type-check sekaligus.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;2. Konfigurasi API URL&lt;/h4&gt;
&lt;p&gt;Pastikan &lt;code&gt;.env.production&lt;/code&gt; mengarah ke URL backend yang benar:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;VITE_API_URL=https://sankyu-transport.fun
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;3. Nginx Configuration&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-nginx&quot;&gt;server {
    listen 80;
    server_name sankyu-transport.fun;

    # Frontend static files
    root /opt/transport/tailadmin-vuejs-1.0.0/dist;
    index index.html;

    # SPA fallback
    location / {
        try_files $uri $uri/ /index.html;
    }

    # Proxy API ke backend
    location /api/ {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection &amp;#39;upgrade&amp;#39;;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;
    }

    # Proxy static uploads
    location /img/ {
        proxy_pass http://127.0.0.1:3000;
    }
    location /doc-data-truck/ {
        proxy_pass http://127.0.0.1:3000;
    }
    location /doc-data-chasis/ {
        proxy_pass http://127.0.0.1:3000;
    }
    location /doc-supir/ {
        proxy_pass http://127.0.0.1:3000;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Alternatif: Development Server sebagai Production&lt;/h3&gt;
&lt;p&gt;Untuk deployment sederhana (internal network):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Backend
cd node_backend &amp;amp;&amp;amp; npm start

# Frontend
cd tailadmin-vuejs-1.0.0 &amp;amp;&amp;amp; npm run dev -- --host 0.0.0.0
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Peringatan:&lt;/strong&gt; Cara ini tidak direkomendasikan untuk production publik.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Update / Redeploy&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Pull changes
cd /opt/transport
git pull origin main

# Update backend
cd node_backend
npm install
npm run migrate
pm2 restart transport-backend

# Update frontend
cd ../tailadmin-vuejs-1.0.0
npm install
npm run build-only
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;SSL/HTTPS&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d sankyu-transport.fun
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Monitoring Production&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Logs (PM2)
pm2 logs transport-backend

# Logs (systemd)
journalctl -u transport-backend -f

# Health check
curl http://localhost:3000/api/auth/me
# Expect: 401 = server berjalan
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Database Backup (Cron)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# /etc/cron.d/transport-backup
0 2 * * * transport mysqldump -u transport_user -p&amp;#39;password&amp;#39; trucking &amp;gt; /backup/trucking_$(date +\%Y\%m\%d).sql
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Checklist Deployment&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&gt; &lt;code&gt;.env&lt;/code&gt; production sudah dikonfigurasi dengan benar&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&gt; Database migration sudah dijalankan&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&gt; Frontend build berhasil tanpa error&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&gt; Backend berjalan dan merespons di port 3000&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&gt; Reverse proxy (Nginx) dikonfigurasi&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&gt; SSL certificate aktif&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&gt; Process manager (PM2/systemd) dikonfigurasi untuk auto-restart&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&gt; Backup database terjadwal&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&quot;&quot; type=&quot;checkbox&quot;&gt; Firewall hanya expose port 80/443&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;7. Troubleshooting&lt;/h2&gt;
&lt;h3&gt;Backend Issues&lt;/h3&gt;
&lt;h4&gt;Server Tidak Bisa Start&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Error&lt;/th&gt;
&lt;th&gt;Penyebab&lt;/th&gt;
&lt;th&gt;Solusi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ECONNREFUSED 127.0.0.1:3306&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;MySQL tidak berjalan&lt;/td&gt;
&lt;td&gt;Start MySQL service&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Access denied for user&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Kredensial salah&lt;/td&gt;
&lt;td&gt;Cek &lt;code&gt;DB_USER&lt;/code&gt; dan &lt;code&gt;DB_PASS&lt;/code&gt; di &lt;code&gt;.env&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Unknown database &amp;#39;trucking&amp;#39;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Database belum dibuat&lt;/td&gt;
&lt;td&gt;Jalankan &lt;code&gt;npm run migrate&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;JWT_SECRET belum dikonfigurasi&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.env&lt;/code&gt; tidak lengkap&lt;/td&gt;
&lt;td&gt;Tambahkan &lt;code&gt;JWT_SECRET&lt;/code&gt; di &lt;code&gt;.env&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MONGO_URI belum dikonfigurasi&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;MongoDB tidak diset&lt;/td&gt;
&lt;td&gt;Opsional — server tetap jalan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;EADDRINUSE :::3000&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Port sudah dipakai&lt;/td&gt;
&lt;td&gt;Kill proses lain atau ganti &lt;code&gt;PORT&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Cek port yang dipakai:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;netstat -ano | findstr :3000
taskkill /PID &amp;lt;pid&amp;gt; /F
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;API Return 401 Unauthorized&lt;/h4&gt;
&lt;p&gt;Penyebab umum:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Token expired — login ulang&lt;/li&gt;
&lt;li&gt;Token tidak dikirim — cek header &lt;code&gt;Authorization: Bearer &amp;lt;token&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;JWT_SECRET&lt;/code&gt; berbeda antara saat generate dan verify&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;API Return 403 Forbidden&lt;/h4&gt;
&lt;p&gt;User dengan role &lt;code&gt;cs&lt;/code&gt; mencoba akses endpoint yang tidak diizinkan. Hanya endpoint berikut yang bisa diakses CS:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GET /api/schedule-pengiriman&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/auth/me&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PUT /api/auth/me&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;MySQL Connection Pool Exhausted&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Gejala:&lt;/strong&gt; Request timeout atau &lt;code&gt;Too many connections&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Solusi:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Pastikan tidak ada query yang hang&lt;/li&gt;
&lt;li&gt;Cek &lt;code&gt;connectionLimit&lt;/code&gt; di &lt;code&gt;db.js&lt;/code&gt; (default: 10)&lt;/li&gt;
&lt;li&gt;Pastikan setiap query menggunakan pool (bukan manual connection)&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Migration Gagal&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situasi&lt;/th&gt;
&lt;th&gt;Solusi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Table already exists&lt;/td&gt;
&lt;td&gt;Gunakan &lt;code&gt;npm run migrate:adopt-existing&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Syntax error di SQL&lt;/td&gt;
&lt;td&gt;Perbaiki file migration, rollback dulu jika perlu&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Permission denied&lt;/td&gt;
&lt;td&gt;Cek user MySQL punya privilege CREATE/ALTER&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Frontend Issues&lt;/h3&gt;
&lt;h4&gt;Halaman Blank / White Screen&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Buka browser DevTools (F12) → Console&lt;/li&gt;
&lt;li&gt;Cek apakah ada JavaScript error&lt;/li&gt;
&lt;li&gt;Cek Network tab — apakah API calls gagal&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Penyebab umum:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Backend belum berjalan → start backend dulu&lt;/li&gt;
&lt;li&gt;CORS error → seharusnya tidak terjadi dengan Vite proxy&lt;/li&gt;
&lt;li&gt;Build error → jalankan &lt;code&gt;npm run build-only&lt;/code&gt; untuk cek&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;API Calls Gagal (Network Error)&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Development:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pastikan backend berjalan di port 3000&lt;/li&gt;
&lt;li&gt;Vite proxy otomatis forward &lt;code&gt;/api/*&lt;/code&gt; ke &lt;code&gt;http://127.0.0.1:3000&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Production:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Pastikan &lt;code&gt;VITE_API_URL&lt;/code&gt; di &lt;code&gt;.env.production&lt;/code&gt; benar&lt;/li&gt;
&lt;li&gt;Cek Nginx proxy configuration&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;CSS / UI Tidak Update&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Hard refresh: &lt;code&gt;Ctrl + Shift + R&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Clear browser cache&lt;/li&gt;
&lt;li&gt;Leaflet cluster icons bisa ter-cache&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;TypeScript Build Error&lt;/h4&gt;
&lt;p&gt;Jika ada TS error di file yang tidak terkait:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gunakan &lt;code&gt;npm run build-only&lt;/code&gt; (skip type-check)&lt;/li&gt;
&lt;li&gt;File legacy &lt;code&gt;.js&lt;/code&gt; di &lt;code&gt;src/services/&lt;/code&gt; mungkin punya implicit any — known issue&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Leaflet Map Tidak Muncul&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Container div tidak punya height → pastikan parent punya fixed height&lt;/li&gt;
&lt;li&gt;Leaflet CSS tidak ter-import → cek import di component&lt;/li&gt;
&lt;li&gt;Tile server unreachable → cek koneksi internet&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;GPS / Wialon Issues&lt;/h3&gt;
&lt;h4&gt;Semua Truck Muncul Offline&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Restart backend&lt;/li&gt;
&lt;li&gt;Cek log backend untuk error login Wialon&lt;/li&gt;
&lt;li&gt;Verifikasi &lt;code&gt;WIALON_TOKEN&lt;/code&gt; di &lt;code&gt;.env&lt;/code&gt; belum expired&lt;/li&gt;
&lt;li&gt;Cek apakah Wialon API accessible dari server&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Reverse Geocode Tidak Menampilkan Alamat&lt;/h4&gt;
&lt;p&gt;Penyebab:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;GEOAPIFY_API_KEY&lt;/code&gt; tidak valid atau quota habis&lt;/li&gt;
&lt;li&gt;Koordinat tidak valid (0,0 atau null)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Solusi:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;UI fallback ke koordinat mentah&lt;/li&gt;
&lt;li&gt;Cek Geoapify dashboard untuk usage/quota&lt;/li&gt;
&lt;li&gt;Clear localStorage jika ingin force re-fetch:&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;Object.keys(localStorage)
  .filter(k =&amp;gt; k.startsWith(&amp;#39;geocode_&amp;#39;))
  .forEach(k =&amp;gt; localStorage.removeItem(k));
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Geofence History Tetap &amp;quot;Pending&amp;quot;&lt;/h4&gt;
&lt;p&gt;Penyebab: Wialon &lt;code&gt;resource/get_zones_by_unit&lt;/code&gt; mengembalikan nested payload.&lt;/p&gt;
&lt;p&gt;Langkah debug:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Cek raw Wialon membership result untuk truck/unit bermasalah&lt;/li&gt;
&lt;li&gt;Verifikasi parsed membership map dari &lt;code&gt;fetchUnitsInZonesByResource&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Pastikan &lt;code&gt;normalizeZoneMembershipPayload&lt;/code&gt; handle nested format: &lt;code&gt;{resourceId: {zoneId: [unitIds]}}&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Cek apakah truck benar-benar di dalam polygon geofence di Wialon&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Monthly Mileage &amp;quot;Invalid GPS Mapping&amp;quot;&lt;/h4&gt;
&lt;p&gt;Penyebab: &lt;code&gt;wialon_unit_id&lt;/code&gt; di database tidak cocok dengan unit di Wialon.&lt;/p&gt;
&lt;p&gt;Solusi:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Cek mapping di Master Truck&lt;/li&gt;
&lt;li&gt;Jalankan auto-map ulang: &lt;code&gt;POST /api/wialon/trucks/auto-map&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Atau update &lt;code&gt;wialon_unit_id&lt;/code&gt; manual&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Database Issues&lt;/h3&gt;
&lt;h4&gt;Tanggal Bergeser 1 Hari&lt;/h4&gt;
&lt;p&gt;Penyebab: MySQL &lt;code&gt;DATE&lt;/code&gt; di-parse melalui UTC conversion.&lt;/p&gt;
&lt;p&gt;Solusi:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Backend: Jangan gunakan &lt;code&gt;new Date(dateString).toISOString().slice(0,10)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Frontend: Parse dengan &lt;code&gt;new Date(year, month - 1, day)&lt;/code&gt; bukan &lt;code&gt;new Date(&amp;#39;YYYY-MM-DD&amp;#39;)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Data Tidak Konsisten Setelah Import&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Cek log import di backend console&lt;/li&gt;
&lt;li&gt;Verifikasi format Excel sesuai template&lt;/li&gt;
&lt;li&gt;Pastikan referensi (truck_id, driver_id) valid dan active&lt;/li&gt;
&lt;li&gt;Import akan reject inactive trucks/drivers&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Network &amp;amp; Infrastructure&lt;/h3&gt;
&lt;h4&gt;CORS Error&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Development:&lt;/strong&gt; Pastikan request ke &lt;code&gt;/api/*&lt;/code&gt; (bukan full URL ke port 3000)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Production:&lt;/strong&gt; Pastikan Nginx proxy_pass dikonfigurasi untuk semua path&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;WebSocket / HMR Error (Development)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Pastikan port 5173 tidak diblokir firewall&lt;/li&gt;
&lt;li&gt;Untuk development lokal, comment out &lt;code&gt;hmr&lt;/code&gt; config di &lt;code&gt;vite.config.ts&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;PowerShell Execution Policy&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Performance Issues&lt;/h3&gt;
&lt;h4&gt;Backend Response Lambat&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Cek slow queries: &lt;code&gt;SHOW PROCESSLIST;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Tambahkan index untuk kolom yang sering di-query/filter&lt;/li&gt;
&lt;li&gt;Cek Wialon API timeout (increase &lt;code&gt;WIALON_TIMEOUT_MS&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Cek connection pool usage&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Frontend Load Lambat&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Jalankan production build (bukan dev mode)&lt;/li&gt;
&lt;li&gt;Cek bundle size via &lt;code&gt;npm run build-only&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Pastikan gambar/assets sudah optimized&lt;/li&gt;
&lt;li&gt;Gunakan browser DevTools → Performance tab&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;8. Coding Conventions&lt;/h2&gt;
&lt;h3&gt;Backend (Node.js / Express)&lt;/h3&gt;
&lt;h4&gt;Bahasa &amp;amp; Module System&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;JavaScript (bukan TypeScript)&lt;/li&gt;
&lt;li&gt;CommonJS: &lt;code&gt;require()&lt;/code&gt; / &lt;code&gt;module.exports&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Tidak menggunakan ES Modules di backend&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Struktur File Route&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const express = require(&amp;quot;express&amp;quot;);
const router = express.Router();
const pool = require(&amp;quot;../db&amp;quot;);
const { authenticateToken } = require(&amp;quot;../middleware/auth&amp;quot;);

router.use(authenticateToken);

router.get(&amp;quot;/&amp;quot;, async (req, res) =&amp;gt; {
  try {
    const [rows] = await pool.query(&amp;quot;SELECT * FROM table_name&amp;quot;);
    res.json(rows);
  } catch (error) {
    console.error(&amp;quot;Error:&amp;quot;, error);
    res.status(500).json({ message: &amp;quot;Gagal mengambil data&amp;quot; });
  }
});

module.exports = router;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Naming Conventions (Backend)&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Convention&lt;/th&gt;
&lt;th&gt;Contoh&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;File route&lt;/td&gt;
&lt;td&gt;camelCase&lt;/td&gt;
&lt;td&gt;&lt;code&gt;salesCost.js&lt;/code&gt;, &lt;code&gt;dataTruck.js&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;File service&lt;/td&gt;
&lt;td&gt;camelCase&lt;/td&gt;
&lt;td&gt;&lt;code&gt;wialonService.js&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Variable&lt;/td&gt;
&lt;td&gt;camelCase&lt;/td&gt;
&lt;td&gt;&lt;code&gt;truckId&lt;/code&gt;, &lt;code&gt;noPolisi&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database column&lt;/td&gt;
&lt;td&gt;snake_case&lt;/td&gt;
&lt;td&gt;&lt;code&gt;is_active&lt;/code&gt;, &lt;code&gt;wialon_unit_id&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API endpoint&lt;/td&gt;
&lt;td&gt;kebab-case&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/api/sales-costs&lt;/code&gt;, &lt;code&gt;/api/data-trucks&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Error message&lt;/td&gt;
&lt;td&gt;Bahasa Indonesia&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;quot;Token tidak ditemukan&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;Database Query Pattern&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// ✅ Parameterized query (aman dari SQL injection)
const [rows] = await pool.query(
  &amp;quot;SELECT * FROM truck WHERE id = ? AND is_active = ?&amp;quot;,
  [id, 1]
);

// ❌ String concatenation (JANGAN)
const [rows] = await pool.query(
  `SELECT * FROM truck WHERE id = ${id}`
);
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Error Handling Pattern&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;router.post(&amp;quot;/&amp;quot;, async (req, res) =&amp;gt; {
  try {
    // ... logic
    res.status(201).json({ message: &amp;quot;Berhasil&amp;quot;, data: result });
  } catch (error) {
    console.error(&amp;quot;Deskripsi context:&amp;quot;, error);
    res.status(500).json({ message: &amp;quot;Pesan error user-friendly&amp;quot; });
  }
});
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Soft Delete Pattern&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// Deactivate
router.patch(&amp;quot;/:id/status&amp;quot;, async (req, res) =&amp;gt; {
  const { is_active } = req.body;
  await pool.query(&amp;quot;UPDATE truck SET is_active = ? WHERE id = ?&amp;quot;, [is_active, id]);
});

// Default query: hanya active
const [rows] = await pool.query(&amp;quot;SELECT * FROM truck WHERE is_active = 1&amp;quot;);

// Admin view: semua
const [rows] = await pool.query(&amp;quot;SELECT * FROM truck&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Date Handling (Backend)&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;// ✅ Preserve local date parts
const formatDate = (dateValue) =&amp;gt; {
  if (!dateValue) return null;
  const d = new Date(dateValue);
  const year = d.getFullYear();
  const month = String(d.getMonth() + 1).padStart(2, &amp;#39;0&amp;#39;);
  const day = String(d.getDate()).padStart(2, &amp;#39;0&amp;#39;);
  return `${year}-${month}-${day}`;
};

// ❌ Jangan gunakan (bisa geser 1 hari karena UTC)
const bad = new Date(dateValue).toISOString().slice(0, 10);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Frontend (Vue 3 / TypeScript)&lt;/h3&gt;
&lt;h4&gt;Bahasa &amp;amp; Style&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;TypeScript untuk file baru (&lt;code&gt;.ts&lt;/code&gt;, &lt;code&gt;.vue&lt;/code&gt; dengan &lt;code&gt;&amp;lt;script setup lang=&amp;quot;ts&amp;quot;&amp;gt;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;File legacy boleh tetap &lt;code&gt;.js&lt;/code&gt; sampai ada kebutuhan refactor&lt;/li&gt;
&lt;li&gt;Vue 3 Composition API dengan &lt;code&gt;&amp;lt;script setup&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Tailwind CSS utility classes&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Struktur Component (Vue SFC)&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-vue&quot;&gt;&amp;lt;script setup lang=&amp;quot;ts&amp;quot;&amp;gt;
import { ref, onMounted } from &amp;#39;vue&amp;#39;
import { API_BASE } from &amp;#39;@/config/api&amp;#39;

const props = defineProps&amp;lt;{
  truckId: number
}&amp;gt;()

const loading = ref(false)
const data = ref&amp;lt;TruckData | null&amp;gt;(null)

const fetchData = async () =&amp;gt; {
  loading.value = true
  try {
    const res = await fetch(`${API_BASE}/trucks/${props.truckId}`)
    data.value = await res.json()
  } finally {
    loading.value = false
  }
}

onMounted(() =&amp;gt; {
  fetchData()
})
&amp;lt;/script&amp;gt;

&amp;lt;template&amp;gt;
  &amp;lt;div class=&amp;quot;p-4&amp;quot;&amp;gt;
    &amp;lt;!-- template --&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/template&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Naming Conventions (Frontend)&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Convention&lt;/th&gt;
&lt;th&gt;Contoh&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Component file&lt;/td&gt;
&lt;td&gt;PascalCase&lt;/td&gt;
&lt;td&gt;&lt;code&gt;TruckLocationMap.vue&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;View folder&lt;/td&gt;
&lt;td&gt;PascalCase&lt;/td&gt;
&lt;td&gt;&lt;code&gt;views/Master/&lt;/code&gt;, &lt;code&gt;views/Monitoring/&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Service file&lt;/td&gt;
&lt;td&gt;camelCase&lt;/td&gt;
&lt;td&gt;&lt;code&gt;truckLocationService.ts&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Composable&lt;/td&gt;
&lt;td&gt;camelCase with &lt;code&gt;use&lt;/code&gt; prefix&lt;/td&gt;
&lt;td&gt;&lt;code&gt;useAuth.ts&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Variable/ref&lt;/td&gt;
&lt;td&gt;camelCase&lt;/td&gt;
&lt;td&gt;&lt;code&gt;truckList&lt;/code&gt;, &lt;code&gt;isLoading&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CSS class&lt;/td&gt;
&lt;td&gt;Tailwind utilities&lt;/td&gt;
&lt;td&gt;&lt;code&gt;class=&amp;quot;flex items-center gap-2&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;Service Pattern&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;// src/services/truckLocationService.ts
import { API_BASE } from &amp;#39;@/config/api&amp;#39;

export const getTruckLocations = async () =&amp;gt; {
  const token = localStorage.getItem(&amp;#39;token&amp;#39;)
  const res = await fetch(`${API_BASE}/wialon/trucks/location`, {
    headers: { Authorization: `Bearer ${token}` }
  })
  if (!res.ok) throw new Error(&amp;#39;Failed to fetch&amp;#39;)
  return res.json()
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Path Alias&lt;/h4&gt;
&lt;p&gt;Gunakan &lt;code&gt;@/&lt;/code&gt; untuk import dari &lt;code&gt;src/&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-typescript&quot;&gt;import { API_BASE } from &amp;#39;@/config/api&amp;#39;
import TruckCard from &amp;#39;@/components/TruckCard.vue&amp;#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Tailwind CSS Guidelines&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;lt;!-- ✅ Tailwind utilities --&amp;gt;
&amp;lt;div class=&amp;quot;flex items-center gap-4 p-4 rounded-lg bg-white shadow-sm&amp;quot;&amp;gt;

&amp;lt;!-- ❌ Hindari custom class tanpa alasan kuat --&amp;gt;
&amp;lt;div class=&amp;quot;truck-card-wrapper&amp;quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Git Conventions&lt;/h3&gt;
&lt;h4&gt;Commit Messages&lt;/h4&gt;
&lt;p&gt;Format: &lt;code&gt;&amp;lt;type&amp;gt;: &amp;lt;description&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Penggunaan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;feat&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Fitur baru&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fix&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Bug fix&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;refactor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Refactoring tanpa perubahan behavior&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;docs&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Perubahan dokumentasi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;style&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Formatting, missing semicolons, dll&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;chore&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Maintenance, dependency update&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Contoh:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;feat: add monthly mileage export to Excel
fix: date shift issue on Sales Cost edit
refactor: extract geofence tracking to service
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Branch Naming&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;feature/add-truck-mileage
fix/date-shift-sales-cost
refactor/wialon-service-cleanup
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;File Organization Rules&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Satu route file per domain&lt;/strong&gt; — jangan gabung multiple domains&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Business logic di services&lt;/strong&gt; — route hanya handle HTTP&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Satu service file per external integration&lt;/strong&gt; — e.g., &lt;code&gt;wialonService.js&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Views by domain&lt;/strong&gt; — &lt;code&gt;views/Master/&lt;/code&gt;, &lt;code&gt;views/Transaksi/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Shared components di &lt;code&gt;components/&lt;/code&gt;&lt;/strong&gt; — bukan di dalam &lt;code&gt;views/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Migration files tidak boleh diedit&lt;/strong&gt; setelah di-apply — buat migration baru&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Bahasa&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Context&lt;/th&gt;
&lt;th&gt;Bahasa&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Code (variable, function, comments)&lt;/td&gt;
&lt;td&gt;English&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UI text&lt;/td&gt;
&lt;td&gt;Bahasa Indonesia&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API error messages&lt;/td&gt;
&lt;td&gt;Bahasa Indonesia&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Documentation&lt;/td&gt;
&lt;td&gt;Bahasa Indonesia (kecuali technical terms)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Git commits&lt;/td&gt;
&lt;td&gt;English&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Dokumen ini di-generate dari:&lt;/strong&gt; &lt;code&gt;docs/developer/&lt;/code&gt; folder&lt;br&gt;&lt;strong&gt;Terakhir diperbarui:&lt;/strong&gt; Mei 2026&lt;/p&gt;
&lt;/blockquote&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://ngopidulur.my.id/blog/transport-project-doc/&quot;&gt;https://ngopidulur.my.id/blog/transport-project-doc/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>Ngopidulur</dc:creator><pubDate>Tue, 26 May 2026 11:44:00 GMT</pubDate></item><item><title>PowerShell Notes for Professionals</title><link>https://ngopidulur.my.id/blog/powershell-notes-for-professionals/</link><guid isPermaLink="true">https://ngopidulur.my.id/blog/powershell-notes-for-professionals/</guid><description>Versi ini dirapikan dan diperingkas dari dokumen PowerShell Notes for Professionals. Fokusnya adalah navigasi cepat, inti materi, dan daftar konsep/cmdlet penting per bab.</description><content:encoded>&lt;h1&gt;PowerShell Notes for Professionals&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;Versi ini dirapikan dan diperingkas dari dokumen PowerShell Notes for Professionals. Fokusnya adalah navigasi cepat, inti materi, dan daftar konsep/cmdlet penting per bab.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Cara Pakai Dokumen&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Gunakan &lt;strong&gt;Daftar Isi&lt;/strong&gt; untuk lompat ke bab tertentu.&lt;/li&gt;
&lt;li&gt;Setiap bab berisi &lt;strong&gt;inti materi&lt;/strong&gt;, &lt;strong&gt;topik/bagian&lt;/strong&gt;, dan &lt;strong&gt;cmdlet/konsep cepat&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Contoh kode tidak ditampilkan penuh agar dokumen lebih ringkas; gunakan versi lengkap jika perlu detail sintaks.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Daftar Isi&lt;/h2&gt;
&lt;h3&gt;Dasar PowerShell&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#bab-1-memulai-powershell&quot;&gt;Bab 1: Memulai PowerShell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-2-variabel-di-powershell&quot;&gt;Bab 2: Variabel di PowerShell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-3-operator&quot;&gt;Bab 3: Operator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-4-operator-khusus&quot;&gt;Bab 4: Operator Khusus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-5-operasi-set-dasar&quot;&gt;Bab 5: Operasi Set Dasar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-6-logika-kondisional&quot;&gt;Bab 6: Logika Kondisional&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-7-perulangan&quot;&gt;Bab 7: Perulangan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-8-pernyataan-switch&quot;&gt;Bab 8: Pernyataan Switch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-9-string&quot;&gt;Bab 9: String&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-10-hashtable&quot;&gt;Bab 10: HashTable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-11-bekerja-dengan-objek&quot;&gt;Bab 11: Bekerja dengan Objek&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-12-fungsi-powershell&quot;&gt;Bab 12: Fungsi PowerShell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-13-kelas-powershell&quot;&gt;Bab 13: Kelas PowerShell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-14-modul-powershell&quot;&gt;Bab 14: Modul PowerShell&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Objek, Modul, Pipeline, dan Data&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#bab-15-profil-powershell&quot;&gt;Bab 15: Profil PowerShell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-16-properti-terhitung&quot;&gt;Bab 16: Properti Terhitung&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-17-menggunakan-kelas-statis-net&quot;&gt;Bab 17: Menggunakan Kelas Statis .NET&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-18-variabel-bawaan&quot;&gt;Bab 18: Variabel Bawaan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-19-variabel-otomatis&quot;&gt;Bab 19: Variabel Otomatis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-20-variabel-lingkungan&quot;&gt;Bab 20: Variabel Lingkungan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-21-splatting&quot;&gt;Bab 21: Splatting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-22-stream-powershell&quot;&gt;Bab 22: Stream PowerShell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-23-mengirim-email&quot;&gt;Bab 23: Mengirim Email&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-24-powershell-remoting&quot;&gt;Bab 24: PowerShell Remoting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-25-pipeline-powershell&quot;&gt;Bab 25: Pipeline PowerShell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-26-background-job-powershell&quot;&gt;Bab 26: Background Job PowerShell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-27-perilaku-return-di-powershell&quot;&gt;Bab 27: Perilaku Return di PowerShell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-28-parsing-csv&quot;&gt;Bab 28: Parsing CSV&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-29-bekerja-dengan-file-xml&quot;&gt;Bab 29: Bekerja dengan File XML&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Integrasi, Tooling, dan CLI&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#bab-30-restful-api&quot;&gt;Bab 30: RESTful API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-31-query-sql-powershell&quot;&gt;Bab 31: Query SQL PowerShell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-32-regular-expression&quot;&gt;Bab 32: Regular Expression&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-33-alias&quot;&gt;Bab 33: Alias&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-34-progress-bar&quot;&gt;Bab 34: Progress Bar&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-35-command-line-powershellexe&quot;&gt;Bab 35: Command-Line PowerShell.exe&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-36-penamaan-cmdlet&quot;&gt;Bab 36: Penamaan Cmdlet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-37-menjalankan-executable&quot;&gt;Bab 37: Menjalankan Executable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-38-prasyarat-script&quot;&gt;Bab 38: Prasyarat Script&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-39-sistem-bantuan&quot;&gt;Bab 39: Sistem Bantuan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-40-modul-script-dan-fungsi&quot;&gt;Bab 40: Modul, Script, dan Fungsi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-41-konvensi-penamaan&quot;&gt;Bab 41: Konvensi Penamaan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-42-parameter-umum&quot;&gt;Bab 42: Parameter Umum&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-43-parameter-set&quot;&gt;Bab 43: Parameter Set&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-44-parameter-dinamis&quot;&gt;Bab 44: Parameter Dinamis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-45-gui-di-powershell&quot;&gt;Bab 45: GUI di PowerShell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-46-url-encodedecode&quot;&gt;Bab 46: URL Encode/Decode&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Automation, Security, Cloud, dan Enterprise&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#bab-47-penanganan-error&quot;&gt;Bab 47: Penanganan Error&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-48-manajemen-paket&quot;&gt;Bab 48: Manajemen Paket&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-49-komunikasi-tcp&quot;&gt;Bab 49: Komunikasi TCP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-50-workflow-powershell&quot;&gt;Bab 50: Workflow PowerShell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-51-managed-code-c-vb&quot;&gt;Bab 51: Managed Code C# / VB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-52-download-artifact-dari-artifactory&quot;&gt;Bab 52: Download Artifact dari Artifactory&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-53-comment-based-help&quot;&gt;Bab 53: Comment-Based Help&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-54-modul-archive&quot;&gt;Bab 54: Modul Archive&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-55-otomasi-infrastruktur&quot;&gt;Bab 55: Otomasi Infrastruktur&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-56-psscriptanalyzer&quot;&gt;Bab 56: PSScriptAnalyzer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-57-desired-state-configuration-dsc&quot;&gt;Bab 57: Desired State Configuration DSC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-58-shouldprocess&quot;&gt;Bab 58: ShouldProcess&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-59-scheduled-tasks&quot;&gt;Bab 59: Scheduled Tasks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-60-modul-ise&quot;&gt;Bab 60: Modul ISE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-61-resource-dsc-berbasis-class&quot;&gt;Bab 61: Resource DSC Berbasis Class&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-62-wmi-dan-cim&quot;&gt;Bab 62: WMI dan CIM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-63-modul-activedirectory&quot;&gt;Bab 63: Modul ActiveDirectory&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-64-modul-sharepoint&quot;&gt;Bab 64: Modul SharePoint&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-65-psake&quot;&gt;Bab 65: Psake&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-66-pester&quot;&gt;Bab 66: Pester&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-67-secret-dan-credential&quot;&gt;Bab 67: Secret dan Credential&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-68-security-dan-cryptography&quot;&gt;Bab 68: Security dan Cryptography&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-69-signing-scripts&quot;&gt;Bab 69: Signing Scripts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-70-anonimisasi-ip&quot;&gt;Bab 70: Anonimisasi IP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-71-aws-rekognition&quot;&gt;Bab 71: AWS Rekognition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-72-aws-s3&quot;&gt;Bab 72: AWS S3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-1-memulai-powershell&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 1: Memulai PowerShell&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Fondasi PowerShell: execution policy, alias, pipeline, pemanggilan .NET, instalasi, komentar, dan pembuatan objek.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-11-allow-scripts-stored-on-your-machine-to-run-un-signed-2&quot;&gt;&lt;/a&gt;&lt;strong&gt;1.1&lt;/strong&gt; — Allow scripts stored on your machine to run un-signed 2 ........................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-12-aliases-similar-functions-2&quot;&gt;&lt;/a&gt;&lt;strong&gt;1.2&lt;/strong&gt; — Aliases &amp;amp; Similar Functions 2 .......................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-13-the-pipeline-using-output-from-a-powershell-cmdlet-3&quot;&gt;&lt;/a&gt;&lt;strong&gt;1.3&lt;/strong&gt; — The Pipeline-Using Output from a PowerShell cmdlet 3 ........................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-14-calling-net-library-methods-4&quot;&gt;&lt;/a&gt;&lt;strong&gt;1.4&lt;/strong&gt; — Calling .Net Library Methods 4 ....................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-15-installation-or-setup-5&quot;&gt;&lt;/a&gt;&lt;strong&gt;1.5&lt;/strong&gt; — Installation or Setup 5 ..................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-16-commenting-5&quot;&gt;&lt;/a&gt;&lt;strong&gt;1.6&lt;/strong&gt; — Commenting 5 ...............................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-17-creating-objects-6&quot;&gt;&lt;/a&gt;&lt;strong&gt;1.7&lt;/strong&gt; — Creating Objects 6 ........................................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-2-variabel-di-powershell&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 2: Variabel di PowerShell&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Cara menyimpan dan mengelola nilai memakai variabel, array, scope, assignment multi-variabel, dan penghapusan variabel.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-21-simple-variable-7&quot;&gt;&lt;/a&gt;&lt;strong&gt;2.1&lt;/strong&gt; — Simple variable 7 ..........................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-22-arrays-7&quot;&gt;&lt;/a&gt;&lt;strong&gt;2.2&lt;/strong&gt; — Arrays 7 ........................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-23-list-assignment-of-multiple-variables-7&quot;&gt;&lt;/a&gt;&lt;strong&gt;2.3&lt;/strong&gt; — List Assignment of Multiple Variables 7 .....................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-24-scope-8&quot;&gt;&lt;/a&gt;&lt;strong&gt;2.4&lt;/strong&gt; — Scope 8 .........................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-25-removing-a-variable-8&quot;&gt;&lt;/a&gt;&lt;strong&gt;2.5&lt;/strong&gt; — Removing a variable 8 ................................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-3-operator&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 3: Operator&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Operator penting untuk perbandingan, aritmatika, assignment, redirection stream, logika, dan manipulasi string.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-31-comparison-operators-9&quot;&gt;&lt;/a&gt;&lt;strong&gt;3.1&lt;/strong&gt; — Comparison Operators 9 .............................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-32-arithmetic-operators-9&quot;&gt;&lt;/a&gt;&lt;strong&gt;3.2&lt;/strong&gt; — Arithmetic Operators 9 ................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-33-assignment-operators-10&quot;&gt;&lt;/a&gt;&lt;strong&gt;3.3&lt;/strong&gt; — Assignment Operators 10 ...........................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-34-redirection-operators-10&quot;&gt;&lt;/a&gt;&lt;strong&gt;3.4&lt;/strong&gt; — Redirection Operators 10 ............................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-35-mixing-operand-types-the-type-of-the-left-operand-dictates-the-behavior-11&quot;&gt;&lt;/a&gt;&lt;strong&gt;3.5&lt;/strong&gt; — Mixing operand types, the type of the left operand dictates the behavior 11 ......................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-36-logical-operators-11&quot;&gt;&lt;/a&gt;&lt;strong&gt;3.6&lt;/strong&gt; — Logical Operators 11 ...................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-37-string-manipulation-operators-11&quot;&gt;&lt;/a&gt;&lt;strong&gt;3.7&lt;/strong&gt; — String Manipulation Operators 11 ..............................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-4-operator-khusus&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 4: Operator Khusus&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Operator khusus seperti array expression, call operator, dan dot sourcing untuk menjalankan script di scope tertentu.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-41-array-expression-operator-13&quot;&gt;&lt;/a&gt;&lt;strong&gt;4.1&lt;/strong&gt; — Array Expression Operator 13 .....................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-42-call-operation-13&quot;&gt;&lt;/a&gt;&lt;strong&gt;4.2&lt;/strong&gt; — Call Operation 13 .........................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-43-dot-sourcing-operator-13&quot;&gt;&lt;/a&gt;&lt;strong&gt;4.3&lt;/strong&gt; — Dot sourcing operator 13 ............................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-5-operasi-set-dasar&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 5: Operasi Set Dasar&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Operasi koleksi dasar: filter, sort, group, dan select/projection objek PowerShell.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-51-filtering-where-object-where-14&quot;&gt;&lt;/a&gt;&lt;strong&gt;5.1&lt;/strong&gt; — Filtering: Where-Object / where / ? 14 ......................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-52-ordering-sort-object-sort-14&quot;&gt;&lt;/a&gt;&lt;strong&gt;5.2&lt;/strong&gt; — Ordering: Sort-Object / sort 14 ..................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-53-grouping-group-object-group-15&quot;&gt;&lt;/a&gt;&lt;strong&gt;5.3&lt;/strong&gt; — Grouping: Group-Object / group 15 ..........................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-54-projecting-select-object-select-16&quot;&gt;&lt;/a&gt;&lt;strong&gt;5.4&lt;/strong&gt; — Projecting: Select-Object / select 16 ..........................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cmdlet/konsep cepat:&lt;/strong&gt; &lt;code&gt;Where-Object&lt;/code&gt;, &lt;code&gt;Sort-Object&lt;/code&gt;, &lt;code&gt;Group-Object&lt;/code&gt;, &lt;code&gt;Select-Object&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-6-logika-kondisional&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 6: Logika Kondisional&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Pola percabangan dengan if/else/elseif, negasi, dan perilaku truthy/falsy dalam PowerShell.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-61-if-else-and-else-if-17&quot;&gt;&lt;/a&gt;&lt;strong&gt;6.1&lt;/strong&gt; — if, else and else if 17 .....................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-62-negation-17&quot;&gt;&lt;/a&gt;&lt;strong&gt;6.2&lt;/strong&gt; — Negation 17 ..................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-63-if-conditional-shorthand-18&quot;&gt;&lt;/a&gt;&lt;strong&gt;6.3&lt;/strong&gt; — If conditional shorthand 18 .........................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-7-perulangan&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 7: Perulangan&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Teknik perulangan: foreach, for, ForEach-Object, continue, break, while, dan do/until.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-71-foreach-19&quot;&gt;&lt;/a&gt;&lt;strong&gt;7.1&lt;/strong&gt; — Foreach 19 .....................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-72-for-19&quot;&gt;&lt;/a&gt;&lt;strong&gt;7.2&lt;/strong&gt; — For 19 ............................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-73-foreach-method-19&quot;&gt;&lt;/a&gt;&lt;strong&gt;7.3&lt;/strong&gt; — ForEach() Method 19 ...................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-74-foreach-object-20&quot;&gt;&lt;/a&gt;&lt;strong&gt;7.4&lt;/strong&gt; — ForEach-Object 20 .......................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-75-continue-21&quot;&gt;&lt;/a&gt;&lt;strong&gt;7.5&lt;/strong&gt; — Continue 21 ...................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-76-break-21&quot;&gt;&lt;/a&gt;&lt;strong&gt;7.6&lt;/strong&gt; — Break 21 ........................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-77-while-22&quot;&gt;&lt;/a&gt;&lt;strong&gt;7.7&lt;/strong&gt; — While 22 .........................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-78-do-22&quot;&gt;&lt;/a&gt;&lt;strong&gt;7.8&lt;/strong&gt; — Do 22 .............................................................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cmdlet/konsep cepat:&lt;/strong&gt; &lt;code&gt;ForEach-Object&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-8-pernyataan-switch&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 8: Pernyataan Switch&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Penggunaan switch untuk banyak kondisi, termasuk wildcard, regex, file input, exact match, default, dan break.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-81-simple-switch&quot;&gt;&lt;/a&gt;&lt;strong&gt;8.1&lt;/strong&gt; — Simple Switch ...........................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-82-switch-statement-with-casesensitive-parameter&quot;&gt;&lt;/a&gt;&lt;strong&gt;8.2&lt;/strong&gt; — Switch Statement with CaseSensitive Parameter ...............................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-83-switch-statement-with-wildcard-parameter&quot;&gt;&lt;/a&gt;&lt;strong&gt;8.3&lt;/strong&gt; — Switch Statement with Wildcard Parameter ........................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-84-switch-statement-with-file-parameter&quot;&gt;&lt;/a&gt;&lt;strong&gt;8.4&lt;/strong&gt; — Switch Statement with File Parameter .................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-85-simple-switch-with-default-condition&quot;&gt;&lt;/a&gt;&lt;strong&gt;8.5&lt;/strong&gt; — Simple Switch with Default Condition ...................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-86-switch-statement-with-regex-parameter&quot;&gt;&lt;/a&gt;&lt;strong&gt;8.6&lt;/strong&gt; — Switch Statement with Regex Parameter ............................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-87-simple-switch-with-break&quot;&gt;&lt;/a&gt;&lt;strong&gt;8.7&lt;/strong&gt; — Simple Switch With Break ......................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-88-switch-statement-with-exact-parameter&quot;&gt;&lt;/a&gt;&lt;strong&gt;8.8&lt;/strong&gt; — Switch Statement with Exact Parameter ..............................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-89-switch-statement-with-expressions&quot;&gt;&lt;/a&gt;&lt;strong&gt;8.9&lt;/strong&gt; — Switch Statement with Expressions ......................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-9-string&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 9: String&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Pengolahan string: multi-line string, here-string, concatenation, karakter escape, literal string, dan format string.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-91-multiline-string&quot;&gt;&lt;/a&gt;&lt;strong&gt;9.1&lt;/strong&gt; — Multiline string ..........................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-92-here-string&quot;&gt;&lt;/a&gt;&lt;strong&gt;9.2&lt;/strong&gt; — Here-string ..............................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-93-concatenating-strings&quot;&gt;&lt;/a&gt;&lt;strong&gt;9.3&lt;/strong&gt; — Concatenating strings ............................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-94-special-characters&quot;&gt;&lt;/a&gt;&lt;strong&gt;9.4&lt;/strong&gt; — Special characters ..................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-95-creating-a-basic-string&quot;&gt;&lt;/a&gt;&lt;strong&gt;9.5&lt;/strong&gt; — Creating a basic string ...........................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-96-format-string&quot;&gt;&lt;/a&gt;&lt;strong&gt;9.6&lt;/strong&gt; — Format string ..........................................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-10-hashtable&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 10: HashTable&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; HashTable sebagai struktur key-value: membuat, membaca, menambah, menghapus, enumerasi, dan looping.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-101-access-a-hash-table-value-by-key&quot;&gt;&lt;/a&gt;&lt;strong&gt;10.1&lt;/strong&gt; — Access a hash table value by key ........................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-102-creating-a-hash-table&quot;&gt;&lt;/a&gt;&lt;strong&gt;10.2&lt;/strong&gt; — Creating a Hash Table ..........................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-103-add-a-key-value-pair-to-an-existing-hash-table&quot;&gt;&lt;/a&gt;&lt;strong&gt;10.3&lt;/strong&gt; — Add a key value pair to an existing hash table ..................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-104-remove-a-key-value-pair-from-an-existing-hash-table&quot;&gt;&lt;/a&gt;&lt;strong&gt;10.4&lt;/strong&gt; — Remove a key value pair from an existing hash table .....................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-105-enumerating-through-keys-and-key-value-pairs&quot;&gt;&lt;/a&gt;&lt;strong&gt;10.5&lt;/strong&gt; — Enumerating through keys and Key-Value Pairs ..............................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-106-looping-over-a-hash-table&quot;&gt;&lt;/a&gt;&lt;strong&gt;10.6&lt;/strong&gt; — Looping over a hash table ...................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-11-bekerja-dengan-objek&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 11: Bekerja dengan Objek&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Bekerja dengan objek: inspeksi member, menambah/menghapus properti, membuat objek custom, dan generic class.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-111-examining-an-object&quot;&gt;&lt;/a&gt;&lt;strong&gt;11.1&lt;/strong&gt; — Examining an object ...............................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-112-updating-objects&quot;&gt;&lt;/a&gt;&lt;strong&gt;11.2&lt;/strong&gt; — Updating Objects ...................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-113-creating-a-new-object&quot;&gt;&lt;/a&gt;&lt;strong&gt;11.3&lt;/strong&gt; — Creating a new object ............................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-114-creating-instances-of-generic-classes&quot;&gt;&lt;/a&gt;&lt;strong&gt;11.4&lt;/strong&gt; — Creating Instances of Generic Classes ................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-12-fungsi-powershell&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 12: Fungsi PowerShell&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Pembuatan fungsi: parameter dasar/lanjutan, mandatory parameter, validasi, dan fungsi tanpa parameter.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-121-basic-parameters&quot;&gt;&lt;/a&gt;&lt;strong&gt;12.1&lt;/strong&gt; — Basic Parameters ...................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-122-advanced-function&quot;&gt;&lt;/a&gt;&lt;strong&gt;12.2&lt;/strong&gt; — Advanced Function ...............................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-123-mandatory-parameters&quot;&gt;&lt;/a&gt;&lt;strong&gt;12.3&lt;/strong&gt; — Mandatory Parameters ........................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-124-parameter-validation&quot;&gt;&lt;/a&gt;&lt;strong&gt;12.4&lt;/strong&gt; — Parameter Validation ............................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-125-simple-function-with-no-parameters&quot;&gt;&lt;/a&gt;&lt;strong&gt;12.5&lt;/strong&gt; — Simple Function with No Parameters ..................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-13-kelas-powershell&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 13: Kelas PowerShell&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Class PowerShell: constructor, method, property, overload, inheritance, dan template class.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-131-listing-available-constructors-for-a-class&quot;&gt;&lt;/a&gt;&lt;strong&gt;13.1&lt;/strong&gt; — Listing available constructors for a class ............................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-132-methods-and-properties&quot;&gt;&lt;/a&gt;&lt;strong&gt;13.2&lt;/strong&gt; — Methods and properties .......................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-133-constructor-overloading&quot;&gt;&lt;/a&gt;&lt;strong&gt;13.3&lt;/strong&gt; — Constructor overloading .......................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-134-get-all-members-of-an-instance&quot;&gt;&lt;/a&gt;&lt;strong&gt;13.4&lt;/strong&gt; — Get All Members of an Instance ...........................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-135-basic-class-template&quot;&gt;&lt;/a&gt;&lt;strong&gt;13.5&lt;/strong&gt; — Basic Class Template ............................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-136-inheritance-from-parent-class-to-child-class&quot;&gt;&lt;/a&gt;&lt;strong&gt;13.6&lt;/strong&gt; — Inheritance from Parent Class to Child Class .....................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-14-modul-powershell&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 14: Modul PowerShell&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Modul PowerShell: manifest, struktur folder, ekspor fungsi/variabel, lokasi modul, dan visibilitas member.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-141-create-a-module-manifest&quot;&gt;&lt;/a&gt;&lt;strong&gt;14.1&lt;/strong&gt; — Create a Module Manifest .....................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-142-simple-module-example&quot;&gt;&lt;/a&gt;&lt;strong&gt;14.2&lt;/strong&gt; — Simple Module Example .......................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-143-exporting-a-variable-from-a-module&quot;&gt;&lt;/a&gt;&lt;strong&gt;14.3&lt;/strong&gt; — Exporting a Variable from a Module ...................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-144-structuring-powershell-modules&quot;&gt;&lt;/a&gt;&lt;strong&gt;14.4&lt;/strong&gt; — Structuring PowerShell Modules ..........................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-145-location-of-modules&quot;&gt;&lt;/a&gt;&lt;strong&gt;14.5&lt;/strong&gt; — Location of Modules ..............................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-146-module-member-visibility&quot;&gt;&lt;/a&gt;&lt;strong&gt;14.6&lt;/strong&gt; — Module Member Visibility .....................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-15-profil-powershell&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 15: Profil PowerShell&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Profil PowerShell untuk memuat otomatis fungsi, alias, dan konfigurasi pengguna saat shell dibuka.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-151-create-an-basic-profle&quot;&gt;&lt;/a&gt;&lt;strong&gt;15.1&lt;/strong&gt; — Create an basic profle ..........................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-16-properti-terhitung&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 16: Properti Terhitung&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Calculated properties untuk membentuk properti hasil kalkulasi saat memakai Select-Object.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-161-display-fle-size-in-kb-calculated-properties&quot;&gt;&lt;/a&gt;&lt;strong&gt;16.1&lt;/strong&gt; — Display fle size in KB-Calculated Properties .....................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-17-menggunakan-kelas-statis-net&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 17: Menggunakan Kelas Statis .NET&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Pemakaian class statis .NET seperti System.Math dan GUID dari PowerShell.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-171-adding-types&quot;&gt;&lt;/a&gt;&lt;strong&gt;17.1&lt;/strong&gt; — Adding types ...........................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-172-using-the-net-math-class&quot;&gt;&lt;/a&gt;&lt;strong&gt;17.2&lt;/strong&gt; — Using the .Net Math Class .....................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-173-creating-new-guid-instantly&quot;&gt;&lt;/a&gt;&lt;strong&gt;17.3&lt;/strong&gt; — Creating new GUID instantly ................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-18-variabel-bawaan&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 18: Variabel Bawaan&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Variabel bawaan penting seperti $PSScriptRoot, $Args, $PSItem, $?, dan $error.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-181-psscriptroot&quot;&gt;&lt;/a&gt;&lt;strong&gt;18.1&lt;/strong&gt; — $PSScriptRoot .........................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-182-args&quot;&gt;&lt;/a&gt;&lt;strong&gt;18.2&lt;/strong&gt; — $Args ......................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-183-psitem&quot;&gt;&lt;/a&gt;&lt;strong&gt;18.3&lt;/strong&gt; — $PSItem ...................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-184&quot;&gt;&lt;/a&gt;&lt;strong&gt;18.4&lt;/strong&gt; — $? .............................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-185-error&quot;&gt;&lt;/a&gt;&lt;strong&gt;18.5&lt;/strong&gt; — $error ......................................................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cmdlet/konsep cepat:&lt;/strong&gt; &lt;code&gt;$PSScriptRoot&lt;/code&gt;, &lt;code&gt;$Args&lt;/code&gt;, &lt;code&gt;$PSItem&lt;/code&gt;, &lt;code&gt;$?&lt;/code&gt;, &lt;code&gt;$error&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-19-variabel-otomatis&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 19: Variabel Otomatis&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Variabel otomatis seperti $OFS, $null, $pid, $true/$false, $_/$PSItem, dan $PSVersionTable.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-191-ofs&quot;&gt;&lt;/a&gt;&lt;strong&gt;19.1&lt;/strong&gt; — $OFS ........................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-192&quot;&gt;&lt;/a&gt;&lt;strong&gt;19.2&lt;/strong&gt; — $? .............................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-193-null&quot;&gt;&lt;/a&gt;&lt;strong&gt;19.3&lt;/strong&gt; — $null .........................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-194-error&quot;&gt;&lt;/a&gt;&lt;strong&gt;19.4&lt;/strong&gt; — $error ......................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-195-pid&quot;&gt;&lt;/a&gt;&lt;strong&gt;19.5&lt;/strong&gt; — $pid .........................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-196-boolean-values&quot;&gt;&lt;/a&gt;&lt;strong&gt;19.6&lt;/strong&gt; — Boolean values ......................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-197-psitem&quot;&gt;&lt;/a&gt;&lt;strong&gt;19.7&lt;/strong&gt; — $_ / $PSItem ..........................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-198-psversiontable&quot;&gt;&lt;/a&gt;&lt;strong&gt;19.8&lt;/strong&gt; — $PSVersionTable ...................................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cmdlet/konsep cepat:&lt;/strong&gt; &lt;code&gt;$OFS&lt;/code&gt;, &lt;code&gt;$?&lt;/code&gt;, &lt;code&gt;$null&lt;/code&gt;, &lt;code&gt;$error&lt;/code&gt;, &lt;code&gt;$pid&lt;/code&gt;, &lt;code&gt;$_&lt;/code&gt;, &lt;code&gt;$PSItem&lt;/code&gt;, &lt;code&gt;$PSVersionTable&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-20-variabel-lingkungan&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 20: Variabel Lingkungan&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Mengakses environment variables melalui drive Env: dan notasi $env:.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-201-windows-environment-variables-are-visible-as-a-ps-drive-called-env&quot;&gt;&lt;/a&gt;&lt;strong&gt;20.1&lt;/strong&gt; — Windows environment variables are visible as a PS drive called Env: ............................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-202-instant-call-of-environment-variables-with-env&quot;&gt;&lt;/a&gt;&lt;strong&gt;20.2&lt;/strong&gt; — Instant call of Environment Variables with $env: ..............................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cmdlet/konsep cepat:&lt;/strong&gt; &lt;code&gt;$env&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-21-splatting&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 21: Splatting&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Splatting untuk mengirim banyak parameter memakai hashtable agar command lebih ringkas dan reusable.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-211-piping-and-splatting&quot;&gt;&lt;/a&gt;&lt;strong&gt;21.1&lt;/strong&gt; — Piping and Splatting ...............................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-212-passing-a-switch-parameter-using-splatting&quot;&gt;&lt;/a&gt;&lt;strong&gt;21.2&lt;/strong&gt; — Passing a Switch parameter using Splatting ......................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-213-splatting-from-top-level-function-to-a-series-of-inner-function&quot;&gt;&lt;/a&gt;&lt;strong&gt;21.3&lt;/strong&gt; — Splatting From Top Level Function to a Series of Inner Function ....................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-214-splatting-parameters&quot;&gt;&lt;/a&gt;&lt;strong&gt;21.4&lt;/strong&gt; — Splatting parameters ............................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-22-stream-powershell&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 22: Stream PowerShell&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Stream output PowerShell: output, error, warning, verbose, debug, information, dan preference variable.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-221-write-output&quot;&gt;&lt;/a&gt;&lt;strong&gt;22.1&lt;/strong&gt; — Write-Output ..........................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-222-write-preferences&quot;&gt;&lt;/a&gt;&lt;strong&gt;22.2&lt;/strong&gt; — Write Preferences .................................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cmdlet/konsep cepat:&lt;/strong&gt; &lt;code&gt;Write-Output&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-23-mengirim-email&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 23: Mengirim Email&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Pengiriman email dengan Send-MailMessage dan SMTPClient.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-231-send-mailmessage-with-predefned-parameters&quot;&gt;&lt;/a&gt;&lt;strong&gt;23.1&lt;/strong&gt; — Send-MailMessage with predefned parameters ...............................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-232-simple-send-mailmessage&quot;&gt;&lt;/a&gt;&lt;strong&gt;23.2&lt;/strong&gt; — Simple Send-MailMessage ...................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-233-smtpclient-mail-with-txt-fle-in-body-message&quot;&gt;&lt;/a&gt;&lt;strong&gt;23.3&lt;/strong&gt; — SMTPClient-Mail with .txt fle in body message ...............................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-24-powershell-remoting&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 24: PowerShell Remoting&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; PowerShell Remoting: Enter-PSSession, Invoke-Command, serialization, trusted hosts, dan cleanup PSSession.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-241-connecting-to-a-remote-server-via-powershell&quot;&gt;&lt;/a&gt;&lt;strong&gt;24.1&lt;/strong&gt; — Connecting to a Remote Server via PowerShell ................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-242-run-commands-on-a-remote-computer&quot;&gt;&lt;/a&gt;&lt;strong&gt;24.2&lt;/strong&gt; — Run commands on a Remote Computer ...........................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-243-enabling-powershell-remoting&quot;&gt;&lt;/a&gt;&lt;strong&gt;24.3&lt;/strong&gt; — Enabling PowerShell Remoting ...........................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-244-a-best-practise-for-automatically-cleaning-up-pssessions&quot;&gt;&lt;/a&gt;&lt;strong&gt;24.4&lt;/strong&gt; — A best practise for automatically cleaning-up PSSessions ..............................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-25-pipeline-powershell&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 25: Pipeline PowerShell&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Pipeline berbasis objek dan cara membuat fungsi yang menerima input pipeline.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-251-writing-functions-with-advanced-lifecycle&quot;&gt;&lt;/a&gt;&lt;strong&gt;25.1&lt;/strong&gt; — Writing Functions with Advanced Lifecycle ........................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-252-basic-pipeline-support-in-functions&quot;&gt;&lt;/a&gt;&lt;strong&gt;25.2&lt;/strong&gt; — Basic Pipeline Support in Functions ....................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-253-working-concept-of-pipeline&quot;&gt;&lt;/a&gt;&lt;strong&gt;25.3&lt;/strong&gt; — Working concept of pipeline ...............................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-26-background-job-powershell&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 26: Background Job PowerShell&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Background jobs untuk menjalankan proses panjang tanpa mengunci prompt.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-261-basic-job-creation&quot;&gt;&lt;/a&gt;&lt;strong&gt;26.1&lt;/strong&gt; — Basic job creation ..................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-262-basic-job-management&quot;&gt;&lt;/a&gt;&lt;strong&gt;26.2&lt;/strong&gt; — Basic job management ........................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-27-perilaku-return-di-powershell&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 27: Perilaku Return di PowerShell&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Perilaku return dan output pipeline dalam fungsi/script PowerShell.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-271-early-exit&quot;&gt;&lt;/a&gt;&lt;strong&gt;27.1&lt;/strong&gt; — Early exit .................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-272-gotcha-return-in-the-pipeline&quot;&gt;&lt;/a&gt;&lt;strong&gt;27.2&lt;/strong&gt; — Gotcha! Return in the pipeline .............................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-273-return-with-a-value&quot;&gt;&lt;/a&gt;&lt;strong&gt;27.3&lt;/strong&gt; — Return with a value ...............................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-274-how-to-work-with-functions-returns&quot;&gt;&lt;/a&gt;&lt;strong&gt;27.4&lt;/strong&gt; — How to work with functions returns ....................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-275-gotcha-ignoring-unwanted-output&quot;&gt;&lt;/a&gt;&lt;strong&gt;27.5&lt;/strong&gt; — Gotcha! Ignoring unwanted output .....................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-28-parsing-csv&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 28: Parsing CSV&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Import CSV dan casting tipe data hasil Import-Csv.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-281-basic-usage-of-import-csv&quot;&gt;&lt;/a&gt;&lt;strong&gt;28.1&lt;/strong&gt; — Basic usage of Import-Csv ...................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-282-import-from-csv-and-cast-properties-to-correct-type&quot;&gt;&lt;/a&gt;&lt;strong&gt;28.2&lt;/strong&gt; — Import from CSV and cast properties to correct type .....................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cmdlet/konsep cepat:&lt;/strong&gt; &lt;code&gt;Import-Csv&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-29-bekerja-dengan-file-xml&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 29: Bekerja dengan File XML&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Membaca, menulis, memanipulasi XML, XPath, namespace, dan XmlWriter.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-291-accessing-an-xml-file&quot;&gt;&lt;/a&gt;&lt;strong&gt;29.1&lt;/strong&gt; — Accessing an XML File ...........................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-292-creating-an-xml-document-using-xmlwriter&quot;&gt;&lt;/a&gt;&lt;strong&gt;29.2&lt;/strong&gt; — Creating an XML Document using XmlWriter() .................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-293-adding-snippets-of-xml-to-current-xmldocument&quot;&gt;&lt;/a&gt;&lt;strong&gt;29.3&lt;/strong&gt; — Adding snippets of XML to current XMLDocument ...........................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-30-restful-api&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 30: RESTful API&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Konsumsi REST API memakai Invoke-RestMethod untuk GET, POST, PUT, dan DELETE.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-301-post-message-to-hipchat&quot;&gt;&lt;/a&gt;&lt;strong&gt;30.1&lt;/strong&gt; — Post Message to hipChat ......................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-302-using-rest-with-powershell-objects-to-get-and-post-many-items&quot;&gt;&lt;/a&gt;&lt;strong&gt;30.2&lt;/strong&gt; — Using REST with PowerShell Objects to GET and POST many items ..............................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-303-use-slackcom-incoming-webhooks&quot;&gt;&lt;/a&gt;&lt;strong&gt;30.3&lt;/strong&gt; — Use Slack.com Incoming Webhooks ..................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-304-using-rest-with-powershell-objects-to-get-and-put-individual-data&quot;&gt;&lt;/a&gt;&lt;strong&gt;30.4&lt;/strong&gt; — Using REST with PowerShell Objects to Get and Put individual data .............................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-305-using-rest-with-powershell-to-delete-items&quot;&gt;&lt;/a&gt;&lt;strong&gt;30.5&lt;/strong&gt; — Using REST with PowerShell to Delete items .....................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-31-query-sql-powershell&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 31: Query SQL PowerShell&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Menjalankan query SQL dari PowerShell.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-311-sqlexample&quot;&gt;&lt;/a&gt;&lt;strong&gt;31.1&lt;/strong&gt; — SQLExample ............................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-312-sqlquery&quot;&gt;&lt;/a&gt;&lt;strong&gt;31.2&lt;/strong&gt; — SQLQuery ...............................................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-32-regular-expression&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 32: Regular Expression&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Regex untuk match, replace, escape karakter khusus, dan multiple matches.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-321-single-match&quot;&gt;&lt;/a&gt;&lt;strong&gt;32.1&lt;/strong&gt; — Single match ..........................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-322-replace&quot;&gt;&lt;/a&gt;&lt;strong&gt;32.2&lt;/strong&gt; — Replace ..................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-323-replace-text-with-dynamic-value-using-a-matchevalutor&quot;&gt;&lt;/a&gt;&lt;strong&gt;32.3&lt;/strong&gt; — Replace text with dynamic value using a MatchEvalutor ................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-324-escape-special-characters&quot;&gt;&lt;/a&gt;&lt;strong&gt;32.4&lt;/strong&gt; — Escape special characters ...................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-325-multiple-matches&quot;&gt;&lt;/a&gt;&lt;strong&gt;32.5&lt;/strong&gt; — Multiple matches ...................................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-33-alias&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 33: Alias&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Membaca dan membuat alias cmdlet.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-331-get-alias&quot;&gt;&lt;/a&gt;&lt;strong&gt;33.1&lt;/strong&gt; — Get-Alias .................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-332-set-alias&quot;&gt;&lt;/a&gt;&lt;strong&gt;33.2&lt;/strong&gt; — Set-Alias .................................................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cmdlet/konsep cepat:&lt;/strong&gt; &lt;code&gt;Get-Alias&lt;/code&gt;, &lt;code&gt;Set-Alias&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-34-progress-bar&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 34: Progress Bar&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Menampilkan progress proses dengan Write-Progress.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-341-simple-use-of-progress-bar&quot;&gt;&lt;/a&gt;&lt;strong&gt;34.1&lt;/strong&gt; — Simple use of progress bar ..................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-342-usage-of-inner-progress-bar&quot;&gt;&lt;/a&gt;&lt;strong&gt;34.2&lt;/strong&gt; — Usage of inner progress bar ...............................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-35-command-line-powershellexe&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 35: Command-Line PowerShell.exe&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Opsi command-line PowerShell.exe untuk menjalankan command, script, policy, profile, dan window style.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-351-executing-a-command-100&quot;&gt;&lt;/a&gt;&lt;strong&gt;35.1&lt;/strong&gt; — Executing a command 100 ........................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-352-executing-a-script-fle-101&quot;&gt;&lt;/a&gt;&lt;strong&gt;35.2&lt;/strong&gt; — Executing a script fle 101 .........................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-36-penamaan-cmdlet&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 36: Penamaan Cmdlet&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Standar penamaan cmdlet Verb-Noun.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-361-verbs-102&quot;&gt;&lt;/a&gt;&lt;strong&gt;36.1&lt;/strong&gt; — Verbs 102 .....................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-362-nouns-102&quot;&gt;&lt;/a&gt;&lt;strong&gt;36.2&lt;/strong&gt; — Nouns 102 ...................................................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-37-menjalankan-executable&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 37: Menjalankan Executable&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Menjalankan aplikasi GUI/console dan membaca exit code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-371-gui-applications-103&quot;&gt;&lt;/a&gt;&lt;strong&gt;37.1&lt;/strong&gt; — GUI Applications 103 ..................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-372-console-streams-103&quot;&gt;&lt;/a&gt;&lt;strong&gt;37.2&lt;/strong&gt; — Console Streams 103 .................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-373-exit-codes-103&quot;&gt;&lt;/a&gt;&lt;strong&gt;37.3&lt;/strong&gt; — Exit Codes 103 ............................................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-38-prasyarat-script&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 38: Prasyarat Script&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Menetapkan prasyarat script seperti versi minimum dan administrator.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-381-enforce-minimum-version-of-powershell-host-104&quot;&gt;&lt;/a&gt;&lt;strong&gt;38.1&lt;/strong&gt; — Enforce minimum version of PowerShell host 104 ..................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-382-enforce-running-the-script-as-administrator&quot;&gt;&lt;/a&gt;&lt;strong&gt;38.2&lt;/strong&gt; — Enforce running the script as administrator ....................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-39-sistem-bantuan&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 39: Sistem Bantuan&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Memakai Get-Help, update help, contoh, full help, online help, dan parameter-specific help.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-391-updating-the-help-system&quot;&gt;&lt;/a&gt;&lt;strong&gt;39.1&lt;/strong&gt; — Updating the Help System .................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-392-using-get-help&quot;&gt;&lt;/a&gt;&lt;strong&gt;39.2&lt;/strong&gt; — Using Get-Help ....................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-393-viewing-online-version-of-a-help-topic&quot;&gt;&lt;/a&gt;&lt;strong&gt;39.3&lt;/strong&gt; — Viewing online version of a help topic ..............................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-394-viewing-examples&quot;&gt;&lt;/a&gt;&lt;strong&gt;39.4&lt;/strong&gt; — Viewing Examples ...............................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-395-viewing-the-full-help-page&quot;&gt;&lt;/a&gt;&lt;strong&gt;39.5&lt;/strong&gt; — Viewing the Full Help Page ................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-396-viewing-help-for-a-specifc-parameter&quot;&gt;&lt;/a&gt;&lt;strong&gt;39.6&lt;/strong&gt; — Viewing help for a specifc parameter .............................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cmdlet/konsep cepat:&lt;/strong&gt; &lt;code&gt;Get-Help&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-40-modul-script-dan-fungsi&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 40: Modul, Script, dan Fungsi&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Perbedaan function, script, module, dan advanced function.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-401-function&quot;&gt;&lt;/a&gt;&lt;strong&gt;40.1&lt;/strong&gt; — Function ...............................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-402-script&quot;&gt;&lt;/a&gt;&lt;strong&gt;40.2&lt;/strong&gt; — Script ....................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-403-module&quot;&gt;&lt;/a&gt;&lt;strong&gt;40.3&lt;/strong&gt; — Module .................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-404-advanced-functions&quot;&gt;&lt;/a&gt;&lt;strong&gt;40.4&lt;/strong&gt; — Advanced Functions ..........................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-41-konvensi-penamaan&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 41: Konvensi Penamaan&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Konvensi penamaan fungsi agar konsisten dan mudah dipahami.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-411-functions&quot;&gt;&lt;/a&gt;&lt;strong&gt;41.1&lt;/strong&gt; — Functions ...............................................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-42-parameter-umum&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 42: Parameter Umum&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Parameter umum seperti ErrorAction untuk mengontrol error.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-421-erroraction-parameter&quot;&gt;&lt;/a&gt;&lt;strong&gt;42.1&lt;/strong&gt; — ErrorAction parameter .......................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-43-parameter-set&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 43: Parameter Set&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Parameter set untuk membatasi kombinasi parameter dan memaksa pilihan valid.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-431-parameter-set-to-enforce-the-use-of-a-parameter-when-a-other-is-selected&quot;&gt;&lt;/a&gt;&lt;strong&gt;43.1&lt;/strong&gt; — Parameter set to enforce the use of a parameter when a other is selected ...............................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-432-parameter-set-to-limit-the-combination-of-parameters&quot;&gt;&lt;/a&gt;&lt;strong&gt;43.2&lt;/strong&gt; — Parameter set to limit the combination of parameters .................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-44-parameter-dinamis&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 44: Parameter Dinamis&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Dynamic parameter untuk menambahkan parameter saat runtime.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-441-simpledynamic-parameter&quot;&gt;&lt;/a&gt;&lt;strong&gt;44.1&lt;/strong&gt; — &amp;quot;Simple&amp;quot;dynamic parameter ............................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-45-gui-di-powershell&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 45: GUI di PowerShell&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Pembuatan GUI WPF sederhana dari PowerShell.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-451-wpf-gui-for-get-service-cmdlet&quot;&gt;&lt;/a&gt;&lt;strong&gt;45.1&lt;/strong&gt; — WPF GUI for Get-Service cmdlet .......................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cmdlet/konsep cepat:&lt;/strong&gt; &lt;code&gt;Get-Service&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-46-url-encodedecode&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 46: URL Encode/Decode&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Encode dan decode URL memakai HttpUtility atau URI class.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-461-encode-query-string-withsystemwebhttputilityurlencode&quot;&gt;&lt;/a&gt;&lt;strong&gt;46.1&lt;/strong&gt; — Encode Query String with&lt;code&gt;[System.Web.HttpUtility]::UrlEncode()&lt;/code&gt; ...............................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-462-quick-start-encoding&quot;&gt;&lt;/a&gt;&lt;strong&gt;46.2&lt;/strong&gt; — Quick Start: Encoding .........................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-463-quick-start-decoding&quot;&gt;&lt;/a&gt;&lt;strong&gt;46.3&lt;/strong&gt; — Quick Start: Decoding ........................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-464-encode-query-string-withuriescapedatastring&quot;&gt;&lt;/a&gt;&lt;strong&gt;46.4&lt;/strong&gt; — Encode Query String with&lt;code&gt;[uri]::EscapeDataString()&lt;/code&gt; ....................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-465-decode-url-withuriunescapedatastring&quot;&gt;&lt;/a&gt;&lt;strong&gt;46.5&lt;/strong&gt; — Decode URL with&lt;code&gt;[uri]::UnescapeDataString()&lt;/code&gt; ..............................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-466-decode-url-withsystemwebhttputilityurldecode&quot;&gt;&lt;/a&gt;&lt;strong&gt;46.6&lt;/strong&gt; — Decode URL with&lt;code&gt;[System.Web.HttpUtility]::UrlDecode()&lt;/code&gt; ............................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-47-penanganan-error&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 47: Penanganan Error&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Jenis error dan dasar penanganan error.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-471-error-types&quot;&gt;&lt;/a&gt;&lt;strong&gt;47.1&lt;/strong&gt; — Error Types ..........................................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-48-manajemen-paket&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 48: Manajemen Paket&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Mencari, menginstall, update, dan uninstall modul PowerShell.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-481-create-the-default-powershell-module-repository&quot;&gt;&lt;/a&gt;&lt;strong&gt;48.1&lt;/strong&gt; — Create the default PowerShell Module Repository ..........................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-482-find-a-module-by-name&quot;&gt;&lt;/a&gt;&lt;strong&gt;48.2&lt;/strong&gt; — Find a module by name ....................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-483-install-a-module-by-name&quot;&gt;&lt;/a&gt;&lt;strong&gt;48.3&lt;/strong&gt; — Install a Module by name ..................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-484-uninstall-a-module-my-name-and-version&quot;&gt;&lt;/a&gt;&lt;strong&gt;48.4&lt;/strong&gt; — Uninstall a module my name and version .......................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-485-update-a-module-by-name&quot;&gt;&lt;/a&gt;&lt;strong&gt;48.5&lt;/strong&gt; — Update a module by name ...............................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-486-find-a-powershell-module-using-a-pattern&quot;&gt;&lt;/a&gt;&lt;strong&gt;48.6&lt;/strong&gt; — Find a PowerShell module using a pattern ......................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-49-komunikasi-tcp&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 49: Komunikasi TCP&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Komunikasi TCP listener/sender menggunakan PowerShell.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-491-tcp-listener&quot;&gt;&lt;/a&gt;&lt;strong&gt;49.1&lt;/strong&gt; — TCP listener ..........................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-492-tcp-sender&quot;&gt;&lt;/a&gt;&lt;strong&gt;49.2&lt;/strong&gt; — TCP Sender .........................................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-50-workflow-powershell&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 50: Workflow PowerShell&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Workflow PowerShell untuk proses background, paralel, dan input parameter.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-501-workfow-with-input-parameters&quot;&gt;&lt;/a&gt;&lt;strong&gt;50.1&lt;/strong&gt; — Workfow with Input Parameters .......................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-502-simple-workfow-example&quot;&gt;&lt;/a&gt;&lt;strong&gt;50.2&lt;/strong&gt; — Simple Workfow Example ................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-503-run-workfow-as-a-background-job&quot;&gt;&lt;/a&gt;&lt;strong&gt;50.3&lt;/strong&gt; — Run Workfow as a Background Job ...............................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-504-add-a-parallel-block-to-a-workfow&quot;&gt;&lt;/a&gt;&lt;strong&gt;50.4&lt;/strong&gt; — Add a Parallel Block to a Workfow .................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-51-managed-code-c-vb&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 51: Managed Code C# / VB&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Menyematkan kode C# atau VB.NET dengan Add-Type.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-511-c-example&quot;&gt;&lt;/a&gt;&lt;strong&gt;51.1&lt;/strong&gt; — C# Example ...........................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-512-vbnet-example&quot;&gt;&lt;/a&gt;&lt;strong&gt;51.2&lt;/strong&gt; — VB.NET Example ..................................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-52-download-artifact-dari-artifactory&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 52: Download Artifact dari Artifactory&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Contoh script untuk mengambil artifact terbaru dari Artifactory.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-521-powershell-script-for-downloading-the-latest-artifact&quot;&gt;&lt;/a&gt;&lt;strong&gt;52.1&lt;/strong&gt; — PowerShell Script for downloading the latest artifact ....................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-53-comment-based-help&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 53: Comment-Based Help&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Help berbasis komentar agar fungsi/script dapat dibaca oleh Get-Help.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-531-function-comment-based-help&quot;&gt;&lt;/a&gt;&lt;strong&gt;53.1&lt;/strong&gt; — Function comment-based help ..........................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-532-script-comment-based-help&quot;&gt;&lt;/a&gt;&lt;strong&gt;53.2&lt;/strong&gt; — Script comment-based help ..............................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-54-modul-archive&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 54: Modul Archive&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Compress-Archive dan Expand-Archive untuk ZIP.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-541-compress-archive-with-wildcard&quot;&gt;&lt;/a&gt;&lt;strong&gt;54.1&lt;/strong&gt; — Compress-Archive with wildcard .......................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-542-update-existing-zip-with-compress-archive&quot;&gt;&lt;/a&gt;&lt;strong&gt;54.2&lt;/strong&gt; — Update existing ZIP with Compress-Archive ...................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-543-extract-a-zip-with-expand-archive&quot;&gt;&lt;/a&gt;&lt;strong&gt;54.3&lt;/strong&gt; — Extract a Zip with Expand-Archive ....................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cmdlet/konsep cepat:&lt;/strong&gt; &lt;code&gt;Compress-Archive&lt;/code&gt;, &lt;code&gt;Expand-Archive&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-55-otomasi-infrastruktur&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 55: Otomasi Infrastruktur&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Otomasi infrastruktur dan contoh test integrasi black-box.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-551-simple-script-for-black-box-integration-test-of-console-applications&quot;&gt;&lt;/a&gt;&lt;strong&gt;55.1&lt;/strong&gt; — Simple script for black-box integration test of console applications ............................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-56-psscriptanalyzer&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 56: PSScriptAnalyzer&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; PSScriptAnalyzer untuk static analysis script PowerShell.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-561-analyzing-scripts-with-the-built-in-preset-rulesets&quot;&gt;&lt;/a&gt;&lt;strong&gt;56.1&lt;/strong&gt; — Analyzing scripts with the built-in preset rulesets ...........................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-562-analyzing-scripts-against-every-built-in-rule&quot;&gt;&lt;/a&gt;&lt;strong&gt;56.2&lt;/strong&gt; — Analyzing scripts against every built-in rule ...................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-563-list-all-built-in-rules&quot;&gt;&lt;/a&gt;&lt;strong&gt;56.3&lt;/strong&gt; — List all built-in rules .............................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-57-desired-state-configuration-dsc&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 57: Desired State Configuration DSC&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; DSC untuk mendefinisikan konfigurasi target dan resource.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-571-simple-example-enabling-windowsfeature&quot;&gt;&lt;/a&gt;&lt;strong&gt;57.1&lt;/strong&gt; — Simple example-Enabling WindowsFeature ...................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-572-starting-dsc-mof-on-remote-machine&quot;&gt;&lt;/a&gt;&lt;strong&gt;57.2&lt;/strong&gt; — Starting DSC (mof) on remote machine ..........................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-573-importing-psd1-data-fle-into-local-variable&quot;&gt;&lt;/a&gt;&lt;strong&gt;57.3&lt;/strong&gt; — Importing psd1 (data fle) into local variable ...................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-574-list-available-dsc-resources&quot;&gt;&lt;/a&gt;&lt;strong&gt;57.4&lt;/strong&gt; — List available DSC Resources ............................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-575-importing-resources-for-use-in-dsc&quot;&gt;&lt;/a&gt;&lt;strong&gt;57.5&lt;/strong&gt; — Importing resources for use in DSC ..................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-58-shouldprocess&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 58: ShouldProcess&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; ShouldProcess untuk dukungan -WhatIf dan -Confirm.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-581-full-usage-example&quot;&gt;&lt;/a&gt;&lt;strong&gt;58.1&lt;/strong&gt; — Full Usage Example ............................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-582-adding-whatif-and-confrm-support-to-your-cmdlet&quot;&gt;&lt;/a&gt;&lt;strong&gt;58.2&lt;/strong&gt; — Adding-WhatIf and-Confrm support to your cmdlet ..................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-583-using-shouldprocess-with-one-argument&quot;&gt;&lt;/a&gt;&lt;strong&gt;58.3&lt;/strong&gt; — Using ShouldProcess() with one argument .....................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-59-scheduled-tasks&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 59: Scheduled Tasks&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Scheduled Tasks untuk menjalankan script PowerShell secara terjadwal.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-591-run-powershell-script-in-scheduled-task&quot;&gt;&lt;/a&gt;&lt;strong&gt;59.1&lt;/strong&gt; — Run PowerShell Script in Scheduled Task .........................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-60-modul-ise&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 60: Modul ISE&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; PowerShell ISE dan fitur scripting/debugging.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-601-test-scripts&quot;&gt;&lt;/a&gt;&lt;strong&gt;60.1&lt;/strong&gt; — Test Scripts ..........................................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-61-resource-dsc-berbasis-class&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 61: Resource DSC Berbasis Class&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Membuat DSC resource berbasis class.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-611-create-a-dsc-resource-skeleton-class&quot;&gt;&lt;/a&gt;&lt;strong&gt;61.1&lt;/strong&gt; — Create a DSC Resource Skeleton Class .............................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-612-dsc-resource-skeleton-with-key-property&quot;&gt;&lt;/a&gt;&lt;strong&gt;61.2&lt;/strong&gt; — DSC Resource Skeleton with Key Property ......................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-613-dsc-resource-with-mandatory-property&quot;&gt;&lt;/a&gt;&lt;strong&gt;61.3&lt;/strong&gt; — DSC Resource with Mandatory Property ..........................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-614-dsc-resource-with-required-methods&quot;&gt;&lt;/a&gt;&lt;strong&gt;61.4&lt;/strong&gt; — DSC Resource with Required Methods .............................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-62-wmi-dan-cim&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 62: WMI dan CIM&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Query WMI/CIM, namespace, class, dan instance.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-621-querying-objects&quot;&gt;&lt;/a&gt;&lt;strong&gt;62.1&lt;/strong&gt; — Querying objects .................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-622-classes-and-namespaces&quot;&gt;&lt;/a&gt;&lt;strong&gt;62.2&lt;/strong&gt; — Classes and namespaces ..................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-63-modul-activedirectory&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 63: Modul ActiveDirectory&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Cmdlet ActiveDirectory untuk user, group, computer, dan object AD.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-631-users&quot;&gt;&lt;/a&gt;&lt;strong&gt;63.1&lt;/strong&gt; — Users .....................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-632-module&quot;&gt;&lt;/a&gt;&lt;strong&gt;63.2&lt;/strong&gt; — Module .................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-633-groups&quot;&gt;&lt;/a&gt;&lt;strong&gt;63.3&lt;/strong&gt; — Groups ..................................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-634-computers&quot;&gt;&lt;/a&gt;&lt;strong&gt;63.4&lt;/strong&gt; — Computers ...........................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-635-objects&quot;&gt;&lt;/a&gt;&lt;strong&gt;63.5&lt;/strong&gt; — Objects .................................................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-64-modul-sharepoint&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 64: Modul SharePoint&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Modul SharePoint untuk snap-in, list, dan feature site collection.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-641-loading-sharepoint-snap-in&quot;&gt;&lt;/a&gt;&lt;strong&gt;64.1&lt;/strong&gt; — Loading SharePoint Snap-In ..............................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-642-iterating-over-all-lists-of-a-site-collection&quot;&gt;&lt;/a&gt;&lt;strong&gt;64.2&lt;/strong&gt; — Iterating over all lists of a site collection .........................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-643-get-all-installed-features-on-a-site-collection&quot;&gt;&lt;/a&gt;&lt;strong&gt;64.3&lt;/strong&gt; — Get all installed features on a site collection ...................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-65-psake&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 65: Psake&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Psake untuk build/task automation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-651-basic-outline&quot;&gt;&lt;/a&gt;&lt;strong&gt;65.1&lt;/strong&gt; — Basic outline .........................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-652-formattaskname-example&quot;&gt;&lt;/a&gt;&lt;strong&gt;65.2&lt;/strong&gt; — FormatTaskName example ..............................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-653-run-task-conditionally&quot;&gt;&lt;/a&gt;&lt;strong&gt;65.3&lt;/strong&gt; — Run Task conditionally .......................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-654-continueonerror&quot;&gt;&lt;/a&gt;&lt;strong&gt;65.4&lt;/strong&gt; — ContinueOnError .................................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-66-pester&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 66: Pester&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Pester untuk unit testing PowerShell.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-661-getting-started-with-pester&quot;&gt;&lt;/a&gt;&lt;strong&gt;66.1&lt;/strong&gt; — Getting Started with Pester ................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-67-secret-dan-credential&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 67: Secret dan Credential&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Menangani credential dan secret dengan SecureString/Export-CliXml.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-671-accessing-the-plaintext-password&quot;&gt;&lt;/a&gt;&lt;strong&gt;67.1&lt;/strong&gt; — Accessing the Plaintext Password .....................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-672-prompting-for-credentials&quot;&gt;&lt;/a&gt;&lt;strong&gt;67.2&lt;/strong&gt; — Prompting for Credentials .................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-673-working-with-stored-credentials&quot;&gt;&lt;/a&gt;&lt;strong&gt;67.3&lt;/strong&gt; — Working with Stored Credentials ......................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-674-storing-the-credentials-in-encrypted-form-and-passing-it-as-parameter-when-required&quot;&gt;&lt;/a&gt;&lt;strong&gt;67.4&lt;/strong&gt; — Storing the credentials in Encrypted form and Passing it as parameter when Required&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-68-security-dan-cryptography&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 68: Security dan Cryptography&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Hashing dan kriptografi via .NET.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-681-calculating-a-strings-hash-codes-via-net-cryptography&quot;&gt;&lt;/a&gt;&lt;strong&gt;68.1&lt;/strong&gt; — Calculating a string&amp;#39;s hash codes via .Net Cryptography ...............................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-69-signing-scripts&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 69: Signing Scripts&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Menandatangani script dan mengatur execution policy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-691-signing-a-script&quot;&gt;&lt;/a&gt;&lt;strong&gt;69.1&lt;/strong&gt; — Signing a script ....................................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-692-bypassing-execution-policy-for-a-single-script&quot;&gt;&lt;/a&gt;&lt;strong&gt;69.2&lt;/strong&gt; — Bypassing execution policy for a single script ................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-693-changing-the-execution-policy-using-set-executionpolicy&quot;&gt;&lt;/a&gt;&lt;strong&gt;69.3&lt;/strong&gt; — Changing the execution policy using Set-ExecutionPolicy .............................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-694-get-the-current-execution-policy&quot;&gt;&lt;/a&gt;&lt;strong&gt;69.4&lt;/strong&gt; — Get the current execution policy .......................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-695-getting-the-signature-from-a-signed-script&quot;&gt;&lt;/a&gt;&lt;strong&gt;69.5&lt;/strong&gt; — Getting the signature from a signed script ......................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-696-creating-a-self-signed-code-signing-certifcate-for-testing&quot;&gt;&lt;/a&gt;&lt;strong&gt;69.6&lt;/strong&gt; — Creating a self-signed code signing certifcate for testing ............................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cmdlet/konsep cepat:&lt;/strong&gt; &lt;code&gt;Set-ExecutionPolicy&lt;/code&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-70-anonimisasi-ip&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 70: Anonimisasi IP&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Anonimisasi IPv4/IPv6 dalam file teks dengan regex.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-701-anonymize-ip-address-in-text-fle&quot;&gt;&lt;/a&gt;&lt;strong&gt;70.1&lt;/strong&gt; — Anonymize IP address in text fle .......................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-71-aws-rekognition&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 71: AWS Rekognition&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Contoh AWS Rekognition dari PowerShell.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-711-detect-image-labels-with-aws-rekognition&quot;&gt;&lt;/a&gt;&lt;strong&gt;71.1&lt;/strong&gt; — Detect Image Labels with AWS Rekognition .....................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-712-compare-facial-similarity-with-aws-rekognition&quot;&gt;&lt;/a&gt;&lt;strong&gt;71.2&lt;/strong&gt; — Compare Facial Similarity with AWS Rekognition ...........................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a id=&quot;bab-72-aws-s3&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Bab 72: AWS S3&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Inti:&lt;/strong&gt; Operasi dasar AWS S3: bucket, upload, dan delete.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Topik penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a id=&quot;bagian-721-create-a-new-s3-bucket&quot;&gt;&lt;/a&gt;&lt;strong&gt;72.1&lt;/strong&gt; — Create a new S3 Bucket ......................................................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-722-upload-a-local-file-into-an-s3-bucket&quot;&gt;&lt;/a&gt;&lt;strong&gt;72.2&lt;/strong&gt; — Upload a Local File Into an S3 Bucket .............................................................................................&lt;/li&gt;
&lt;li&gt;&lt;a id=&quot;bagian-723-delete-a-s3-bucket&quot;&gt;&lt;/a&gt;&lt;strong&gt;72.3&lt;/strong&gt; — Delete a S3 Bucket .............................................................................................................................&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://ngopidulur.my.id/blog/powershell-notes-for-professionals/&quot;&gt;https://ngopidulur.my.id/blog/powershell-notes-for-professionals/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>Ngopidulur</dc:creator><pubDate>Mon, 25 May 2026 23:17:00 GMT</pubDate></item><item><title>PostgreSQL® Notes for Professionals</title><link>https://ngopidulur.my.id/blog/postgresql-notes-for-professionals/</link><guid isPermaLink="true">https://ngopidulur.my.id/blog/postgresql-notes-for-professionals/</guid><description>Dokumen Markdown ini dibuat dari file `PostgreSQLNotesForProfessionals.pdf` dan diterjemahkan ke Bahasa Indonesia. Contoh perintah SQL, shell, C, Java, Python, PHP, dan C# sengaja dipertahankan sedekat mungkin dengan bentuk aslinya agar tetap dapat digunakan.</description><content:encoded>&lt;h1&gt;PostgreSQL® Notes for Professionals — Versi Bahasa Indonesia&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Catatan&lt;/strong&gt;: Dokumen Markdown ini dibuat dari file &lt;code&gt;PostgreSQLNotesForProfessionals.pdf&lt;/code&gt; dan diterjemahkan ke Bahasa Indonesia. Contoh perintah SQL, shell, C, Java, Python, PHP, dan C# sengaja dipertahankan sedekat mungkin dengan bentuk aslinya agar tetap dapat digunakan.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Tentang&lt;/h2&gt;
&lt;p&gt;Buku &lt;em&gt;PostgreSQL® Notes for Professionals&lt;/em&gt; adalah buku gratis tidak resmi untuk tujuan edukasi. Materinya dikompilasi dari Stack Overflow Documentation. PostgreSQL®, Stack Overflow, dan merek lain adalah milik pemiliknya masing-masing. Informasi di dalam buku tidak dijamin selalu benar atau akurat; gunakan dengan pertimbangan sendiri.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Daftar Isi&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;#bab-1-memulai-dengan-postgresql&quot;&gt;Bab 1: Memulai dengan PostgreSQL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-2-tipe-data&quot;&gt;Bab 2: Tipe Data&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-3-tanggal-timestamp-dan-interval&quot;&gt;Bab 3: Tanggal, Timestamp, dan Interval&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-4-pembuatan-tabel&quot;&gt;Bab 4: Pembuatan Tabel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-5-select&quot;&gt;Bab 5: SELECT&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-6-mencari-panjang-string--karakter&quot;&gt;Bab 6: Mencari Panjang String / Karakter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-7-coalesce&quot;&gt;Bab 7: COALESCE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-8-insert&quot;&gt;Bab 8: INSERT&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-9-update&quot;&gt;Bab 9: UPDATE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-10-dukungan-json&quot;&gt;Bab 10: Dukungan JSON&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-11-fungsi-agregat&quot;&gt;Bab 11: Fungsi Agregat&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-12-common-table-expressions&quot;&gt;Bab 12: Common Table Expressions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-13-window-functions&quot;&gt;Bab 13: Window Functions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-14-query-rekursif&quot;&gt;Bab 14: Query Rekursif&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-15-pemrograman-dengan-plpgsql&quot;&gt;Bab 15: PL/pgSQL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-16-inheritance&quot;&gt;Bab 16: Inheritance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-17-ekspor-header-dan-data-tabel-postgresql-ke-csv&quot;&gt;Bab 17: Export CSV&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-18-trigger-dan-fungsi-trigger&quot;&gt;Bab 18: Trigger&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-19-event-trigger&quot;&gt;Bab 19: Event Trigger&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-20-manajemen-role&quot;&gt;Bab 20: Role Management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-21-fungsi-kriptografi-postgresql&quot;&gt;Bab 21: Kriptografi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-22-komentar-di-postgresql&quot;&gt;Bab 22: Comment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-23-backup-dan-restore&quot;&gt;Bab 23: Backup &amp;amp; Restore&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-24-skrip-backup-untuk-database-produksi&quot;&gt;Bab 24: Script Backup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-25-mengakses-data-secara-programatis&quot;&gt;Bab 25: Akses Programatik&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-26-koneksi-postgresql-dari-java&quot;&gt;Bab 26: Java&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-27-postgresql-high-availability&quot;&gt;Bab 27: High Availability&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-28-extension-dblink-dan-postgresfdw&quot;&gt;Bab 28: dblink &amp;amp; FDW&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bab-29-tips-dan-trik-postgresql&quot;&gt;Bab 29: Tips &amp;amp; Tricks&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 1: Memulai dengan PostgreSQL&lt;/h1&gt;
&lt;h2&gt;Versi PostgreSQL&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Versi&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Tanggal Rilis&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Tanggal EOL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;10.0&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2017-10-05&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2022-10-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9.6&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2016-09-29&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2021-09-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9.5&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2016-01-07&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2021-01-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9.4&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2014-12-18&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2019-12-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9.3&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2013-09-09&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2018-09-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9.2&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2012-09-10&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2017-09-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9.1&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2011-09-12&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2016-09-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9.0&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2010-09-20&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2015-09-01&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8.4&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2009-07-01&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2014-07-01&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;1.1 Menginstal PostgreSQL di Windows&lt;/h2&gt;
&lt;p&gt;Walaupun server produksi umumnya lebih disarankan berjalan di sistem berbasis Unix seperti Linux atau BSD, PostgreSQL tetap dapat diinstal di Windows, terutama untuk server pengembangan.&lt;/p&gt;
&lt;p&gt;Langkah umum:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Unduh installer Windows dari EnterpriseDB.&lt;/li&gt;
&lt;li&gt;Pilih versi stabil terbaru, bukan versi beta.&lt;/li&gt;
&lt;li&gt;Pilih paket sesuai arsitektur Windows: &lt;code&gt;x86-64&lt;/code&gt; untuk 64-bit atau &lt;code&gt;x86-32&lt;/code&gt; untuk 32-bit.&lt;/li&gt;
&lt;li&gt;Pada installer, pilih paket tambahan yang diperlukan, misalnya:&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;pgAdmin&lt;/strong&gt;: GUI gratis untuk mengelola database.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PostGIS&lt;/strong&gt;: ekstensi analisis geospasial.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Language Pack&lt;/strong&gt;: library untuk PL/Python, PL/Perl, dan PL/Tcl.&lt;/li&gt;
&lt;li&gt;Paket lain seperti &lt;code&gt;pgAgent&lt;/code&gt;, &lt;code&gt;pgBouncer&lt;/code&gt;, dan &lt;code&gt;Slony&lt;/code&gt; biasanya digunakan untuk server produksi yang lebih besar.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Setelah instalasi, buka pgAdmin dan hubungkan ke server lokal, misalnya &lt;code&gt;PostgreSQL 9.5 (localhost:5432)&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Opsional: Mengubah Startup Service menjadi Manual&lt;/h3&gt;
&lt;p&gt;PostgreSQL berjalan sebagai service di background. Default-nya adalah &lt;strong&gt;Automatic&lt;/strong&gt;, artinya service selalu aktif saat komputer menyala.&lt;/p&gt;
&lt;p&gt;Jika komputer dipakai bergantian untuk pengembangan dan pekerjaan lain, Anda dapat mengubahnya menjadi &lt;strong&gt;Manual&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Buka &lt;code&gt;Control Panel -&amp;gt; System and Security -&amp;gt; Administrative Tools -&amp;gt; Services&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Cari service bernama seperti &lt;code&gt;postgresql-x64-9.5&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Klik kanan → &lt;code&gt;Properties&lt;/code&gt; → &lt;code&gt;Startup type&lt;/code&gt; → &lt;code&gt;Manual&lt;/code&gt; → &lt;code&gt;Apply&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Untuk menjalankan service, klik kanan → &lt;code&gt;Start&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Untuk menghentikan service, klik kanan → &lt;code&gt;Stop&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;1.2 Instal PostgreSQL dari Source di Linux&lt;/h2&gt;
&lt;p&gt;Dependensi umum:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GNU Make versi &amp;gt; 3.80&lt;/li&gt;
&lt;li&gt;Compiler C ISO/ANSI, misalnya &lt;code&gt;gcc&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Extractor seperti &lt;code&gt;tar&lt;/code&gt; atau &lt;code&gt;gzip&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;zlib-devel&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readline-devel&lt;/code&gt; atau &lt;code&gt;libedit-devel&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Contoh ekstraksi source:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;tar -xzvf postgresql-9.6.3.tar.gz
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Opsi konfigurasi yang sering digunakan:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;--prefix=PATH              path untuk semua file
--exec-prefix=PATH         path untuk file bergantung arsitektur
--bindir=PATH              path program executable
--sysconfdir=PATH          path file konfigurasi
--with-pgport=NUMBER       port server
--with-perl                dukungan Perl
--with-python              dukungan Python
--with-openssl             dukungan OpenSSL
--with-ldap                dukungan LDAP
--with-blocksize=BLOCKSIZE ukuran page dalam KB
--with-wal-segsize=SEGSIZE ukuran segmen WAL dalam MB
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Contoh build:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;./configure --exec=/usr/local/pgsql
make
make install
make clean
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Untuk ekstensi:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cd contrib
make
make install
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;1.3 Instalasi di GNU/Linux&lt;/h2&gt;
&lt;h3&gt;Keluarga Red Hat&lt;/h3&gt;
&lt;p&gt;Contoh alur:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;yum list available | grep postgres*
yum -y install postgresqlXX postgresqlXX-server postgresqlXX-libs postgresqlXX-contrib
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Menjalankan service sebagai user &lt;code&gt;postgres&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo -su postgres ./usr/pgsql-X.X/bin/pg_ctl -D /var/lib/pgsql/X.X/data start
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Masuk ke CLI:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;psql
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Keluarga Debian&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt-get install postgresql
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Perintah ini menginstal paket server PostgreSQL versi default dari repository sistem operasi.&lt;/p&gt;
&lt;h2&gt;1.4 Instal PostgreSQL via MacPorts di macOS&lt;/h2&gt;
&lt;p&gt;Cek versi yang tersedia:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo port list | grep &amp;quot;^postgresql[[:digit:]]\{2\}[[:space:]]&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Contoh instalasi PostgreSQL 9.6:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo port install postgresql96-server postgresql96
sudo mkdir -p /opt/local/var/db/postgresql96/defaultdb
sudo chown postgres:postgres /opt/local/var/db/postgresql96/defaultdb
sudo su postgres -c &amp;#39;/opt/local/lib/postgresql96/bin/initdb -D /opt/local/var/db/postgresql96/defaultdb&amp;#39;
sudo port load -w postgresql96-server
su postgres -c psql
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cek direktori data:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT setting FROM pg_settings WHERE name=&amp;#39;data_directory&amp;#39;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Keluar dari &lt;code&gt;psql&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;\q
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;1.5 Instal PostgreSQL dengan Homebrew di Mac&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;brew update
brew install postgresql
brew services start postgresql
psql
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Jika &lt;code&gt;psql&lt;/code&gt; mengeluh tidak ada database sesuai user Anda, jalankan:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;createdb
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;1.6 Postgres.app untuk macOS&lt;/h2&gt;
&lt;p&gt;Postgres.app adalah alat sederhana untuk menginstal PostgreSQL di Mac. Anda dapat mengatur apakah PostgreSQL berjalan di background atau hanya saat aplikasi aktif.&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 2: Tipe Data&lt;/h1&gt;
&lt;p&gt;PostgreSQL menyediakan banyak tipe data native. Pengguna juga dapat menambah tipe baru dengan perintah &lt;code&gt;CREATE TYPE&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;2.1 Tipe Numerik&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Nama&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Ukuran&lt;/th&gt;
&lt;th&gt;Deskripsi&lt;/th&gt;
&lt;th&gt;Rentang&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SMALLINT&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2 byte&lt;/td&gt;
&lt;td&gt;integer rentang kecil&lt;/td&gt;
&lt;td&gt;-32768 sampai +32767&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;INTEGER&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;4 byte&lt;/td&gt;
&lt;td&gt;pilihan umum untuk integer&lt;/td&gt;
&lt;td&gt;-2147483648 sampai +2147483647&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BIGINT&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;8 byte&lt;/td&gt;
&lt;td&gt;integer rentang besar&lt;/td&gt;
&lt;td&gt;-9223372036854775808 sampai +9223372036854775807&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DECIMAL&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;variabel&lt;/td&gt;
&lt;td&gt;presisi ditentukan pengguna, eksak&lt;/td&gt;
&lt;td&gt;sangat besar&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NUMERIC&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;variabel&lt;/td&gt;
&lt;td&gt;presisi ditentukan pengguna, eksak&lt;/td&gt;
&lt;td&gt;sangat besar&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;REAL&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;4 byte&lt;/td&gt;
&lt;td&gt;presisi variabel, tidak eksak&lt;/td&gt;
&lt;td&gt;6 digit desimal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DOUBLE PRECISION&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;8 byte&lt;/td&gt;
&lt;td&gt;presisi variabel, tidak eksak&lt;/td&gt;
&lt;td&gt;15 digit desimal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;smallserial&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;2 byte&lt;/td&gt;
&lt;td&gt;integer auto-increment kecil&lt;/td&gt;
&lt;td&gt;1 sampai 32767&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;serial&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;4 byte&lt;/td&gt;
&lt;td&gt;integer auto-increment&lt;/td&gt;
&lt;td&gt;1 sampai 2147483647&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BIGSERIAL&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;8 byte&lt;/td&gt;
&lt;td&gt;integer auto-increment besar&lt;/td&gt;
&lt;td&gt;1 sampai 9223372036854775807&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Tipe range: &lt;code&gt;int4range&lt;/code&gt;, &lt;code&gt;int8range&lt;/code&gt;, &lt;code&gt;numrange&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;2.2 Tipe Tanggal/Waktu&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Nama&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Ukuran&lt;/th&gt;
&lt;th&gt;Deskripsi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TIMESTAMP without time zone&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;8 byte&lt;/td&gt;
&lt;td&gt;tanggal dan waktu tanpa zona waktu&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TIMESTAMP with time zone&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;8 byte&lt;/td&gt;
&lt;td&gt;tanggal dan waktu dengan zona waktu&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DATE&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;4 byte&lt;/td&gt;
&lt;td&gt;tanggal tanpa jam&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TIME without time zone&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;8 byte&lt;/td&gt;
&lt;td&gt;waktu tanpa tanggal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TIME with time zone&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;12 byte&lt;/td&gt;
&lt;td&gt;waktu dengan zona waktu&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;INTERVAL&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;16 byte&lt;/td&gt;
&lt;td&gt;interval waktu&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Tipe range: &lt;code&gt;tsrange&lt;/code&gt;, &lt;code&gt;tstzrange&lt;/code&gt;, &lt;code&gt;daterange&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;2.3 Tipe Geometrik&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Nama&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Ukuran&lt;/th&gt;
&lt;th&gt;Deskripsi&lt;/th&gt;
&lt;th&gt;Representasi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;point&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;16 byte&lt;/td&gt;
&lt;td&gt;titik pada bidang&lt;/td&gt;
&lt;td&gt;&lt;code&gt;(x,y)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;line&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;32 byte&lt;/td&gt;
&lt;td&gt;garis tak hingga&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{A,B,C}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lseg&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;32 byte&lt;/td&gt;
&lt;td&gt;segmen garis&lt;/td&gt;
&lt;td&gt;&lt;code&gt;((x1,y1),(x2,y2))&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;box&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;32 byte&lt;/td&gt;
&lt;td&gt;kotak persegi panjang&lt;/td&gt;
&lt;td&gt;&lt;code&gt;((x1,y1),(x2,y2))&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;path&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;16+16n byte&lt;/td&gt;
&lt;td&gt;path tertutup/terbuka&lt;/td&gt;
&lt;td&gt;&lt;code&gt;((x1,y1),...)&lt;/code&gt; atau &lt;code&gt;[(x1,y1),...]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;polygon&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;40+16n byte&lt;/td&gt;
&lt;td&gt;poligon&lt;/td&gt;
&lt;td&gt;&lt;code&gt;((x1,y1),...)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;circle&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;24 byte&lt;/td&gt;
&lt;td&gt;lingkaran&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;(x,y),r&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;2.4 Tipe Alamat Jaringan&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Nama&lt;/th&gt;
&lt;th align=&quot;right&quot;&gt;Ukuran&lt;/th&gt;
&lt;th&gt;Deskripsi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CIDR&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;7 atau 19 byte&lt;/td&gt;
&lt;td&gt;jaringan IPv4/IPv6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;INET&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;7 atau 19 byte&lt;/td&gt;
&lt;td&gt;host dan jaringan IPv4/IPv6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;macaddr&lt;/code&gt;&lt;/td&gt;
&lt;td align=&quot;right&quot;&gt;6 byte&lt;/td&gt;
&lt;td&gt;alamat MAC&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;2.5 Tipe Karakter&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Nama&lt;/th&gt;
&lt;th&gt;Deskripsi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;character varying(n)&lt;/code&gt;, &lt;code&gt;varchar(n)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;panjang variabel dengan batas&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;character(n)&lt;/code&gt;, &lt;code&gt;char(n)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;panjang tetap, dipenuhi spasi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;text&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;panjang tidak terbatas&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;2.6 Array&lt;/h2&gt;
&lt;p&gt;PostgreSQL dapat membuat array dari tipe bawaan, tipe buatan pengguna, atau enum.&lt;/p&gt;
&lt;p&gt;Deklarasi:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT INTEGER[];
SELECT INTEGER[3];
SELECT INTEGER[][];
SELECT INTEGER[3][3];
SELECT INTEGER ARRAY;
SELECT INTEGER ARRAY[3];
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Membuat array:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT &amp;#39;{0,1,2}&amp;#39;;
SELECT &amp;#39;{{0,1},{1,2}}&amp;#39;;
SELECT ARRAY[0,1,2];
SELECT ARRAY[ARRAY[0,1], ARRAY[1,2]];
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mengakses array:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;WITH arr AS (SELECT ARRAY[0,1,2] int_arr)
SELECT int_arr[1] FROM arr;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Slicing array:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;WITH arr AS (SELECT ARRAY[0,1,2] int_arr)
SELECT int_arr[1:2] FROM arr;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Informasi array:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;WITH arr AS (SELECT ARRAY[0,1,2] int_arr)
SELECT ARRAY_DIMS(int_arr) FROM arr;

WITH arr AS (SELECT ARRAY[0,1,2] int_arr)
SELECT ARRAY_LENGTH(int_arr, 1) FROM arr;

WITH arr AS (SELECT ARRAY[0,1,2] int_arr)
SELECT cardinality(int_arr) FROM arr;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 3: Tanggal, Timestamp, dan Interval&lt;/h1&gt;
&lt;h2&gt;3.1 SELECT hari terakhir bulan&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT (DATE_TRUNC(&amp;#39;MONTH&amp;#39;, (&amp;#39;201608&amp;#39; || &amp;#39;01&amp;#39;)::DATE) + INTERVAL &amp;#39;1 MONTH - 1 day&amp;#39;)::DATE;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;201608&lt;/code&gt; dapat diganti dengan variabel.&lt;/p&gt;
&lt;h2&gt;3.2 Mengubah timestamp atau interval menjadi string&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT TO_CHAR(&amp;#39;2016-08-12 16:40:32&amp;#39;::TIMESTAMP, &amp;#39;DD Mon YYYY HH:MI:SSPM&amp;#39;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hasil:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;12 Aug 2016 04:40:32PM
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Teks biasa di format sebaiknya diletakkan dalam tanda kutip ganda:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT TO_CHAR(
  &amp;#39;2016-08-12 16:40:32&amp;#39;::TIMESTAMP,
  &amp;#39;&amp;quot;Today is &amp;quot;FMDay&amp;quot;, the &amp;quot;DDth&amp;quot; day of the month of &amp;quot;FMMonth&amp;quot; of &amp;quot;YYYY&amp;#39;
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mode translasi lokal dapat memakai modifier &lt;code&gt;TM&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT TO_CHAR(&amp;#39;2016-08-12 16:40:32&amp;#39;::TIMESTAMP, &amp;#39;TMDay, DD&amp;quot; de &amp;quot;TMMonth&amp;quot; del año &amp;quot;YYYY&amp;#39;);
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3.3 Menghitung jumlah record per minggu&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT DATE_TRUNC(&amp;#39;week&amp;#39;, &amp;lt;&amp;gt;) AS &amp;quot;Week&amp;quot;, COUNT(*)
FROM &amp;lt;&amp;gt;
GROUP BY 1
ORDER BY 1;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 4: Pembuatan Tabel&lt;/h1&gt;
&lt;h2&gt;4.1 Menampilkan definisi tabel&lt;/h2&gt;
&lt;p&gt;Di &lt;code&gt;psql&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;\d tablename
\d+ tablename
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Jika lupa nama tabel:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;\d
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;4.2 Membuat tabel dari SELECT&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE person (
    person_id BIGINT NOT NULL,
    last_name VARCHAR(255) NOT NULL,
    first_name VARCHAR(255),
    age INT NOT NULL,
    PRIMARY KEY (person_id)
);

CREATE TABLE people_over_30 AS
SELECT * FROM person WHERE age &amp;gt; 30;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;4.3 Membuat unlogged table&lt;/h2&gt;
&lt;p&gt;Unlogged table lebih cepat karena melewati penulisan WAL, tetapi tidak aman terhadap crash dan tidak dapat direplikasi.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE UNLOGGED TABLE person (
    person_id BIGINT NOT NULL PRIMARY KEY,
    last_name VARCHAR(255) NOT NULL,
    first_name VARCHAR(255),
    address VARCHAR(255),
    city VARCHAR(255)
);
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;4.4 Tabel dengan Primary Key&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE person (
    person_id BIGINT NOT NULL,
    last_name VARCHAR(255) NOT NULL,
    first_name VARCHAR(255),
    address VARCHAR(255),
    city VARCHAR(255),
    PRIMARY KEY (person_id)
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Atau langsung pada kolom:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE person (
    person_id BIGINT NOT NULL PRIMARY KEY,
    last_name VARCHAR(255) NOT NULL,
    first_name VARCHAR(255),
    address VARCHAR(255),
    city VARCHAR(255)
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Disarankan memakai nama tabel dan kolom huruf kecil. Jika memakai huruf besar, PostgreSQL mengharuskan nama tersebut selalu diapit tanda kutip ganda.&lt;/p&gt;
&lt;h2&gt;4.5 Membuat tabel yang mereferensikan tabel lain&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE agencies (
  id SERIAL PRIMARY KEY,
  name TEXT NOT NULL
);

CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  agency_id INTEGER NOT NULL REFERENCES agencies(id) DEFERRABLE INITIALLY DEFERRED
);
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 5: SELECT&lt;/h1&gt;
&lt;h2&gt;5.1 SELECT menggunakan WHERE&lt;/h2&gt;
&lt;p&gt;Contoh tabel:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE sch_test.user_table (
  id serial NOT NULL,
  username CHARACTER VARYING,
  pass CHARACTER VARYING,
  first_name CHARACTER varying(30),
  last_name CHARACTER varying(30),
  CONSTRAINT user_table_pkey PRIMARY KEY (id)
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sintaks:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT * FROM schema_name.table_name WHERE &amp;lt;condition&amp;gt;;
SELECT field1, field2 FROM schema_name.table_name WHERE &amp;lt;condition&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Contoh:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT * FROM schema_name.table_name WHERE id = 1;
SELECT id FROM schema_name.table_name WHERE username = &amp;#39;root&amp;#39; AND pass = &amp;#39;toor&amp;#39;;
SELECT first_name FROM schema_name.table_name WHERE id != 1;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 6: Mencari Panjang String / Karakter&lt;/h1&gt;
&lt;p&gt;Gunakan &lt;code&gt;char_length()&lt;/code&gt; atau &lt;code&gt;character_length()&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT CHAR_LENGTH(&amp;#39;ABCDE&amp;#39;);
SELECT CHARACTER_LENGTH(&amp;#39;ABCDE&amp;#39;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Keduanya menghasilkan:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;5
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 7: COALESCE&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;COALESCE&lt;/code&gt; mengembalikan argumen pertama yang bukan &lt;code&gt;NULL&lt;/code&gt;. Jika semua argumen &lt;code&gt;NULL&lt;/code&gt;, hasilnya &lt;code&gt;NULL&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT COALESCE(NULL, NULL, &amp;#39;HELLO WORLD&amp;#39;);
SELECT COALESCE(NULL, NULL, &amp;#39;first non null&amp;#39;, NULL, NULL, &amp;#39;second non null&amp;#39;);
SELECT COALESCE(NULL, NULL, NULL);
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 8: INSERT&lt;/h1&gt;
&lt;h2&gt;8.1 Insert data menggunakan COPY&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;COPY&lt;/code&gt; adalah mekanisme bulk insert PostgreSQL. Biasanya jauh lebih cepat daripada &lt;code&gt;INSERT&lt;/code&gt; untuk ribuan baris.&lt;/p&gt;
&lt;p&gt;Contoh data:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cat &amp;gt; sample_data.csv
1,Yogesh
2,Raunak
3,Varun
4,Kamal
5,Hari
6,Amit
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Tabel tujuan:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE copy_test(id INT, name varchar(8));
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Import dari file:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;COPY copy_test FROM &amp;#39;/path/to/file/sample_data.csv&amp;#39; DELIMITER &amp;#39;,&amp;#39;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Import dari &lt;code&gt;STDIN&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;COPY copy_test FROM STDIN DELIMITER &amp;#39;,&amp;#39;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Export ke file:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;COPY copy_test TO &amp;#39;path/to/file/sample_data.csv&amp;#39; DELIMITER &amp;#39;,&amp;#39;;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;8.2 Insert banyak baris&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;INSERT INTO person (name, age) VALUES
  (&amp;#39;john doe&amp;#39;, 25),
  (&amp;#39;jane doe&amp;#39;, 20);
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;8.3 INSERT data dan mengembalikan nilai&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE my_table (
  id serial NOT NULL,
  name CHARACTER VARYING,
  contact_number INTEGER,
  CONSTRAINT my_table_pkey PRIMARY KEY (id)
);

INSERT INTO my_table(name, contact_number)
VALUES (&amp;#39;USER&amp;#39;, 8542621)
RETURNING id;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;8.4 INSERT dasar&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE person (
    person_id BIGINT,
    name VARCHAR(255),
    age INT,
    city VARCHAR(255)
);

INSERT INTO person VALUES (1, &amp;#39;john doe&amp;#39;, 25, &amp;#39;new york&amp;#39;);
INSERT INTO person (name, age) VALUES (&amp;#39;john doe&amp;#39;, 25);
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;8.5 Insert dari SELECT&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;INSERT INTO person
SELECT * FROM tmp_person WHERE age &amp;lt; 30;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Kolom hasil &lt;code&gt;SELECT&lt;/code&gt; harus sesuai dengan kolom untuk &lt;code&gt;INSERT&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;8.6 UPSERT — &lt;code&gt;INSERT ... ON CONFLICT DO UPDATE&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Sejak PostgreSQL 9.5, tersedia UPSERT.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;INSERT INTO my_table (name, contact_number)
VALUES (&amp;#39;one&amp;#39;, 333)
RETURNING id;

INSERT INTO my_table VALUES (2, &amp;#39;one&amp;#39;, 333)
ON CONFLICT (id) DO UPDATE
SET name = my_table.name || &amp;#39; changed to: &amp;quot;two&amp;quot; at &amp;#39; || now()
RETURNING *;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;8.7 SELECT data ke file&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;COPY my_table TO &amp;#39;/home/postgres/my_table.txt&amp;#39;
USING DELIMITERS &amp;#39;|&amp;#39;
WITH NULL AS &amp;#39;null_string&amp;#39; CSV HEADER;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 9: UPDATE&lt;/h1&gt;
&lt;h2&gt;9.1 Update berdasarkan join dengan tabel lain&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;UPDATE person
SET state_code = cities.state_code
FROM cities
WHERE cities.city = city;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;9.2 Update semua baris&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;UPDATE person SET planet = &amp;#39;Earth&amp;#39;;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;9.3 Update baris dengan kondisi&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;UPDATE person SET state = &amp;#39;NY&amp;#39; WHERE city = &amp;#39;New York&amp;#39;;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;9.4 Update banyak kolom&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;UPDATE person
SET country = &amp;#39;USA&amp;#39;,
    state = &amp;#39;NY&amp;#39;
WHERE city = &amp;#39;New York&amp;#39;;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 10: Dukungan JSON&lt;/h1&gt;
&lt;p&gt;PostgreSQL mendukung tipe data JSON sejak versi 9.2. Operator penting:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-&amp;gt;&lt;/code&gt; mengembalikan nilai JSON.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-&amp;gt;&amp;gt;&lt;/code&gt; mengembalikan nilai sebagai teks.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;10.1 Menggunakan operator JSONB&lt;/h2&gt;
&lt;p&gt;Membuat database dan tabel:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;DROP DATABASE IF EXISTS books_db;
CREATE DATABASE books_db WITH ENCODING=&amp;#39;UTF8&amp;#39; TEMPLATE template0;

DROP TABLE IF EXISTS books;
CREATE TABLE books (
  id SERIAL PRIMARY KEY,
  client TEXT NOT NULL,
  data JSONb NOT NULL
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mengisi data:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;INSERT INTO books(client, data) VALUES
(
  &amp;#39;Joe&amp;#39;,
  &amp;#39;{ &amp;quot;title&amp;quot;: &amp;quot;Siddhartha&amp;quot;, &amp;quot;author&amp;quot;: { &amp;quot;first_name&amp;quot;: &amp;quot;Herman&amp;quot;, &amp;quot;last_name&amp;quot;: &amp;quot;Hesse&amp;quot; } }&amp;#39;
),
(
  &amp;#39;Jenny&amp;#39;,
  &amp;#39;{ &amp;quot;title&amp;quot;: &amp;quot;Dharma Bums&amp;quot;, &amp;quot;author&amp;quot;: { &amp;quot;first_name&amp;quot;: &amp;quot;Jack&amp;quot;, &amp;quot;last_name&amp;quot;: &amp;quot;Kerouac&amp;quot; } }&amp;#39;
),
(
  &amp;#39;Jenny&amp;#39;,
  &amp;#39;{ &amp;quot;title&amp;quot;: &amp;quot;100 años de soledad&amp;quot;, &amp;quot;author&amp;quot;: { &amp;quot;first_name&amp;quot;: &amp;quot;Gabo&amp;quot;, &amp;quot;last_name&amp;quot;: &amp;quot;Marquéz&amp;quot; } }&amp;#39;
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Memilih nilai JSON:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT client, data-&amp;gt;&amp;#39;title&amp;#39; AS title FROM books;
SELECT client, data-&amp;gt;&amp;#39;title&amp;#39; AS title, data-&amp;gt;&amp;#39;author&amp;#39; AS author FROM books;
SELECT client, data-&amp;gt;&amp;#39;author&amp;#39;-&amp;gt;&amp;#39;last_name&amp;#39; AS author FROM books;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Filter:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT client, data-&amp;gt;&amp;#39;title&amp;#39; AS title
FROM books
WHERE data-&amp;gt;&amp;#39;title&amp;#39; = &amp;#39;&amp;quot;Dharma Bums&amp;quot;&amp;#39;;

SELECT client, data-&amp;gt;&amp;#39;title&amp;#39; AS title
FROM books
WHERE data-&amp;gt;&amp;#39;author&amp;#39;-&amp;gt;&amp;gt;&amp;#39;last_name&amp;#39; = &amp;#39;Kerouac&amp;#39;;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Contoh dunia nyata&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE events (
  name varchar(200),
  visitor_id varchar(200),
  properties json,
  browser json
);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Contoh agregasi:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT browser-&amp;gt;&amp;gt;&amp;#39;name&amp;#39; AS browser,
       COUNT(browser)
FROM events
GROUP BY browser-&amp;gt;&amp;gt;&amp;#39;name&amp;#39;;

SELECT visitor_id,
       SUM(CAST(properties-&amp;gt;&amp;gt;&amp;#39;amount&amp;#39; AS INTEGER)) AS total
FROM events
WHERE CAST(properties-&amp;gt;&amp;gt;&amp;#39;amount&amp;#39; AS INTEGER) &amp;gt; 0
GROUP BY visitor_id;

SELECT AVG(CAST(browser-&amp;gt;&amp;#39;resolution&amp;#39;-&amp;gt;&amp;gt;&amp;#39;x&amp;#39; AS INTEGER)) AS width,
       AVG(CAST(browser-&amp;gt;&amp;#39;resolution&amp;#39;-&amp;gt;&amp;gt;&amp;#39;y&amp;#39; AS INTEGER)) AS height
FROM events;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;10.2 Query dokumen JSON kompleks&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE mytable (data JSONB NOT NULL);
CREATE INDEX mytable_idx ON mytable USING gin (data jsonb_path_ops);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Contoh query:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT data-&amp;gt;&amp;gt;&amp;#39;name&amp;#39; FROM mytable WHERE data @&amp;gt; &amp;#39;{&amp;quot;name&amp;quot;:&amp;quot;Alice&amp;quot;}&amp;#39;;
SELECT data-&amp;gt;&amp;gt;&amp;#39;name&amp;#39; FROM mytable WHERE data @&amp;gt; &amp;#39;{&amp;quot;emails&amp;quot;:[&amp;quot;alice1@test.com&amp;quot;]}&amp;#39;;
SELECT data-&amp;gt;&amp;gt;&amp;#39;name&amp;#39; FROM mytable WHERE data @&amp;gt; &amp;#39;{&amp;quot;events&amp;quot;:[{&amp;quot;type&amp;quot;:&amp;quot;anniversary&amp;quot;}]}&amp;#39;;
SELECT data-&amp;gt;&amp;gt;&amp;#39;name&amp;#39; FROM mytable WHERE data @&amp;gt; &amp;#39;{&amp;quot;locations&amp;quot;:{&amp;quot;home&amp;quot;:{&amp;quot;city&amp;quot;:&amp;quot;London&amp;quot;}}}&amp;#39;;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Performa &lt;code&gt;@&amp;gt;&lt;/code&gt; dibanding &lt;code&gt;-&amp;gt;&lt;/code&gt; dan &lt;code&gt;-&amp;gt;&amp;gt;&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Query dengan &lt;code&gt;@&amp;gt;&lt;/code&gt; dapat memakai index GIN yang dibuat, sedangkan filter memakai &lt;code&gt;data-&amp;gt;&amp;#39;name&amp;#39;&lt;/code&gt; atau &lt;code&gt;data-&amp;gt;&amp;gt;&amp;#39;name&amp;#39;&lt;/code&gt; biasanya melakukan full table scan.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT data FROM mytable WHERE data @&amp;gt; &amp;#39;{&amp;quot;name&amp;quot;:&amp;quot;Alice&amp;quot;}&amp;#39;;
SELECT data FROM mytable WHERE data-&amp;gt;&amp;#39;name&amp;#39; = &amp;#39;&amp;quot;Alice&amp;quot;&amp;#39;;
SELECT data FROM mytable WHERE data-&amp;gt;&amp;gt;&amp;#39;name&amp;#39; = &amp;#39;Alice&amp;#39;;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;10.3 Membuat tabel JSON murni&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE mytable (data JSONB NOT NULL);
CREATE INDEX mytable_idx ON mytable USING gin (data jsonb_path_ops);
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 11: Fungsi Agregat&lt;/h1&gt;
&lt;h2&gt;11.1 Statistik sederhana: &lt;code&gt;min()&lt;/code&gt;, &lt;code&gt;max()&lt;/code&gt;, &lt;code&gt;avg()&lt;/code&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT MIN(age), MAX(age), AVG(age)
FROM individuals;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.2 &lt;code&gt;regr_slope(Y, X)&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;regr_slope(Y, X)&lt;/code&gt; menghitung kemiringan garis regresi linear least-squares dari pasangan &lt;code&gt;(X, Y)&lt;/code&gt;. Contoh penggunaan: mencari kandidat memory leak dari tren pemakaian memori.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE heap_histogram (
    histwhen TIMESTAMP WITHOUT TIME ZONE NOT NULL,
    class CHARACTER VARYING NOT NULL,
    bytes INTEGER NOT NULL
);

SELECT class,
       REGR_SLOPE(bytes, EXTRACT(epoch FROM histwhen)) AS slope
FROM public.heap_histogram
GROUP BY class
HAVING REGR_SLOPE(bytes, EXTRACT(epoch FROM histwhen)) &amp;gt; 0
ORDER BY slope DESC;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;11.3 &lt;code&gt;string_agg(expression, delimiter)&lt;/code&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT STRING_AGG(name, &amp;#39;, &amp;#39;) AS names, country
FROM individuals
GROUP BY country;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 12: Common Table Expressions (&lt;code&gt;WITH&lt;/code&gt;)&lt;/h1&gt;
&lt;h2&gt;12.1 CTE dalam SELECT&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;WITH sales AS (
  SELECT
    orders.ordered_at,
    orders.user_id,
    SUM(orders.amount) AS total
  FROM orders
  GROUP BY orders.ordered_at, orders.user_id
)
SELECT
  sales.ordered_at,
  sales.total,
  users.name
FROM sales
JOIN users USING (user_id);
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;12.2 Menelusuri tree dengan &lt;code&gt;WITH RECURSIVE&lt;/code&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE empl (
    name TEXT PRIMARY KEY,
    boss TEXT NULL REFERENCES empl(name)
        ON UPDATE CASCADE
        ON DELETE CASCADE
        DEFAULT NULL
);

WITH RECURSIVE t(level, path, boss, name) AS (
    SELECT 0, name, boss, name FROM empl WHERE boss IS NULL
    UNION
    SELECT
        level + 1,
        path || &amp;#39; &amp;gt; &amp;#39; || empl.name,
        empl.boss,
        empl.name
    FROM empl JOIN t ON empl.boss = t.name
)
SELECT * FROM t ORDER BY path;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 13: Window Functions&lt;/h1&gt;
&lt;h2&gt;13.1 Contoh umum&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE wf_example(i INT, t TEXT, ts timestamptz, b BOOLEAN);

SELECT *
  , DENSE_RANK() OVER (ORDER BY i) dist_by_i
  , LAG(t) OVER () prev_t
  , NTH_VALUE(i, 6) OVER () nth
  , COUNT(TRUE) OVER (PARTITION BY i) num_by_i
  , COUNT(TRUE) OVER () num_all
  , NTILE(3) OVER () ntile
FROM wf_example;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Penjelasan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;DENSE_RANK() OVER (ORDER BY i)&lt;/code&gt;: memberi nomor per nilai berbeda.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;LAG(t) OVER ()&lt;/code&gt;: nilai sebelumnya dari kolom &lt;code&gt;t&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NTH_VALUE(i, 6) OVER ()&lt;/code&gt;: nilai kolom &lt;code&gt;i&lt;/code&gt; pada baris ke-6 dalam window.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;COUNT(TRUE) OVER (PARTITION BY i)&lt;/code&gt;: jumlah baris untuk setiap nilai &lt;code&gt;i&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;COUNT(TRUE) OVER ()&lt;/code&gt;: jumlah seluruh baris dalam window.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NTILE(3) OVER ()&lt;/code&gt;: membagi window menjadi 3 bagian yang sebisa mungkin sama besar.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;13.2 &lt;code&gt;dense_rank&lt;/code&gt; vs &lt;code&gt;rank&lt;/code&gt; vs &lt;code&gt;row_number&lt;/code&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT i,
       DENSE_RANK() OVER (ORDER BY i),
       ROW_NUMBER() OVER (),
       RANK() OVER (ORDER BY i)
FROM wf_example;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;dense_rank&lt;/code&gt;: memberi ranking tanpa celah antar nilai berbeda.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;row_number&lt;/code&gt;: memberi nomor baris sesuai urutan hasil.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rank&lt;/code&gt;: ranking berdasarkan posisi baris; nilai sama mendapat ranking sama, lalu dapat menyisakan celah.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 14: Query Rekursif&lt;/h1&gt;
&lt;h2&gt;14.1 Jumlah bilangan bulat&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;WITH RECURSIVE t(n) AS (
    VALUES (1)
  UNION ALL
    SELECT n + 1 FROM t WHERE n &amp;lt; 100
)
SELECT SUM(n) FROM t;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 15: Pemrograman dengan PL/pgSQL&lt;/h1&gt;
&lt;h2&gt;15.1 Fungsi PL/pgSQL dasar&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE FUNCTION active_subscribers() RETURNS BIGINT AS $$
DECLARE
    subscribers INTEGER;
BEGIN
    SELECT COUNT(user_id) INTO subscribers
    FROM users
    WHERE subscribed;

    RETURN subscribers;
EXCEPTION
    WHEN undefined_table THEN
        RETURN NULL;
END;
$$ LANGUAGE plpgsql;

SELECT active_subscribers();
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;15.2 Custom exception&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE OR REPLACE FUNCTION s164() RETURNS void AS $$
BEGIN
  RAISE EXCEPTION USING
    message = &amp;#39;S 164&amp;#39;,
    detail = &amp;#39;D 164&amp;#39;,
    hint = &amp;#39;H 164&amp;#39;,
    errcode = &amp;#39;P2222&amp;#39;;
END;
$$ LANGUAGE plpgsql;
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE OR REPLACE FUNCTION s165() RETURNS void AS $$
BEGIN
  RAISE EXCEPTION &amp;#39;%&amp;#39;, &amp;#39;nothing specified&amp;#39;;
END;
$$ LANGUAGE plpgsql;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;15.3 Sintaks PL/pgSQL&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE [OR REPLACE] FUNCTION functionName (someParameter parameterType)
RETURNS DATATYPE AS $_block_name_$
DECLARE
    -- deklarasi
BEGIN
    -- proses
    -- return
END;
$_block_name_$ LANGUAGE plpgsql;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;15.4 Blok &lt;code&gt;RETURNS&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Pilihan return:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tipe data tunggal.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TABLE(column_name column_type, ...)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SETOF datatype&lt;/code&gt; atau &lt;code&gt;SETOF table_column&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 16: Inheritance&lt;/h1&gt;
&lt;h2&gt;16.1 Membuat tabel anak&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE users (username TEXT, email TEXT);
CREATE TABLE simple_users () INHERITS (users);
CREATE TABLE users_with_password (password TEXT) INHERITS (users);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Hasil:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;users&lt;/code&gt;: &lt;code&gt;username&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;simple_users&lt;/code&gt;: &lt;code&gt;username&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;users_with_password&lt;/code&gt;: &lt;code&gt;username&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;password&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 17: Ekspor Header dan Data Tabel PostgreSQL ke CSV&lt;/h1&gt;
&lt;h2&gt;17.1 Copy dari query&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;COPY (SELECT oid, relname FROM pg_class LIMIT 5) TO STDOUT;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;17.2 Ekspor kolom tertentu ke CSV dengan header&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;COPY products(is_public, title, discount)
TO &amp;#39;D:\csv_backup\products_db.csv&amp;#39;
DELIMITER &amp;#39;,&amp;#39; CSV HEADER;

COPY categories(name)
TO &amp;#39;D:\csv_backup\categories_db.csv&amp;#39;
DELIMITER &amp;#39;,&amp;#39; CSV HEADER;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;17.3 Backup tabel penuh ke CSV dengan header&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;COPY products
TO &amp;#39;D:\csv_backup\products_db.csv&amp;#39;
DELIMITER &amp;#39;,&amp;#39; CSV HEADER;

COPY categories
TO &amp;#39;D:\csv_backup\categories_db.csv&amp;#39;
DELIMITER &amp;#39;,&amp;#39; CSV HEADER;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 18: Trigger dan Fungsi Trigger&lt;/h1&gt;
&lt;p&gt;Trigger dikaitkan dengan tabel atau view dan menjalankan fungsi tertentu ketika event terjadi.&lt;/p&gt;
&lt;h2&gt;18.1 Jenis trigger&lt;/h2&gt;
&lt;p&gt;Trigger dapat dijalankan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;BEFORE&lt;/code&gt;: sebelum operasi &lt;code&gt;INSERT&lt;/code&gt;, &lt;code&gt;UPDATE&lt;/code&gt;, atau &lt;code&gt;DELETE&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AFTER&lt;/code&gt;: setelah operasi selesai.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;INSTEAD OF&lt;/code&gt;: untuk operasi pada view.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Trigger dapat ditandai:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;FOR EACH ROW&lt;/code&gt;: dipanggil untuk setiap baris yang berubah.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;FOR EACH STATEMENT&lt;/code&gt;: dipanggil sekali untuk setiap statement.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Persiapan contoh&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE company (
    id SERIAL PRIMARY KEY NOT NULL,
    name TEXT NOT NULL,
    created_at TIMESTAMP,
    modified_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE log (
    id SERIAL PRIMARY KEY NOT NULL,
    table_name TEXT NOT NULL,
    table_id TEXT NOT NULL,
    description TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT NOW()
);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Single insert trigger&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE OR REPLACE FUNCTION add_created_at_function()
RETURNS TRIGGER AS $BODY$
BEGIN
  NEW.created_at := NOW();
  RETURN NEW;
END
$BODY$ LANGUAGE plpgsql;

CREATE TRIGGER add_created_at_trigger
BEFORE INSERT ON company
FOR EACH ROW
EXECUTE PROCEDURE add_created_at_function();
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Trigger untuk banyak operasi&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE OR REPLACE FUNCTION add_log_function()
RETURNS TRIGGER AS $BODY$
DECLARE
  vDescription TEXT;
  vId INT;
  vReturn RECORD;
BEGIN
  vDescription := TG_TABLE_NAME || &amp;#39; &amp;#39;;

  IF (TG_OP = &amp;#39;INSERT&amp;#39;) THEN
    vId := NEW.id;
    vDescription := vDescription || &amp;#39;added. Id: &amp;#39; || vId;
    vReturn := NEW;
  ELSIF (TG_OP = &amp;#39;UPDATE&amp;#39;) THEN
    vId := NEW.id;
    vDescription := vDescription || &amp;#39;updated. Id: &amp;#39; || vId;
    vReturn := NEW;
  ELSIF (TG_OP = &amp;#39;DELETE&amp;#39;) THEN
    vId := OLD.id;
    vDescription := vDescription || &amp;#39;deleted. Id: &amp;#39; || vId;
    vReturn := OLD;
  END IF;

  INSERT INTO log(table_name, table_id, description, created_at)
  VALUES (TG_TABLE_NAME, vId, vDescription, NOW());

  RETURN vReturn;
END
$BODY$ LANGUAGE plpgsql;

CREATE TRIGGER add_log_trigger
AFTER INSERT OR UPDATE OR DELETE ON company
FOR EACH ROW
EXECUTE PROCEDURE add_log_function();
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;18.2 Fungsi trigger PL/pgSQL dasar&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE OR REPLACE FUNCTION my_simple_trigger_function()
RETURNS TRIGGER AS $BODY$
BEGIN
  IF (TG_TABLE_NAME = &amp;#39;users&amp;#39;) THEN
    IF (TG_OP = &amp;#39;INSERT&amp;#39;) THEN
      INSERT INTO log_table(date_and_time, description)
      VALUES (NOW(), &amp;#39;New user inserted. User ID: &amp;#39; || NEW.id);
      RETURN NEW;
    ELSIF (TG_OP = &amp;#39;DELETE&amp;#39;) THEN
      INSERT INTO log_table(date_and_time, description)
      VALUES (NOW(), &amp;#39;User deleted. User ID: &amp;#39; || OLD.id);
      RETURN OLD;
    END IF;
    RETURN NULL;
  END IF;
END;
$BODY$ LANGUAGE plpgsql VOLATILE COST 100;

CREATE TRIGGER my_trigger
AFTER INSERT OR DELETE ON users
FOR EACH ROW
EXECUTE PROCEDURE my_simple_trigger_function();
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 19: Event Trigger&lt;/h1&gt;
&lt;p&gt;Event trigger dijalankan ketika event database tertentu terjadi.&lt;/p&gt;
&lt;p&gt;Event umum:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;DDL_COMMAND_START&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DDL_COMMAND_END&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SQL_DROP&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;19.1 Logging event awal command DDL&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE tab_event_logs(
  date_time TIMESTAMP,
  event_name TEXT,
  remarks TEXT
);

CREATE OR REPLACE FUNCTION fn_log_event()
RETURNS EVENT_TRIGGER
LANGUAGE SQL
AS $main$
  INSERT INTO tab_event_logs(date_time, event_name, remarks)
  VALUES (NOW(), TG_TAG, &amp;#39;Event Logging&amp;#39;);
$main$;

CREATE EVENT TRIGGER trg_log_event
ON DDL_COMMAND_START
EXECUTE PROCEDURE fn_log_event();
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 20: Manajemen Role&lt;/h1&gt;
&lt;h2&gt;20.1 Membuat user dengan password&lt;/h2&gt;
&lt;p&gt;Sebaiknya hindari memakai role default seperti &lt;code&gt;postgres&lt;/code&gt; di aplikasi. Buat user dengan privilege lebih rendah.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE ROLE niceusername WITH PASSWORD &amp;#39;very-strong-password&amp;#39; LOGIN;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Agar password tidak tersimpan di history &lt;code&gt;psql&lt;/code&gt;, gunakan:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE ROLE niceusername WITH LOGIN;
\password niceusername
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;20.2 Grant dan Revoke privilege&lt;/h2&gt;
&lt;p&gt;Contoh role:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;admin&lt;/code&gt;: administrator database.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;read_write&lt;/code&gt;: aplikasi dengan akses penuh pada datanya.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;read_only&lt;/code&gt;: akses baca saja.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Akses database:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;REVOKE CONNECT ON DATABASE nova FROM PUBLIC;
GRANT CONNECT ON DATABASE nova TO user_name;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Akses schema:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;REVOKE ALL ON SCHEMA public FROM PUBLIC;
GRANT USAGE ON SCHEMA public TO user_name;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Akses tabel:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;REVOKE ALL ON ALL TABLES IN SCHEMA public FROM PUBLIC;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO read_write;
GRANT ALL ON ALL TABLES IN SCHEMA public TO admin;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Akses sequence:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;REVOKE ALL ON ALL SEQUENCES IN SCHEMA public FROM PUBLIC;
GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO read_only;
GRANT UPDATE ON ALL SEQUENCES IN SCHEMA public TO read_write;
GRANT USAGE ON ALL SEQUENCES IN SCHEMA public TO read_write;
GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO admin;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;20.3 Membuat role dan database yang sesuai&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;createuser -P blogger
createdb -O blogger blogger
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Contoh &lt;code&gt;pg_hba.conf&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;host    sameuser        all     localhost    md5
local   sameuser        all                  md5
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;20.4 Mengubah default &lt;code&gt;search_path&lt;/code&gt; user&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SHOW search_path;
ALTER USER user1 SET search_path=&amp;#39;my_schema, &amp;quot;$user&amp;quot;, public&amp;#39;;
SHOW search_path;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Alternatif:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SET ROLE user1;
SHOW search_path;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;20.5 Membuat read-only user&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE USER readonly WITH ENCRYPTED PASSWORD &amp;#39;yourpassword&amp;#39;;
GRANT CONNECT ON DATABASE &amp;lt;database_name&amp;gt; TO readonly;
GRANT USAGE ON SCHEMA public TO readonly;
GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;20.6 Grant privilege untuk object masa depan&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;ALTER DEFAULT PRIVILEGES IN SCHEMA myschema
GRANT SELECT ON TABLES TO read_only;

ALTER DEFAULT PRIVILEGES IN SCHEMA myschema
GRANT SELECT, INSERT, DELETE, UPDATE ON TABLES TO read_write;

ALTER DEFAULT PRIVILEGES IN SCHEMA myschema
GRANT ALL ON TABLES TO admin;

ALTER DEFAULT PRIVILEGES FOR ROLE admin
GRANT SELECT ON TABLES TO read_only;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 21: Fungsi Kriptografi PostgreSQL&lt;/h1&gt;
&lt;p&gt;Fungsi kriptografi tersedia melalui module &lt;code&gt;pgcrypto&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE EXTENSION pgcrypto;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;21.1 &lt;code&gt;digest&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;digest()&lt;/code&gt; membuat hash biner dari data.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT DIGEST(&amp;#39;1&amp;#39;, &amp;#39;sha1&amp;#39;);
SELECT DIGEST(CONCAT(CAST(CURRENT_TIMESTAMP AS TEXT), RANDOM()::TEXT), &amp;#39;sha1&amp;#39;);
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 22: Komentar di PostgreSQL&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;COMMENT&lt;/code&gt; digunakan untuk mendefinisikan atau mengubah komentar pada object database.&lt;/p&gt;
&lt;h2&gt;22.1 Komentar pada tabel&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;COMMENT ON TABLE table_name IS &amp;#39;this is student details table&amp;#39;;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;22.2 Menghapus komentar&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;COMMENT ON TABLE student IS NULL;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 23: Backup dan Restore&lt;/h1&gt;
&lt;h2&gt;23.1 Backup satu database&lt;/h2&gt;
&lt;p&gt;Custom format:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;pg_dump -Fc -f DATABASE.pgsql DATABASE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Format SQL biasa:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;pg_dump -f DATABASE.sql DATABASE
pg_dump DATABASE &amp;gt; DATABASE.sql
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;23.2 Restore backup&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;psql &amp;lt; backup.sql
psql -1f backup.sql
pg_restore -d DATABASE DATABASE.pgsql
pg_restore backup.pgsql &amp;gt; backup.sql
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Custom format direkomendasikan karena dapat memilih object yang dipulihkan dan mendukung parallel processing.&lt;/p&gt;
&lt;h2&gt;23.3 Backup seluruh cluster&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;pg_dumpall -f backup.sql
postgres-backup-$(date +%Y-%m-%d).sql
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Catatan: backup harian dapat menghasilkan file besar. PostgreSQL memiliki mekanisme backup reguler yang lebih baik seperti WAL archiving.&lt;/p&gt;
&lt;p&gt;Untuk backup filesystem:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT pg_start_backup(&amp;#39;my-backup&amp;#39;);
SELECT pg_stop_backup();
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;File konfigurasi seperti &lt;code&gt;pg_hba.conf&lt;/code&gt; dan &lt;code&gt;postgresql.conf&lt;/code&gt; harus dibackup terpisah.&lt;/p&gt;
&lt;h2&gt;23.4 Menggunakan &lt;code&gt;psql&lt;/code&gt; untuk export data&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;psql -p 5432 -U postgres -d test_database -A -F, -c &amp;quot;select * from user&amp;quot; &amp;gt; /home/USER/user_data.csv
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-F&lt;/code&gt;: delimiter.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-A&lt;/code&gt; / &lt;code&gt;--no-align&lt;/code&gt;: output tanpa alignment.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;23.5 Menggunakan COPY untuk import&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;COPY &amp;lt;tablename&amp;gt; FROM &amp;#39;&amp;lt;filename with path&amp;gt;&amp;#39;;
COPY user FROM &amp;#39;/home/user/user_data.csv&amp;#39;;
COPY user FROM &amp;#39;/home/user/user_data&amp;#39; WITH DELIMITER &amp;#39;|&amp;#39;;
COPY user FROM &amp;#39;/home/user/user_data&amp;#39; WITH DELIMITER &amp;#39;|&amp;#39; HEADER;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;23.6 Menggunakan COPY untuk export&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;COPY &amp;lt;tablename&amp;gt; TO STDOUT (DELIMITER &amp;#39;|&amp;#39;);
COPY user TO STDOUT (DELIMITER &amp;#39;|&amp;#39;);
COPY (SELECT * FROM user WHERE user_name LIKE &amp;#39;A%&amp;#39;) TO &amp;#39;/home/user/user_data&amp;#39;;
COPY user TO PROGRAM &amp;#39;gzip &amp;gt; /home/user/user_data.gz&amp;#39;;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 24: Skrip Backup untuk Database Produksi&lt;/h1&gt;
&lt;p&gt;Parameter:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Keterangan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;save_db&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;direktori backup utama&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dbProd&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;direktori backup sekunder&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DATE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;tanggal backup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dbprod&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;nama database&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pg_dump&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;path binary &lt;code&gt;pg_dump&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-h&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;host server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-p&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;port&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-U&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;username koneksi&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;24.1 &lt;code&gt;saveProdDb.sh&lt;/code&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;#!/bin/sh
cd /save_db
DATE=$(date +%d-%m-%Y-%Hh%M)
echo -e &amp;quot;Sauvegarde de la base du ${DATE}&amp;quot;
mkdir prodDir${DATE}
cd prodDir${DATE}

# dump file
/opt/postgres/9.0/bin/pg_dump -i -h localhost -p 5432 -U postgres -F c -b -w -v -f &amp;quot;dbprod${DATE}.backup&amp;quot; dbprod

# SQL file
/opt/postgres/9.0/bin/pg_dump -i -h localhost -p 5432 -U postgres --format plain --verbose -f &amp;quot;dbprod${DATE}.sql&amp;quot; dbprod
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 25: Mengakses Data Secara Programatis&lt;/h1&gt;
&lt;h2&gt;25.1 Mengakses PostgreSQL dengan C-API&lt;/h2&gt;
&lt;p&gt;C-API memakai library client PostgreSQL &lt;code&gt;libpq&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Kompilasi di GNU C:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;gcc -Wall -I &amp;quot;$(pg_config --includedir)&amp;quot; -L &amp;quot;$(pg_config --libdir)&amp;quot; -o coltype coltype.c -lpq
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Program C biasanya:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Membuka koneksi dengan &lt;code&gt;PQconnectdb&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Mengecek status dengan &lt;code&gt;PQstatus&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Menjalankan query dengan &lt;code&gt;PQexecParams&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Membaca hasil dengan &lt;code&gt;PQntuples&lt;/code&gt;, &lt;code&gt;PQnfields&lt;/code&gt;, &lt;code&gt;PQfname&lt;/code&gt;, dan &lt;code&gt;PQgetvalue&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Membersihkan hasil dengan &lt;code&gt;PQclear&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Menutup koneksi dengan &lt;code&gt;PQfinish&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;25.2 Mengakses PostgreSQL dari Python dengan &lt;code&gt;psycopg2&lt;/code&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import psycopg2

db_host = &amp;#39;postgres.server.com&amp;#39;
db_port = &amp;#39;5432&amp;#39;
db_un = &amp;#39;user&amp;#39;
db_pw = &amp;#39;password&amp;#39;
db_name = &amp;#39;testdb&amp;#39;

conn = psycopg2.connect(
    &amp;quot;dbname={} host={} user={} password={}&amp;quot;.format(db_name, db_host, db_un, db_pw)
)
cur = conn.cursor()
sql = &amp;#39;select * from testtable where id &amp;gt; %s and id &amp;lt; %s&amp;#39;
args = (1, 4)
cur.execute(sql, args)
print(cur.fetchall())
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;25.3 Mengakses PostgreSQL dari .NET dengan Npgsql&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-csharp&quot;&gt;var connString = &amp;quot;Host=myserv;Username=myuser;Password=mypass;Database=mydb&amp;quot;;
using (var conn = new NpgsqlConnection(connString))
{
    var querystring = &amp;quot;INSERT INTO data (some_field) VALUES (@content)&amp;quot;;
    conn.Open();
    using (var cmd = new NpgsqlCommand(querystring, conn))
    {
        var contentString = &amp;quot;Hello World!&amp;quot;;
        cmd.Parameters.Add(&amp;quot;@content&amp;quot;, NpgsqlDbType.Text).Value = contentString;
        cmd.ExecuteNonQuery();
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;25.4 Mengakses PostgreSQL dari PHP menggunakan Pomm2&lt;/h2&gt;
&lt;p&gt;Pomm menyediakan pendekatan modular, converter data, dukungan listen/notify, inspector database, dan lain-lain.&lt;/p&gt;
&lt;p&gt;Query manager Pomm melakukan escaping argument query untuk mencegah SQL injection. Jika argument di-cast, Pomm juga mengonversinya dari representasi PHP menjadi nilai PostgreSQL valid.&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 26: Koneksi PostgreSQL dari Java&lt;/h1&gt;
&lt;p&gt;Java memakai JDBC untuk database relasional. API JDBC diimplementasikan oleh driver JDBC. Letakkan file JAR driver pada Java class path.&lt;/p&gt;
&lt;h2&gt;26.1 Koneksi dengan &lt;code&gt;java.sql.DriverManager&lt;/code&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;private static java.sql.Connection connect(String url, String user, String password)
    throws ClassNotFoundException, java.sql.SQLException {

    Class.forName(&amp;quot;org.postgresql.Driver&amp;quot;);
    return java.sql.DriverManager.getConnection(url, user, password);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;user&lt;/code&gt; dan &lt;code&gt;password&lt;/code&gt; juga dapat dimasukkan dalam JDBC URL.&lt;/p&gt;
&lt;h2&gt;26.2 Koneksi dengan &lt;code&gt;DriverManager&lt;/code&gt; dan &lt;code&gt;Properties&lt;/code&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;private static java.sql.Connection connect(String url, String user, String password)
    throws ClassNotFoundException, java.sql.SQLException {

    Class.forName(&amp;quot;org.postgresql.Driver&amp;quot;);

    java.util.Properties props = new java.util.Properties();
    props.setProperty(&amp;quot;user&amp;quot;, user);
    props.setProperty(&amp;quot;password&amp;quot;, password);
    props.setProperty(&amp;quot;prepareThreshold&amp;quot;, &amp;quot;0&amp;quot;);

    return java.sql.DriverManager.getConnection(url, props);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;26.3 Koneksi dengan &lt;code&gt;javax.sql.DataSource&lt;/code&gt; dan connection pool&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;private static javax.sql.DataSource createDataSource(String url, String user, String password) {
    org.postgresql.ds.PGPoolingDataSource ds = new org.postgresql.ds.PGPoolingDataSource();
    ds.setUrl(url);
    ds.setUser(user);
    ds.setPassword(password);
    ds.setInitialConnections(10);
    ds.setMaxConnections(20);
    ds.setSslMode(&amp;quot;require&amp;quot;);
    ds.setSslfactory(&amp;quot;org.postgresql.ssl.NonValidatingFactory&amp;quot;);
    return ds;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pemakaian:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;java.sql.Connection conn = ds.getConnection();
// lakukan pekerjaan
conn.close(); // mengembalikan koneksi ke pool
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 27: PostgreSQL High Availability&lt;/h1&gt;
&lt;h2&gt;27.1 Replikasi di PostgreSQL&lt;/h2&gt;
&lt;h3&gt;Konfigurasi primary server&lt;/h3&gt;
&lt;p&gt;Kebutuhan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;User replikasi.&lt;/li&gt;
&lt;li&gt;Direktori untuk menyimpan WAL archive.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Membuat user replikasi:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;createuser -U postgres replication -P -c 5 --replication
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Membuat direktori archive:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mkdir $PGDATA/archive
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Tambahkan pada &lt;code&gt;pg_hba.conf&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;host    replication    replication    &amp;lt;slave-IP&amp;gt;/32    md5
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Edit &lt;code&gt;postgresql.conf&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;wal_level = hot_standby
archive_mode = on
archive_command = &amp;#39;test ! -f /path/to/archivedir/%f &amp;amp;&amp;amp; cp %p /path/to/archivedir/%f&amp;#39;
wal_senders = 5
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Restart primary server.&lt;/p&gt;
&lt;h3&gt;Backup primary ke standby&lt;/h3&gt;
&lt;p&gt;Jalankan &lt;code&gt;pg_basebackup&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;pg_basebackup -h &amp;lt;PRIMARY IP&amp;gt; -D /var/lib/postgresql/&amp;lt;VERSION&amp;gt;/main -U replication -v -P --xlog-method=stream
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Keterangan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-D&lt;/code&gt;: lokasi backup awal.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-h&lt;/code&gt;: host primary server.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--xlog-method=stream&lt;/code&gt;: membuka koneksi lain untuk streaming xlog selama backup.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Konfigurasi standby server&lt;/h3&gt;
&lt;p&gt;Pada &lt;code&gt;postgresql.conf&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;hot_standby = on
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Buat &lt;code&gt;recovery.conf&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;standby_mode = on
primary_conninfo = &amp;#39;host=&amp;lt;PRIMARY_IP&amp;gt; port=5432 user=replication password=&amp;lt;PASSWORD&amp;gt;&amp;#39;
trigger_file = &amp;#39;/tmp/postgresql.trigger.5432&amp;#39;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;trigger_file&lt;/code&gt; dapat digunakan untuk memicu failover. Alternatifnya, gunakan &lt;code&gt;pg_ctl promote&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 28: Extension &lt;code&gt;dblink&lt;/code&gt; dan &lt;code&gt;postgres_fdw&lt;/code&gt;&lt;/h1&gt;
&lt;h2&gt;28.1 Extension FDW&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE EXTENSION postgres_fdw;

CREATE SERVER name_srv
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host &amp;#39;hostname&amp;#39;, dbname &amp;#39;bd_name&amp;#39;, port &amp;#39;5432&amp;#39;);

CREATE USER MAPPING FOR postgres
SERVER name_srv
OPTIONS (user &amp;#39;postgres&amp;#39;, password &amp;#39;password&amp;#39;);

CREATE FOREIGN TABLE table_foreign (
  id INTEGER,
  code CHARACTER VARYING
)
SERVER name_srv
OPTIONS (schema_name &amp;#39;schema&amp;#39;, table_name &amp;#39;table&amp;#39;);

SELECT * FROM table_foreign;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;28.2 Foreign Data Wrapper untuk schema lengkap&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE EXTENSION postgres_fdw;

CREATE SERVER server_name
FOREIGN DATA WRAPPER postgres_fdw
OPTIONS (host &amp;#39;host_ip&amp;#39;, dbname &amp;#39;db_name&amp;#39;, port &amp;#39;port_number&amp;#39;);

CREATE USER MAPPING FOR CURRENT_USER
SERVER server_name
OPTIONS (user &amp;#39;user_name&amp;#39;, password &amp;#39;password&amp;#39;);

CREATE SCHEMA schema_name;

IMPORT FOREIGN SCHEMA schema_name_to_import_from_remote_db
FROM SERVER server_name
INTO schema_name;

SELECT * FROM schema_name.table_name;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;28.3 Extension &lt;code&gt;dblink&lt;/code&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE EXTENSION dblink;

SELECT *
FROM dblink(
  &amp;#39;dbname=bd_distance port=5432 host=10.6.6.6 user=username password=passw@rd&amp;#39;,
  &amp;#39;SELECT id, code FROM schema.table&amp;#39;
) AS newTable(id INTEGER, code CHARACTER VARYING);
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1&gt;Bab 29: Tips dan Trik PostgreSQL&lt;/h1&gt;
&lt;h2&gt;29.1 Alternatif &lt;code&gt;DATEADD&lt;/code&gt; di PostgreSQL&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT CURRENT_DATE + &amp;#39;1 day&amp;#39;::INTERVAL;
SELECT &amp;#39;1999-12-11&amp;#39;::TIMESTAMP + &amp;#39;19 days&amp;#39;::INTERVAL;
SELECT &amp;#39;1 month&amp;#39;::INTERVAL + &amp;#39;1 month 3 days&amp;#39;::INTERVAL;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;29.2 Nilai kolom dipisahkan koma&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT STRING_AGG(&amp;lt;TABLE_NAME&amp;gt;.&amp;lt;COLUMN_NAME&amp;gt;, &amp;#39;,&amp;#39;)
FROM &amp;lt;SCHEMA_NAME&amp;gt;.&amp;lt;TABLE_NAME&amp;gt; T;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;29.3 Menghapus record duplikat&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;DELETE FROM &amp;lt;SCHEMA_NAME&amp;gt;.&amp;lt;TABLE_NAME&amp;gt;
WHERE ctid NOT IN (
    SELECT MAX(ctid)
    FROM &amp;lt;SCHEMA_NAME&amp;gt;.&amp;lt;TABLE_NAME&amp;gt;
    GROUP BY &amp;lt;SCHEMA_NAME&amp;gt;.&amp;lt;TABLE_NAME&amp;gt;.*
);
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;29.4 Update dengan join antar dua tabel&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;UPDATE &amp;lt;SCHEMA_NAME&amp;gt;.&amp;lt;TABLE_NAME_1&amp;gt; AS A
SET &amp;lt;COLUMN_1&amp;gt; = TRUE
FROM &amp;lt;SCHEMA_NAME&amp;gt;.&amp;lt;TABLE_NAME_2&amp;gt; AS B
WHERE A.&amp;lt;COLUMN_2&amp;gt; = B.&amp;lt;COLUMN_2&amp;gt;
  AND A.&amp;lt;COLUMN_3&amp;gt; = B.&amp;lt;COLUMN_3&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;29.5 Selisih dua timestamp dalam bulan dan tahun&lt;/h2&gt;
&lt;p&gt;Selisih bulan:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT (
    (DATE_PART(&amp;#39;year&amp;#39;, AgeonDate) - DATE_PART(&amp;#39;year&amp;#39;, tmpdate)) * 12
    +
    (DATE_PART(&amp;#39;month&amp;#39;, AgeonDate) - DATE_PART(&amp;#39;month&amp;#39;, tmpdate))
)
FROM dbo.&amp;quot;Table1&amp;quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Selisih tahun:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT (DATE_PART(&amp;#39;year&amp;#39;, AgeonDate) - DATE_PART(&amp;#39;year&amp;#39;, tmpdate))
FROM dbo.&amp;quot;Table1&amp;quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;29.6 Copy/pindah data tabel antar database dengan schema sama&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE EXTENSION dblink;

INSERT INTO &amp;lt;SCHEMA_NAME&amp;gt;.&amp;lt;TABLE_NAME_1&amp;gt;
SELECT *
FROM dblink(
    &amp;#39;HOST=&amp;lt;IP-ADDRESS&amp;gt; USER=&amp;lt;USERNAME&amp;gt; PASSWORD=&amp;lt;PASSWORD&amp;gt; DBNAME=&amp;lt;DATABASE&amp;gt;&amp;#39;,
    &amp;#39;SELECT * FROM &amp;lt;SCHEMA_NAME&amp;gt;.&amp;lt;TABLE_NAME_2&amp;gt;&amp;#39;
) AS &amp;lt;TABLE_NAME&amp;gt; (
    &amp;lt;COLUMN_1&amp;gt; &amp;lt;DATATYPE_1&amp;gt;,
    &amp;lt;COLUMN_2&amp;gt; &amp;lt;DATATYPE_2&amp;gt;,
    &amp;lt;COLUMN_3&amp;gt; &amp;lt;DATATYPE_3&amp;gt;
);
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h1&gt;Kredit&lt;/h1&gt;
&lt;p&gt;Terima kasih kepada para kontributor Stack Overflow Documentation yang menyediakan materi untuk buku ini. Beberapa nama kontributor yang tercantum dalam dokumen sumber antara lain Alison S, Andrew Cichocki, ankidaemon, AstraSerg, Ben, Ben H, bignose, Blackus, chalitha geekiyanage, commonSenseCode, Dakota Wagner, Daniel Lyons, Demircan Celebi, Dmitri Goldring, e4c5, evuez, Goerman, gpdude_, greg, Jakub Fedyczak, jasonszhao, Jefferson, jgm, joseph, Kevin Sylvestre, KIM, KIRAN KUMAR MATAM, Laurenz Albe, leeor, Mohamed Navas, Mokadillion, Nathaniel Waisbrot, Nuri Tasdemir, Patrick, Reboot, Riya Bansal, Tajinder, Tom Gerken, Udlei Nati, user_0, Vao Tsun, wOwhOw, YCF_L, dan lainnya.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Catatan konversi&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Struktur bab dan subbab dipertahankan.&lt;/li&gt;
&lt;li&gt;Kode/perintah dipertahankan dalam bahasa aslinya.&lt;/li&gt;
&lt;li&gt;Istilah teknis umum seperti &lt;code&gt;role&lt;/code&gt;, &lt;code&gt;trigger&lt;/code&gt;, &lt;code&gt;schema&lt;/code&gt;, &lt;code&gt;backup&lt;/code&gt;, &lt;code&gt;restore&lt;/code&gt;, &lt;code&gt;query&lt;/code&gt;, &lt;code&gt;index&lt;/code&gt;, dan &lt;code&gt;extension&lt;/code&gt; dipertahankan bila lebih lazim dalam ekosistem PostgreSQL.&lt;/li&gt;
&lt;/ul&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://ngopidulur.my.id/blog/postgresql-notes-for-professionals/&quot;&gt;https://ngopidulur.my.id/blog/postgresql-notes-for-professionals/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>Ngopidulur</dc:creator><pubDate>Mon, 25 May 2026 22:37:00 GMT</pubDate></item><item><title>Aplikasi Bengkel Project Doc</title><link>https://ngopidulur.my.id/blog/aplikasi-bengkel-project-doc/</link><guid isPermaLink="true">https://ngopidulur.my.id/blog/aplikasi-bengkel-project-doc/</guid><description>Ini adalah dokumentasi project Aplikasi-Bengkel</description><content:encoded>&lt;h1&gt;Dokumentasi Aplikasi Bengkel Home Service&lt;/h1&gt;
&lt;h2&gt;Daftar Isi&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;#gambaran-umum&quot;&gt;Gambaran Umum&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#tech-stack&quot;&gt;Tech Stack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#instalasi--setup&quot;&gt;Instalasi &amp;amp; Setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#arsitektur-aplikasi&quot;&gt;Arsitektur Aplikasi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#database--model&quot;&gt;Database &amp;amp; Model&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#fitur-utama&quot;&gt;Fitur Utama&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#routing--api&quot;&gt;Routing &amp;amp; API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#frontend&quot;&gt;Frontend&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#testing&quot;&gt;Testing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#deployment&quot;&gt;Deployment&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Gambaran Umum&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Bengkel Home Service (ASM MOTOR)&lt;/strong&gt; adalah aplikasi booking servis motor panggilan
berbasis web. Pelanggan dapat memesan layanan servis motor (ganti oli, tune up,
perbaikan ringan) yang dikerjakan langsung di lokasi pelanggan oleh mekanik keliling.&lt;/p&gt;
&lt;h3&gt;Tujuan Aplikasi&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Menyediakan platform booking online untuk servis motor home service&lt;/li&gt;
&lt;li&gt;Mengelola paket layanan dan item servis custom&lt;/li&gt;
&lt;li&gt;Menghitung biaya transport berdasarkan jarak&lt;/li&gt;
&lt;li&gt;Memvalidasi area coverage layanan&lt;/li&gt;
&lt;li&gt;Menyediakan dashboard admin untuk manajemen booking dan analitik&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Lokasi Operasional&lt;/h3&gt;
&lt;p&gt;Karawang, Jawa Barat, Indonesia (area coverage mencakup Karawang Barat, Timur, Kota,
dan sekitarnya dalam radius operasional).&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Tech Stack&lt;/h2&gt;
&lt;h3&gt;Backend&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Teknologi&lt;/th&gt;
&lt;th&gt;Versi&lt;/th&gt;
&lt;th&gt;Keterangan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;PHP&lt;/td&gt;
&lt;td&gt;8.4&lt;/td&gt;
&lt;td&gt;Runtime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Laravel&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;Framework utama&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inertia.js&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Bridge server-client&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fortify&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Autentikasi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wayfinder&lt;/td&gt;
&lt;td&gt;0.x&lt;/td&gt;
&lt;td&gt;Typed route generation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pest&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Testing framework&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pint&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Code formatter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sail&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Docker dev environment&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Frontend&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Teknologi&lt;/th&gt;
&lt;th&gt;Versi&lt;/th&gt;
&lt;th&gt;Keterangan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Svelte&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;UI framework&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tailwind CSS&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Utility-first CSS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vite&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Build tool&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Leaflet&lt;/td&gt;
&lt;td&gt;1.9&lt;/td&gt;
&lt;td&gt;Peta interaktif&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lucide Svelte&lt;/td&gt;
&lt;td&gt;0.468&lt;/td&gt;
&lt;td&gt;Icon library&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bits-ui&lt;/td&gt;
&lt;td&gt;2.15&lt;/td&gt;
&lt;td&gt;Headless UI components&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;svelte-sonner&lt;/td&gt;
&lt;td&gt;0.3&lt;/td&gt;
&lt;td&gt;Toast notifications&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Database&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;MySQL (default)&lt;/li&gt;
&lt;li&gt;SQLite (development alternatif)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Instalasi &amp;amp; Setup&lt;/h2&gt;
&lt;h3&gt;Prasyarat&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;PHP &amp;gt;= 8.3&lt;/li&gt;
&lt;li&gt;Composer&lt;/li&gt;
&lt;li&gt;Node.js &amp;amp; npm&lt;/li&gt;
&lt;li&gt;MySQL / MariaDB&lt;/li&gt;
&lt;li&gt;Git&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Langkah Instalasi&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 1. Clone repository
git clone &amp;lt;repository-url&amp;gt;
cd aplikasi-bengkel

# 2. Install dependencies
composer install
npm install

# 3. Setup environment
cp .env.example .env
php artisan key:generate

# 4. Konfigurasi database di .env
# DB_CONNECTION=mysql
# DB_HOST=127.0.0.1
# DB_PORT=3306
# DB_DATABASE=aplikasi_bengkel
# DB_USERNAME=root
# DB_PASSWORD=

# 5. Jalankan migrasi dan seeder
php artisan migrate
php artisan db:seed

# 6. Build frontend assets
npm run build

# 7. Jalankan development server
composer run dev
# Atau manual:
# php artisan serve
# npm run dev (di terminal terpisah)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Shortcut Setup (Composer Script)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;composer run setup
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Script ini otomatis menjalankan: install dependencies, copy .env, generate key,
migrate, install npm, dan build assets.&lt;/p&gt;
&lt;h3&gt;Environment Variables Penting&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Variable&lt;/th&gt;
&lt;th&gt;Keterangan&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;APP_NAME&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Nama aplikasi&lt;/td&gt;
&lt;td&gt;Bengkel Home Service&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;APP_TIMEZONE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Timezone&lt;/td&gt;
&lt;td&gt;Asia/Jakarta&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;APP_LOCALE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Locale&lt;/td&gt;
&lt;td&gt;id&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;WORKSHOP_CONTACT_PHONE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Nomor telepon bengkel&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;WORKSHOP_CONTACT_WHATSAPP&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Nomor WhatsApp bengkel&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;WORKSHOP_FOOTER_ADDRESS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Alamat bengkel&lt;/td&gt;
&lt;td&gt;Jl. Badami Ciherang...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;WORKSHOP_FOOTER_LATITUDE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Latitude lokasi bengkel&lt;/td&gt;
&lt;td&gt;-6.3025000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;WORKSHOP_FOOTER_LONGITUDE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Longitude lokasi bengkel&lt;/td&gt;
&lt;td&gt;107.3035000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;WORKSHOP_TRANSPORT_FREE_RADIUS_KM&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Radius gratis ongkir (km)&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;WORKSHOP_TRANSPORT_FEE_PER_KM&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Biaya per km di luar radius&lt;/td&gt;
&lt;td&gt;5000&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Arsitektur Aplikasi&lt;/h2&gt;
&lt;h3&gt;Struktur Direktori Utama&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;aplikasi-bengkel/
├── app/
│   ├── Actions/              # Business logic (single-responsibility)
│   │   ├── Booking/          # Aksi terkait booking
│   │   ├── CustomServiceItem/# Aksi item servis custom
│   │   ├── Fortify/          # Aksi autentikasi
│   │   ├── ServicePackage/   # Aksi paket servis
│   │   └── Visitor/          # Aksi tracking visitor
│   ├── Concerns/             # Shared traits
│   ├── Http/
│   │   ├── Controllers/
│   │   │   ├── Admin/        # Controller panel admin
│   │   │   ├── Public/       # Controller halaman publik
│   │   │   └── Settings/     # Controller pengaturan user
│   │   ├── Middleware/       # HTTP middleware
│   │   └── Requests/         # Form request validation
│   ├── Models/               # Eloquent models
│   └── Support/
│       └── Enums/            # PHP enums
├── config/
│   ├── booking.php           # Konfigurasi booking
│   └── workshop.php          # Konfigurasi bengkel
├── database/
│   ├── factories/            # Model factories
│   ├── migrations/           # Database migrations
│   └── seeders/              # Database seeders
├── resources/
│   └── js/
│       ├── components/       # Svelte components
│       │   ├── admin/        # Komponen admin
│       │   ├── public/       # Komponen publik
│       │   └── ui/           # UI primitives (shadcn-svelte)
│       ├── layouts/          # Layout templates
│       └── pages/            # Inertia pages
│           ├── admin/        # Halaman admin
│           ├── auth/         # Halaman autentikasi
│           ├── public/       # Halaman publik
│           └── settings/     # Halaman pengaturan
├── routes/
│   ├── web.php               # Route utama
│   └── settings.php          # Route pengaturan
└── tests/
    ├── Feature/              # Feature tests
    └── Unit/                 # Unit tests
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Pola Arsitektur&lt;/h3&gt;
&lt;h4&gt;Actions Pattern&lt;/h4&gt;
&lt;p&gt;Aplikasi menggunakan pola &lt;strong&gt;Actions&lt;/strong&gt; untuk memisahkan business logic dari controller.
Setiap action adalah class dengan satu tanggung jawab tunggal.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;app/Actions/Booking/
├── CalculateBookingPriceAction.php    # Hitung total harga booking
├── CalculateTransportChargeAction.php # Hitung biaya transport
├── CreateBookingAction.php            # Buat booking baru
├── DeleteBookingAction.php            # Hapus booking
├── GenerateBookingCodeAction.php      # Generate kode booking unik
├── GetBookingFooterLocationAction.php # Ambil lokasi footer
├── GetBookingServiceFeeAction.php     # Ambil biaya jasa
├── GetBookingTransportChargeSettingsAction.php # Ambil setting transport
├── GetPublicBookingPageDataAction.php # Data untuk halaman booking publik
├── UpdateBookingFooterLocationAction.php # Update lokasi footer
├── UpdateBookingNotesAction.php       # Update catatan booking
├── UpdateBookingServiceFeeAction.php  # Update biaya jasa
├── UpdateBookingStatusAction.php      # Update status booking
├── UpdateBookingTransportChargeAction.php # Update biaya transport
├── ValidateBookingSlotAction.php      # Validasi ketersediaan slot
└── ValidateCoverageAreaAction.php     # Validasi area coverage
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Enums&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;// BookingStatus: pending, confirmed, on_the_way, completed, cancelled, rescheduled
// MotorcycleType: matic, bebek, sport, lainnya
// PackageType: fixed_package, custom_package
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Price Snapshot&lt;/h4&gt;
&lt;p&gt;Saat booking dibuat, nama dan harga paket/item di-snapshot ke dalam record booking.
Ini memastikan perubahan harga di masa depan tidak mempengaruhi booking yang sudah ada.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Database &amp;amp; Model&lt;/h2&gt;
&lt;h3&gt;Entity Relationship Diagram (Konseptual)&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;┌─────────────────┐       ┌──────────────────────┐
│  ServicePackage │       │  ServicePackageItem   │
├─────────────────┤       ├──────────────────────┤
│ id              │──┐    │ id                   │
│ name            │  │    │ service_package_id   │──┐
│ slug            │  │    │ name                 │  │
│ short_description│  │    │ description          │  │
│ description     │  └───&amp;gt;│ display_order        │  │
│ price           │       └──────────────────────┘  │
│ duration_estimate│                                  │
│ is_active       │                                  │
│ display_order   │                                  │
└─────────────────┘                                  │
        │                                            │
        │ (nullable FK)                              │
        ▼                                            │
┌─────────────────────────────────────────────┐     │
│                  Booking                     │     │
├─────────────────────────────────────────────┤     │
│ id, booking_code                            │     │
│ customer_name, customer_email, customer_phone│     │
│ motorcycle_type, motorcycle_brand/model/year │     │
│ plate_number                                │     │
│ package_type, service_package_id            │◄────┘
│ package_name_snapshot, package_price_snapshot │
│ notes, service_date, service_time           │
│ status                                      │
│ subtotal_price, service_fee                 │
│ transport_distance_km, transport_charge     │
│ total_price                                 │
│ address_text, house_landmark                │
│ latitude, longitude                         │
│ admin_notes, requires_manual_review         │
│ confirmed_at, completed_at                  │
└─────────────────────────────────────────────┘
        │                    │
        │                    │
        ▼                    ▼
┌──────────────────┐  ┌──────────────────────┐
│ BookingCustomItem│  │  BookingStatusLog     │
├──────────────────┤  ├──────────────────────┤
│ id               │  │ id                   │
│ booking_id       │  │ booking_id           │
│ custom_service_  │  │ old_status           │
│   item_id        │  │ new_status           │
│ item_name_snapshot│  │ changed_by (user_id) │
│ item_price_snapshot│ │ note                 │
│ qty              │  └──────────────────────┘
│ subtotal         │
└──────────────────┘
        │
        │ (nullable FK)
        ▼
┌──────────────────────┐
│  CustomServiceItem   │
├──────────────────────┤
│ id                   │
│ name, slug           │
│ category             │
│ description          │
│ price                │
│ unit_label           │
│ is_active            │
│ display_order        │
└──────────────────────┘

┌──────────────────┐    ┌──────────────────┐
│  BookingSetting  │    │   VisitorLog     │
├──────────────────┤    ├──────────────────┤
│ id               │    │ id               │
│ service_fee      │    │ visit_date       │
│ transport_free_  │    │ ip_hash          │
│   radius_km      │    │ session_key      │
│ transport_fee_   │    │ path             │
│   per_km         │    │ referrer         │
│ footer_address   │    │ user_agent       │
│ footer_latitude  │    │ is_unique_daily  │
│ footer_longitude │    └──────────────────┘
└──────────────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Deskripsi Tabel&lt;/h3&gt;
&lt;h4&gt;&lt;code&gt;service_packages&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Paket layanan servis tetap yang ditawarkan bengkel.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Kolom&lt;/th&gt;
&lt;th&gt;Tipe&lt;/th&gt;
&lt;th&gt;Keterangan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;name&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Nama paket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;slug&lt;/td&gt;
&lt;td&gt;string (unique)&lt;/td&gt;
&lt;td&gt;URL-friendly identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;short_description&lt;/td&gt;
&lt;td&gt;string(255)&lt;/td&gt;
&lt;td&gt;Deskripsi singkat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;description&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;Deskripsi lengkap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;price&lt;/td&gt;
&lt;td&gt;unsigned int&lt;/td&gt;
&lt;td&gt;Harga dalam Rupiah&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;duration_estimate_minutes&lt;/td&gt;
&lt;td&gt;unsigned int&lt;/td&gt;
&lt;td&gt;Estimasi durasi (menit)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;is_active&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;Status aktif&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;display_order&lt;/td&gt;
&lt;td&gt;unsigned int&lt;/td&gt;
&lt;td&gt;Urutan tampilan&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;&lt;code&gt;service_package_items&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Item-item yang termasuk dalam sebuah paket servis.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Kolom&lt;/th&gt;
&lt;th&gt;Tipe&lt;/th&gt;
&lt;th&gt;Keterangan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;service_package_id&lt;/td&gt;
&lt;td&gt;FK&lt;/td&gt;
&lt;td&gt;Relasi ke service_packages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;name&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Nama item&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;description&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;Deskripsi item&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;display_order&lt;/td&gt;
&lt;td&gt;unsigned int&lt;/td&gt;
&lt;td&gt;Urutan tampilan&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;&lt;code&gt;custom_service_items&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Item servis satuan yang bisa dipilih pelanggan secara custom.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Kolom&lt;/th&gt;
&lt;th&gt;Tipe&lt;/th&gt;
&lt;th&gt;Keterangan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;name&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Nama item&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;slug&lt;/td&gt;
&lt;td&gt;string (unique)&lt;/td&gt;
&lt;td&gt;URL-friendly identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;category&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Kategori item&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;description&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;Deskripsi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;price&lt;/td&gt;
&lt;td&gt;unsigned int&lt;/td&gt;
&lt;td&gt;Harga satuan (Rupiah)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;unit_label&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Label satuan (misal: &amp;quot;liter&amp;quot;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;is_active&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;Status aktif&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;display_order&lt;/td&gt;
&lt;td&gt;unsigned int&lt;/td&gt;
&lt;td&gt;Urutan tampilan&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;&lt;code&gt;bookings&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Record booking pelanggan.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Kolom&lt;/th&gt;
&lt;th&gt;Tipe&lt;/th&gt;
&lt;th&gt;Keterangan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;booking_code&lt;/td&gt;
&lt;td&gt;string (unique)&lt;/td&gt;
&lt;td&gt;Kode booking (prefix: ASM)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;customer_name&lt;/td&gt;
&lt;td&gt;string(100)&lt;/td&gt;
&lt;td&gt;Nama pelanggan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;customer_email&lt;/td&gt;
&lt;td&gt;string(100)&lt;/td&gt;
&lt;td&gt;Email pelanggan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;customer_phone&lt;/td&gt;
&lt;td&gt;string(30)&lt;/td&gt;
&lt;td&gt;Nomor telepon&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;motorcycle_type&lt;/td&gt;
&lt;td&gt;enum&lt;/td&gt;
&lt;td&gt;Tipe motor (matic/bebek/sport/lainnya)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;motorcycle_brand&lt;/td&gt;
&lt;td&gt;string(100)&lt;/td&gt;
&lt;td&gt;Merek motor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;motorcycle_model&lt;/td&gt;
&lt;td&gt;string(100)&lt;/td&gt;
&lt;td&gt;Model motor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;motorcycle_year&lt;/td&gt;
&lt;td&gt;string(4)&lt;/td&gt;
&lt;td&gt;Tahun motor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;plate_number&lt;/td&gt;
&lt;td&gt;string(20)&lt;/td&gt;
&lt;td&gt;Nomor plat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;package_type&lt;/td&gt;
&lt;td&gt;enum&lt;/td&gt;
&lt;td&gt;Tipe paket (fixed/custom)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;service_package_id&lt;/td&gt;
&lt;td&gt;FK (nullable)&lt;/td&gt;
&lt;td&gt;Relasi ke paket tetap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;package_name_snapshot&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Snapshot nama paket saat booking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;package_price_snapshot&lt;/td&gt;
&lt;td&gt;unsigned int&lt;/td&gt;
&lt;td&gt;Snapshot harga paket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;notes&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;Catatan pelanggan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;service_date&lt;/td&gt;
&lt;td&gt;date&lt;/td&gt;
&lt;td&gt;Tanggal servis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;service_time&lt;/td&gt;
&lt;td&gt;string(5)&lt;/td&gt;
&lt;td&gt;Jam servis (HH:MM)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;status&lt;/td&gt;
&lt;td&gt;enum&lt;/td&gt;
&lt;td&gt;Status booking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;subtotal_price&lt;/td&gt;
&lt;td&gt;unsigned int&lt;/td&gt;
&lt;td&gt;Subtotal harga&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;service_fee&lt;/td&gt;
&lt;td&gt;unsigned int&lt;/td&gt;
&lt;td&gt;Biaya jasa&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;transport_distance_km&lt;/td&gt;
&lt;td&gt;decimal(8,2)&lt;/td&gt;
&lt;td&gt;Jarak transport (km)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;transport_charge&lt;/td&gt;
&lt;td&gt;unsigned int&lt;/td&gt;
&lt;td&gt;Biaya transport&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;total_price&lt;/td&gt;
&lt;td&gt;unsigned int&lt;/td&gt;
&lt;td&gt;Total harga akhir&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;address_text&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;Alamat lengkap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;house_landmark&lt;/td&gt;
&lt;td&gt;string(255)&lt;/td&gt;
&lt;td&gt;Patokan rumah&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;latitude&lt;/td&gt;
&lt;td&gt;decimal(10,7)&lt;/td&gt;
&lt;td&gt;Koordinat latitude&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;longitude&lt;/td&gt;
&lt;td&gt;decimal(10,7)&lt;/td&gt;
&lt;td&gt;Koordinat longitude&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;admin_notes&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;Catatan admin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;requires_manual_review&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;Perlu review manual&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;confirmed_at&lt;/td&gt;
&lt;td&gt;timestamp&lt;/td&gt;
&lt;td&gt;Waktu konfirmasi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;completed_at&lt;/td&gt;
&lt;td&gt;timestamp&lt;/td&gt;
&lt;td&gt;Waktu selesai&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;&lt;code&gt;booking_custom_items&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Item custom yang dipilih dalam sebuah booking.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Kolom&lt;/th&gt;
&lt;th&gt;Tipe&lt;/th&gt;
&lt;th&gt;Keterangan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;booking_id&lt;/td&gt;
&lt;td&gt;FK&lt;/td&gt;
&lt;td&gt;Relasi ke bookings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;custom_service_item_id&lt;/td&gt;
&lt;td&gt;FK (nullable)&lt;/td&gt;
&lt;td&gt;Relasi ke custom_service_items&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;item_name_snapshot&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Snapshot nama item&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;item_price_snapshot&lt;/td&gt;
&lt;td&gt;unsigned int&lt;/td&gt;
&lt;td&gt;Snapshot harga item&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;qty&lt;/td&gt;
&lt;td&gt;unsigned int&lt;/td&gt;
&lt;td&gt;Jumlah&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;subtotal&lt;/td&gt;
&lt;td&gt;unsigned int&lt;/td&gt;
&lt;td&gt;Subtotal (harga × qty)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;&lt;code&gt;booking_status_logs&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Audit trail perubahan status booking.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Kolom&lt;/th&gt;
&lt;th&gt;Tipe&lt;/th&gt;
&lt;th&gt;Keterangan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;booking_id&lt;/td&gt;
&lt;td&gt;FK&lt;/td&gt;
&lt;td&gt;Relasi ke bookings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;old_status&lt;/td&gt;
&lt;td&gt;string (nullable)&lt;/td&gt;
&lt;td&gt;Status sebelumnya&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;new_status&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Status baru&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;changed_by&lt;/td&gt;
&lt;td&gt;FK (nullable)&lt;/td&gt;
&lt;td&gt;User yang mengubah&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;note&lt;/td&gt;
&lt;td&gt;string(500)&lt;/td&gt;
&lt;td&gt;Catatan perubahan&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;&lt;code&gt;booking_settings&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Pengaturan global booking (singleton row).&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Kolom&lt;/th&gt;
&lt;th&gt;Tipe&lt;/th&gt;
&lt;th&gt;Keterangan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;service_fee&lt;/td&gt;
&lt;td&gt;unsigned int&lt;/td&gt;
&lt;td&gt;Biaya jasa default&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;transport_free_radius_km&lt;/td&gt;
&lt;td&gt;decimal&lt;/td&gt;
&lt;td&gt;Radius gratis transport&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;transport_fee_per_km&lt;/td&gt;
&lt;td&gt;unsigned int&lt;/td&gt;
&lt;td&gt;Biaya per km&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;footer_address&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Alamat footer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;footer_latitude&lt;/td&gt;
&lt;td&gt;decimal&lt;/td&gt;
&lt;td&gt;Latitude footer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;footer_longitude&lt;/td&gt;
&lt;td&gt;decimal&lt;/td&gt;
&lt;td&gt;Longitude footer&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;&lt;code&gt;visitor_logs&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Log kunjungan halaman (privacy-friendly, IP di-hash).&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Kolom&lt;/th&gt;
&lt;th&gt;Tipe&lt;/th&gt;
&lt;th&gt;Keterangan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;visit_date&lt;/td&gt;
&lt;td&gt;date&lt;/td&gt;
&lt;td&gt;Tanggal kunjungan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ip_hash&lt;/td&gt;
&lt;td&gt;string(64)&lt;/td&gt;
&lt;td&gt;Hash IP pengunjung&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;session_key&lt;/td&gt;
&lt;td&gt;string(120)&lt;/td&gt;
&lt;td&gt;Session identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;path&lt;/td&gt;
&lt;td&gt;string(255)&lt;/td&gt;
&lt;td&gt;Path halaman&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;referrer&lt;/td&gt;
&lt;td&gt;string(255)&lt;/td&gt;
&lt;td&gt;Referrer URL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;user_agent&lt;/td&gt;
&lt;td&gt;text&lt;/td&gt;
&lt;td&gt;User agent browser&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;is_unique_daily&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;Kunjungan unik harian&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Fitur Utama&lt;/h2&gt;
&lt;h3&gt;1. Landing Page Publik&lt;/h3&gt;
&lt;p&gt;Halaman utama yang menampilkan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hero section dengan tagline bengkel&lt;/li&gt;
&lt;li&gt;Highlight layanan (Servis Rutin, Ganti Oli, Perbaikan Darurat)&lt;/li&gt;
&lt;li&gt;Paket servis aktif dari database&lt;/li&gt;
&lt;li&gt;Cara kerja booking (3 langkah)&lt;/li&gt;
&lt;li&gt;Area coverage layanan&lt;/li&gt;
&lt;li&gt;FAQ&lt;/li&gt;
&lt;li&gt;Testimonial pelanggan&lt;/li&gt;
&lt;li&gt;CTA menuju form booking&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. Sistem Booking&lt;/h3&gt;
&lt;h4&gt;Alur Booking Pelanggan&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;Landing Page → Form Booking → Review → Submit → Halaman Sukses
&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Pilih Paket&lt;/strong&gt; — Fixed package (paket tetap) atau custom package (pilih item sendiri)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Info Motor&lt;/strong&gt; — Tipe, merek, model, tahun, plat nomor&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pilih Jadwal&lt;/strong&gt; — Tanggal dan jam servis (slot tersedia: 08:00-16:00)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tentukan Lokasi&lt;/strong&gt; — Alamat, patokan rumah, pin di peta (Leaflet)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Review &amp;amp; Submit&lt;/strong&gt; — Ringkasan harga termasuk biaya jasa dan transport&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Validasi Booking&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Slot Capacity&lt;/strong&gt;: Maksimal 3 booking per slot waktu&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Coverage Area&lt;/strong&gt;: Bounding box check (latitude/longitude)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rate Limiting&lt;/strong&gt;: Maksimal 5 percobaan per 10 menit per device&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Out-of-area&lt;/strong&gt;: Booking di luar area otomatis ditandai &lt;code&gt;requires_manual_review&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Perhitungan Harga&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;Total = Subtotal Paket/Item + Service Fee + Transport Charge

Transport Charge:
- Jarak ≤ free_radius_km (default 10km) → Rp 0
- Jarak &amp;gt; free_radius_km → (jarak - free_radius) × fee_per_km (default Rp5.000/km)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. Manajemen Booking (Admin)&lt;/h3&gt;
&lt;h4&gt;Status Workflow&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;Pending → Confirmed → On The Way → Completed
    │         │
    └─────────┴──→ Cancelled
    │
    └──→ Rescheduled
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Fitur admin:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lihat daftar semua booking (filter, search)&lt;/li&gt;
&lt;li&gt;Detail booking lengkap&lt;/li&gt;
&lt;li&gt;Update status booking (dengan catatan)&lt;/li&gt;
&lt;li&gt;Tambah admin notes&lt;/li&gt;
&lt;li&gt;Hapus booking&lt;/li&gt;
&lt;li&gt;Audit trail perubahan status&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4. Manajemen Paket Servis (Admin)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;CRUD paket servis (nama, deskripsi, harga, estimasi durasi)&lt;/li&gt;
&lt;li&gt;Kelola item dalam paket (nama, deskripsi, urutan)&lt;/li&gt;
&lt;li&gt;Aktivasi/deaktivasi paket&lt;/li&gt;
&lt;li&gt;Pengaturan urutan tampilan&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;5. Manajemen Item Servis Custom (Admin)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;CRUD item servis custom (nama, kategori, harga, satuan)&lt;/li&gt;
&lt;li&gt;Deaktivasi item&lt;/li&gt;
&lt;li&gt;Pengaturan urutan tampilan&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;6. Pengaturan Booking (Admin)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Service Fee&lt;/strong&gt;: Biaya jasa yang ditambahkan ke setiap booking&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Transport Charge&lt;/strong&gt;: Radius gratis dan biaya per km&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Footer Location&lt;/strong&gt;: Alamat dan koordinat bengkel (titik awal perhitungan jarak)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;7. Analitik Visitor&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Tracking kunjungan halaman (privacy-friendly, IP di-hash)&lt;/li&gt;
&lt;li&gt;Statistik kunjungan harian&lt;/li&gt;
&lt;li&gt;Unique visitor per hari&lt;/li&gt;
&lt;li&gt;Chart visualisasi&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;8. Autentikasi &amp;amp; Keamanan&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Login admin (Laravel Fortify)&lt;/li&gt;
&lt;li&gt;Two-Factor Authentication (2FA)&lt;/li&gt;
&lt;li&gt;Password reset&lt;/li&gt;
&lt;li&gt;Profile management&lt;/li&gt;
&lt;li&gt;Session management&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Routing &amp;amp; API&lt;/h2&gt;
&lt;h3&gt;Route Publik&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;URI&lt;/th&gt;
&lt;th&gt;Nama&lt;/th&gt;
&lt;th&gt;Keterangan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;home&lt;/td&gt;
&lt;td&gt;Landing page&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/booking&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bookings.create&lt;/td&gt;
&lt;td&gt;Form booking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/bookings&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bookings.store&lt;/td&gt;
&lt;td&gt;Submit booking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/booking/success&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bookings.success&lt;/td&gt;
&lt;td&gt;Halaman sukses&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/booking/{code}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;bookings.public.show&lt;/td&gt;
&lt;td&gt;Detail booking publik&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Route Admin (prefix: &lt;code&gt;/admin&lt;/code&gt;, middleware: &lt;code&gt;auth&lt;/code&gt;)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;URI&lt;/th&gt;
&lt;th&gt;Nama&lt;/th&gt;
&lt;th&gt;Keterangan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/admin/dashboard&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;admin.dashboard&lt;/td&gt;
&lt;td&gt;Dashboard&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/admin/bookings&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;admin.bookings.index&lt;/td&gt;
&lt;td&gt;Daftar booking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/admin/bookings/{code}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;admin.bookings.show&lt;/td&gt;
&lt;td&gt;Detail booking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PATCH&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/admin/bookings/{code}/status&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;admin.bookings.update-status&lt;/td&gt;
&lt;td&gt;Update status&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PATCH&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/admin/bookings/{code}/notes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;admin.bookings.update-notes&lt;/td&gt;
&lt;td&gt;Update catatan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/admin/bookings/{code}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;admin.bookings.destroy&lt;/td&gt;
&lt;td&gt;Hapus booking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/admin/service-packages&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;admin.service-packages.index&lt;/td&gt;
&lt;td&gt;Daftar paket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/admin/service-packages&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;admin.service-packages.store&lt;/td&gt;
&lt;td&gt;Buat paket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/admin/service-packages/{id}/edit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;admin.service-packages.edit&lt;/td&gt;
&lt;td&gt;Edit paket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PATCH&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/admin/service-packages/{id}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;admin.service-packages.update&lt;/td&gt;
&lt;td&gt;Update paket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PATCH&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/admin/service-packages/{id}/activate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;admin.service-packages.activate&lt;/td&gt;
&lt;td&gt;Aktifkan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PATCH&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/admin/service-packages/{id}/deactivate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;admin.service-packages.deactivate&lt;/td&gt;
&lt;td&gt;Nonaktifkan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/admin/service-packages/{id}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;admin.service-packages.destroy&lt;/td&gt;
&lt;td&gt;Hapus paket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/admin/custom-service-items&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;admin.custom-service-items.index&lt;/td&gt;
&lt;td&gt;Daftar item&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/admin/custom-service-items&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;admin.custom-service-items.store&lt;/td&gt;
&lt;td&gt;Buat item&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/admin/custom-service-items/{id}/edit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;admin.custom-service-items.edit&lt;/td&gt;
&lt;td&gt;Edit item&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PATCH&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/admin/custom-service-items/{id}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;admin.custom-service-items.update&lt;/td&gt;
&lt;td&gt;Update item&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PATCH&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/admin/custom-service-items/{id}/deactivate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;admin.custom-service-items.deactivate&lt;/td&gt;
&lt;td&gt;Nonaktifkan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/admin/custom-service-items/{id}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;admin.custom-service-items.destroy&lt;/td&gt;
&lt;td&gt;Hapus item&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PATCH&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/admin/booking-settings/service-fee&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;admin.booking-settings.service-fee&lt;/td&gt;
&lt;td&gt;Update fee&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PATCH&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/admin/booking-settings/footer-location&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;admin.booking-settings.footer-location&lt;/td&gt;
&lt;td&gt;Update lokasi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PATCH&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/admin/booking-settings/transport-charge&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;admin.booking-settings.transport-charge&lt;/td&gt;
&lt;td&gt;Update transport&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/admin/visitors&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;admin.visitors.index&lt;/td&gt;
&lt;td&gt;Analitik visitor&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Route Settings (middleware: &lt;code&gt;auth&lt;/code&gt;)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;URI&lt;/th&gt;
&lt;th&gt;Nama&lt;/th&gt;
&lt;th&gt;Keterangan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/settings/profile&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;profile.edit&lt;/td&gt;
&lt;td&gt;Edit profil&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PATCH&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/settings/profile&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;profile.update&lt;/td&gt;
&lt;td&gt;Update profil&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/settings/profile&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;profile.destroy&lt;/td&gt;
&lt;td&gt;Hapus akun&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/settings/security&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;security.edit&lt;/td&gt;
&lt;td&gt;Keamanan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PUT&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/settings/password&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;user-password.update&lt;/td&gt;
&lt;td&gt;Update password&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/settings/appearance&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;appearance.edit&lt;/td&gt;
&lt;td&gt;Tampilan&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Frontend&lt;/h2&gt;
&lt;h3&gt;Halaman (Inertia Pages)&lt;/h3&gt;
&lt;h4&gt;Publik (&lt;code&gt;resources/js/pages/public/&lt;/code&gt;)&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;Keterangan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;LandingPage.svelte&lt;/td&gt;
&lt;td&gt;Halaman utama dengan info layanan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BookingPage.svelte&lt;/td&gt;
&lt;td&gt;Form booking multi-step&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BookingSummaryPage.svelte&lt;/td&gt;
&lt;td&gt;Detail booking setelah submit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BookingSuccessPage.svelte&lt;/td&gt;
&lt;td&gt;Konfirmasi booking berhasil&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;Admin (&lt;code&gt;resources/js/pages/admin/&lt;/code&gt;)&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;Keterangan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;DashboardPage.svelte&lt;/td&gt;
&lt;td&gt;Dashboard statistik&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BookingsIndexPage.svelte&lt;/td&gt;
&lt;td&gt;Daftar semua booking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BookingDetailPage.svelte&lt;/td&gt;
&lt;td&gt;Detail &amp;amp; manajemen booking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ServicePackagesPage.svelte&lt;/td&gt;
&lt;td&gt;CRUD paket servis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CustomServiceItemsPage.svelte&lt;/td&gt;
&lt;td&gt;CRUD item custom&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VisitorsPage.svelte&lt;/td&gt;
&lt;td&gt;Analitik pengunjung&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;auth/LoginPage.svelte&lt;/td&gt;
&lt;td&gt;Halaman login admin&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;Settings (&lt;code&gt;resources/js/pages/settings/&lt;/code&gt;)&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;File&lt;/th&gt;
&lt;th&gt;Keterangan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Profile.svelte&lt;/td&gt;
&lt;td&gt;Edit profil user&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security.svelte&lt;/td&gt;
&lt;td&gt;Password &amp;amp; 2FA&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Appearance.svelte&lt;/td&gt;
&lt;td&gt;Tema tampilan&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;Komponen Utama&lt;/h3&gt;
&lt;h4&gt;Komponen Publik (&lt;code&gt;resources/js/components/public/&lt;/code&gt;)&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Komponen&lt;/th&gt;
&lt;th&gt;Keterangan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;HeroSection&lt;/td&gt;
&lt;td&gt;Banner utama landing page&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ServiceHighlights&lt;/td&gt;
&lt;td&gt;Highlight layanan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PackageCardsSection&lt;/td&gt;
&lt;td&gt;Kartu paket servis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HowItWorksSection&lt;/td&gt;
&lt;td&gt;Langkah-langkah booking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CoverageAreaSection&lt;/td&gt;
&lt;td&gt;Peta area layanan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FaqSection&lt;/td&gt;
&lt;td&gt;Frequently Asked Questions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TestimonialsSection&lt;/td&gt;
&lt;td&gt;Testimoni pelanggan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BookingCtaSection&lt;/td&gt;
&lt;td&gt;Call-to-action booking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BookingForm&lt;/td&gt;
&lt;td&gt;Form booking utama&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BookingPackageSelector&lt;/td&gt;
&lt;td&gt;Pemilih paket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BookingCustomItemsSelector&lt;/td&gt;
&lt;td&gt;Pemilih item custom&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BookingMotorInfoFields&lt;/td&gt;
&lt;td&gt;Input info motor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BookingSchedulePicker&lt;/td&gt;
&lt;td&gt;Pemilih jadwal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BookingLocationPicker&lt;/td&gt;
&lt;td&gt;Pemilih lokasi (peta)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BookingPriceSummary&lt;/td&gt;
&lt;td&gt;Ringkasan harga&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BookingReviewPanel&lt;/td&gt;
&lt;td&gt;Panel review sebelum submit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PublicHeader&lt;/td&gt;
&lt;td&gt;Header halaman publik&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PublicFooter&lt;/td&gt;
&lt;td&gt;Footer dengan peta&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;Komponen Admin (&lt;code&gt;resources/js/components/admin/&lt;/code&gt;)&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Komponen&lt;/th&gt;
&lt;th&gt;Keterangan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;AdminHeader&lt;/td&gt;
&lt;td&gt;Header panel admin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AdminSidebar&lt;/td&gt;
&lt;td&gt;Sidebar navigasi admin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BookingsTable&lt;/td&gt;
&lt;td&gt;Tabel daftar booking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BookingDetailCard&lt;/td&gt;
&lt;td&gt;Kartu detail booking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BookingStatusBadge&lt;/td&gt;
&lt;td&gt;Badge status booking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;StatusHistoryTimeline&lt;/td&gt;
&lt;td&gt;Timeline riwayat status&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BookingServiceFeeCard&lt;/td&gt;
&lt;td&gt;Pengaturan biaya jasa&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BookingTransportChargeCard&lt;/td&gt;
&lt;td&gt;Pengaturan transport&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BookingFooterLocationCard&lt;/td&gt;
&lt;td&gt;Pengaturan lokasi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ServicePackageForm&lt;/td&gt;
&lt;td&gt;Form paket servis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ServicePackageItemsEditor&lt;/td&gt;
&lt;td&gt;Editor item paket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CustomServiceItemForm&lt;/td&gt;
&lt;td&gt;Form item custom&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DashboardStatCard&lt;/td&gt;
&lt;td&gt;Kartu statistik dashboard&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VisitorsChart&lt;/td&gt;
&lt;td&gt;Chart pengunjung&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CopyValueButton&lt;/td&gt;
&lt;td&gt;Tombol salin nilai&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;UI Components (&lt;code&gt;resources/js/components/ui/&lt;/code&gt;)&lt;/h4&gt;
&lt;p&gt;Menggunakan komponen headless dari &lt;strong&gt;bits-ui&lt;/strong&gt; dengan styling Tailwind CSS
(pola shadcn-svelte):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Alert, Avatar, Badge, Breadcrumb, Button, Card&lt;/li&gt;
&lt;li&gt;Checkbox, Collapsible, Dialog, Dropdown Menu&lt;/li&gt;
&lt;li&gt;Input, Input OTP, Label, Navigation Menu&lt;/li&gt;
&lt;li&gt;Select, Separator, Sheet, Sidebar&lt;/li&gt;
&lt;li&gt;Skeleton, Sonner (toast), Spinner, Tooltip&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Testing&lt;/h2&gt;
&lt;h3&gt;Framework&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pest v4&lt;/strong&gt; (PHP testing framework di atas PHPUnit)&lt;/li&gt;
&lt;li&gt;Test runner: &lt;code&gt;php artisan test --compact&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Struktur Test&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;tests/
├── Feature/
│   ├── Admin/
│   │   ├── BookingFooterLocationManagementTest.php
│   │   ├── BookingManagementTest.php
│   │   ├── BookingServiceFeeManagementTest.php
│   │   ├── BookingTransportChargeManagementTest.php
│   │   ├── CustomServiceItemManagementTest.php
│   │   ├── ServicePackageManagementTest.php
│   │   └── VisitorAnalyticsTest.php
│   ├── Auth/
│   │   ├── AuthenticationTest.php
│   │   ├── EmailVerificationTest.php
│   │   ├── PasswordConfirmationTest.php
│   │   ├── PasswordResetTest.php
│   │   ├── RegistrationTest.php
│   │   ├── TwoFactorChallengeTest.php
│   │   └── VerificationNotificationTest.php
│   ├── Booking/
│   │   ├── BookingEmailConfirmationTest.php
│   │   ├── BookingPublicPagesTest.php
│   │   ├── BookingTransportChargeTest.php
│   │   └── StoreBookingTest.php
│   ├── Settings/
│   │   ├── ProfileUpdateTest.php
│   │   └── SecurityTest.php
│   └── Visitor/
│       └── TrackVisitorMiddlewareTest.php
├── Unit/
├── Browser/                    # Pest Browser tests (Playwright)
├── Pest.php
└── TestCase.php
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Menjalankan Test&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Semua test
php artisan test --compact

# Filter test tertentu
php artisan test --compact --filter=StoreBookingTest

# Dengan coverage
php artisan test --coverage
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Linting &amp;amp; Formatting&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# PHP (Pint)
vendor/bin/pint --dirty --format agent

# JavaScript/Svelte (ESLint + Prettier)
npm run lint        # Fix lint issues
npm run lint:check  # Check only
npm run format      # Format files
npm run format:check # Check formatting

# TypeScript check
npm run types:check
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;CI/CD&lt;/h3&gt;
&lt;p&gt;GitHub Actions workflows tersedia di &lt;code&gt;.github/workflows/&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;lint.yml&lt;/code&gt; — Linting check&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tests.yml&lt;/code&gt; — Test suite&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Deployment&lt;/h2&gt;
&lt;h3&gt;Prasyarat Production&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;PHP 8.3+ dengan ekstensi yang diperlukan&lt;/li&gt;
&lt;li&gt;MySQL 8.0+&lt;/li&gt;
&lt;li&gt;Node.js (untuk build assets)&lt;/li&gt;
&lt;li&gt;Web server (Nginx/Apache)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Langkah Deploy&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 1. Install dependencies (production)
composer install --no-dev --optimize-autoloader
npm ci

# 2. Build frontend
npm run build

# 3. Optimize Laravel
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache

# 4. Migrasi database
php artisan migrate --force

# 5. Set permissions
chmod -R 775 storage bootstrap/cache
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Laravel Cloud&lt;/h3&gt;
&lt;p&gt;Aplikasi ini dapat di-deploy menggunakan &lt;a href=&quot;https://cloud.laravel.com/&quot;&gt;Laravel Cloud&lt;/a&gt;
untuk deployment dan scaling yang lebih mudah.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Konfigurasi&lt;/h2&gt;
&lt;h3&gt;&lt;code&gt;config/booking.php&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;return [
    &amp;#39;code_prefix&amp;#39; =&amp;gt; &amp;#39;ASM&amp;#39;,           // Prefix kode booking
    &amp;#39;max_per_slot&amp;#39; =&amp;gt; 3,               // Maks booking per slot
    &amp;#39;default_service_fee&amp;#39; =&amp;gt; 0,        // Biaya jasa default
    &amp;#39;slot_interval_minutes&amp;#39; =&amp;gt; 60,     // Interval slot (menit)
    &amp;#39;available_hours&amp;#39; =&amp;gt; [             // Jam operasional
        &amp;#39;08:00&amp;#39;, &amp;#39;09:00&amp;#39;, &amp;#39;10:00&amp;#39;, &amp;#39;11:00&amp;#39;,
        &amp;#39;13:00&amp;#39;, &amp;#39;14:00&amp;#39;, &amp;#39;15:00&amp;#39;, &amp;#39;16:00&amp;#39;,
    ],
    &amp;#39;rate_limit&amp;#39; =&amp;gt; [
        &amp;#39;max_attempts&amp;#39; =&amp;gt; 5,           // Maks percobaan
        &amp;#39;decay_seconds&amp;#39; =&amp;gt; 600,        // Cooldown (detik)
    ],
];
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;&lt;code&gt;config/workshop.php&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;return [
    &amp;#39;brand_name&amp;#39; =&amp;gt; env(&amp;#39;APP_NAME&amp;#39;, &amp;#39;ASM MOTOR&amp;#39;),
    &amp;#39;tagline&amp;#39; =&amp;gt; &amp;#39;Servis ringan motor panggilan...&amp;#39;,
    &amp;#39;contact_phone&amp;#39; =&amp;gt; env(&amp;#39;WORKSHOP_CONTACT_PHONE&amp;#39;),
    &amp;#39;contact_whatsapp&amp;#39; =&amp;gt; env(&amp;#39;WORKSHOP_CONTACT_WHATSAPP&amp;#39;),
    &amp;#39;footer_location&amp;#39; =&amp;gt; [
        &amp;#39;address&amp;#39; =&amp;gt; env(&amp;#39;WORKSHOP_FOOTER_ADDRESS&amp;#39;),
        &amp;#39;latitude&amp;#39; =&amp;gt; env(&amp;#39;WORKSHOP_FOOTER_LATITUDE&amp;#39;),
        &amp;#39;longitude&amp;#39; =&amp;gt; env(&amp;#39;WORKSHOP_FOOTER_LONGITUDE&amp;#39;),
    ],
    &amp;#39;transport_charge&amp;#39; =&amp;gt; [
        &amp;#39;free_radius_km&amp;#39; =&amp;gt; env(&amp;#39;WORKSHOP_TRANSPORT_FREE_RADIUS_KM&amp;#39;, &amp;#39;10&amp;#39;),
        &amp;#39;fee_per_km&amp;#39; =&amp;gt; env(&amp;#39;WORKSHOP_TRANSPORT_FEE_PER_KM&amp;#39;, &amp;#39;5000&amp;#39;),
    ],
    &amp;#39;service_areas&amp;#39; =&amp;gt; [...],          // Daftar area layanan
    &amp;#39;coverage&amp;#39; =&amp;gt; [
        &amp;#39;bounding_box&amp;#39; =&amp;gt; [            // Batas area coverage
            &amp;#39;min_latitude&amp;#39; =&amp;gt; -6.75,
            &amp;#39;max_latitude&amp;#39; =&amp;gt; -6.05,
            &amp;#39;min_longitude&amp;#39; =&amp;gt; 106.55,
            &amp;#39;max_longitude&amp;#39; =&amp;gt; 107.05,
        ],
    ],
    &amp;#39;landing&amp;#39; =&amp;gt; [                     // Konten landing page
        &amp;#39;seo&amp;#39; =&amp;gt; [...],
        &amp;#39;highlights&amp;#39; =&amp;gt; [...],
        &amp;#39;how_it_works&amp;#39; =&amp;gt; [...],
        &amp;#39;coverage&amp;#39; =&amp;gt; [...],
        &amp;#39;faqs&amp;#39; =&amp;gt; [...],
        &amp;#39;testimonials&amp;#39; =&amp;gt; [...],
        &amp;#39;cta&amp;#39; =&amp;gt; [...],
    ],
];
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;Seeder Data&lt;/h2&gt;
&lt;p&gt;Aplikasi menyediakan seeder untuk data awal:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;php artisan db:seed
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Seeder yang tersedia:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;AdminSeeder&lt;/code&gt; — Membuat akun admin default&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ServicePackageSeeder&lt;/code&gt; — Paket servis contoh&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CustomServiceItemSeeder&lt;/code&gt; — Item servis custom contoh&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Scripts Tersedia&lt;/h2&gt;
&lt;h3&gt;Composer Scripts&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Script&lt;/th&gt;
&lt;th&gt;Keterangan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;composer run setup&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Setup lengkap project&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;composer run dev&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Jalankan dev server (Laravel + Queue + Vite)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;composer run lint&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Format PHP dengan Pint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;composer run lint:check&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Check formatting PHP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;composer run test&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Jalankan semua test&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;composer run ci:check&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Full CI check (lint + format + types + test)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;NPM Scripts&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Script&lt;/th&gt;
&lt;th&gt;Keterangan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run dev&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Vite dev server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run build&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Build production assets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run build:ssr&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Build dengan SSR&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run lint&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ESLint fix&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run lint:check&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ESLint check&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run format&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Prettier format&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run format:check&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Prettier check&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;npm run types:check&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Svelte/TypeScript type check&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Lisensi&lt;/h2&gt;
&lt;p&gt;MIT License&lt;/p&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://ngopidulur.my.id/blog/aplikasi-bengkel-project-doc/&quot;&gt;https://ngopidulur.my.id/blog/aplikasi-bengkel-project-doc/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>Ngopidulur</dc:creator><pubDate>Mon, 25 May 2026 22:19:00 GMT</pubDate></item><item><title>Warehouse Queue App Project Doc</title><link>https://ngopidulur.my.id/blog/warehouse-queue-app-project-doc/</link><guid isPermaLink="true">https://ngopidulur.my.id/blog/warehouse-queue-app-project-doc/</guid><description>Dokumentasi Project Warehouse Queue App</description><content:encoded>&lt;p&gt;Terakhir diperbarui: 2026-05-22&lt;/p&gt;
&lt;h2&gt;1. Ringkasan&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;warehouse-queue-app&lt;/code&gt; adalah aplikasi operasional warehouse untuk mengelola:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;antrian truk receiving dan delivery,&lt;/li&gt;
&lt;li&gt;display publik antrian truk,&lt;/li&gt;
&lt;li&gt;dashboard SLA dan laporan operasional,&lt;/li&gt;
&lt;li&gt;master data customer, gate, admin, dan karyawan,&lt;/li&gt;
&lt;li&gt;schedule pengiriman,&lt;/li&gt;
&lt;li&gt;picking progress berbasis proses dan Excel import/export,&lt;/li&gt;
&lt;li&gt;backup, restore, dan migrasi aplikasi antar perangkat Windows.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Project ini terdiri dari:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;backend &lt;code&gt;Node.js + Express + Prisma&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;frontend &lt;code&gt;Vue 3 + Vite + TypeScript&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;database &lt;code&gt;PostgreSQL&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;reverse proxy dan static hosting lokal menggunakan &lt;code&gt;Nginx&lt;/code&gt; di Windows.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;2. Modul Utama&lt;/h2&gt;
&lt;h3&gt;2.1 Antrian Truk&lt;/h3&gt;
&lt;p&gt;Modul ini dipakai untuk mencatat truk masuk dan mengawal status proses dari registrasi sampai selesai atau batal.&lt;/p&gt;
&lt;p&gt;Fitur utama:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;registrasi antrian receiving atau delivery,&lt;/li&gt;
&lt;li&gt;assignment gate,&lt;/li&gt;
&lt;li&gt;update status operasional,&lt;/li&gt;
&lt;li&gt;catatan warehouse,&lt;/li&gt;
&lt;li&gt;audit log perubahan status,&lt;/li&gt;
&lt;li&gt;export Excel,&lt;/li&gt;
&lt;li&gt;display publik untuk monitor antrian.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2.2 Dashboard&lt;/h3&gt;
&lt;p&gt;Dashboard menampilkan ringkasan operasional dan SLA, antara lain:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;summary total antrian,&lt;/li&gt;
&lt;li&gt;status distribution,&lt;/li&gt;
&lt;li&gt;hourly trend,&lt;/li&gt;
&lt;li&gt;top customer,&lt;/li&gt;
&lt;li&gt;data over SLA,&lt;/li&gt;
&lt;li&gt;monthly report,&lt;/li&gt;
&lt;li&gt;schedule summary,&lt;/li&gt;
&lt;li&gt;picking progress summary.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2.3 Master Data&lt;/h3&gt;
&lt;p&gt;Master data yang dikelola:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;customer,&lt;/li&gt;
&lt;li&gt;gate,&lt;/li&gt;
&lt;li&gt;admin user,&lt;/li&gt;
&lt;li&gt;employee.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2.4 Schedule Pengiriman&lt;/h3&gt;
&lt;p&gt;Schedule dipakai untuk perencanaan pengiriman berdasarkan tanggal, customer, store type, dan komposisi truck type.&lt;/p&gt;
&lt;h3&gt;2.5 Picking Progress&lt;/h3&gt;
&lt;p&gt;Modul ini dipakai untuk memonitor progres picking per DO, customer, destination, picker, dan target barcode/qty.&lt;/p&gt;
&lt;p&gt;Fitur utama:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;create/edit data picking,&lt;/li&gt;
&lt;li&gt;start picking,&lt;/li&gt;
&lt;li&gt;update picked quantity,&lt;/li&gt;
&lt;li&gt;finish picking,&lt;/li&gt;
&lt;li&gt;cancel picking,&lt;/li&gt;
&lt;li&gt;import/export Excel,&lt;/li&gt;
&lt;li&gt;print summary,&lt;/li&gt;
&lt;li&gt;audit log perubahan.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;3. Workflow Bisnis&lt;/h2&gt;
&lt;h3&gt;3.1 Workflow Antrian Truk&lt;/h3&gt;
&lt;p&gt;Status utama antrian:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;MENUNGGU -&amp;gt; IN_WH -&amp;gt; PROSES -&amp;gt; SELESAI&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Status alternatif:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;MENUNGGU/IN_WH -&amp;gt; BATAL&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Aturan bisnis penting:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Entry baru selalu dibuat dengan status &lt;code&gt;MENUNGGU&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Warehouse memanggil driver dan mengubah status menjadi &lt;code&gt;IN_WH&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Warehouse memulai bongkar/muat dan mengubah status menjadi &lt;code&gt;PROSES&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Saat pindah ke &lt;code&gt;PROSES&lt;/code&gt;, Tallyman dapat dipilih. Jika diisi, employee harus ada di master karyawan dengan posisi &lt;code&gt;TALLYMAN&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Entry dapat dibatalkan hanya sampai status &lt;code&gt;IN_WH&lt;/code&gt; dan alasan cancel wajib diisi.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;notesFromWh&lt;/code&gt; tidak bisa diubah jika status sudah &lt;code&gt;SELESAI&lt;/code&gt; atau &lt;code&gt;BATAL&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Backend menjalankan auto-complete setiap 1 jam. Data antrian berumur lebih dari 3 hari yang masih &lt;code&gt;MENUNGGU&lt;/code&gt;, &lt;code&gt;IN_WH&lt;/code&gt;, atau &lt;code&gt;PROSES&lt;/code&gt; akan otomatis ditandai &lt;code&gt;SELESAI&lt;/code&gt; oleh sistem.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-mermaid&quot;&gt;flowchart LR
    A[CS/Admin input antrian] --&amp;gt; B[Status MENUNGGU]
    B --&amp;gt; C[Warehouse panggil driver]
    C --&amp;gt; D[Status IN_WH]
    D --&amp;gt; E[Warehouse proses bongkar atau muat]
    E --&amp;gt; F[Status PROSES]
    F --&amp;gt; G[Status SELESAI]
    B --&amp;gt; H[BATAL dengan alasan]
    D --&amp;gt; H
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sumber alur ini sejalan dengan diagram &lt;code&gt;docs/flowchart-workflow-antrian-trucking.drawio&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;3.2 Workflow Picking Progress&lt;/h3&gt;
&lt;p&gt;Status utama picking:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;MENUNGGU -&amp;gt; ON_PROCESS -&amp;gt; SELESAI&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Status alternatif:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;MENUNGGU/ON_PROCESS -&amp;gt; BATAL&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Aturan bisnis penting:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Data picking baru dibuat dengan status &lt;code&gt;MENUNGGU&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Start hanya boleh dari status &lt;code&gt;MENUNGGU&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Update &lt;code&gt;pickedQty&lt;/code&gt; hanya boleh saat status &lt;code&gt;ON_PROCESS&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Finish hanya boleh saat status &lt;code&gt;ON_PROCESS&lt;/code&gt; dan &lt;code&gt;pickedQty&lt;/code&gt; harus sama dengan &lt;code&gt;pickingQty&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Cancel mewajibkan alasan.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;notesFromWh&lt;/code&gt; tidak bisa diubah jika status sudah &lt;code&gt;SELESAI&lt;/code&gt; atau &lt;code&gt;BATAL&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-mermaid&quot;&gt;flowchart LR
    A[Create atau import picking] --&amp;gt; B[Status MENUNGGU]
    B --&amp;gt; C[Start picking]
    C --&amp;gt; D[Status ON_PROCESS]
    D --&amp;gt; E[Update pickedQty]
    E --&amp;gt; F{pickedQty = pickingQty?}
    F -- Ya --&amp;gt; G[Finish]
    G --&amp;gt; H[Status SELESAI]
    F -- Belum --&amp;gt; E
    B --&amp;gt; I[BATAL dengan alasan]
    D --&amp;gt; I
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3.3 Workflow Schedule Pengiriman&lt;/h3&gt;
&lt;p&gt;Alur high level schedule:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Admin atau CS membuat schedule pengiriman.&lt;/li&gt;
&lt;li&gt;Schedule menyimpan tanggal, customer, store type, dan item truck type.&lt;/li&gt;
&lt;li&gt;Data schedule dipakai untuk monitoring, export, print summary, dan dashboard bulanan.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;4. Role dan Hak Akses&lt;/h2&gt;
&lt;p&gt;Role aplikasi:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ADMIN&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WAREHOUSE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CS&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ringkasan akses utama:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Area&lt;/th&gt;
&lt;th&gt;ADMIN&lt;/th&gt;
&lt;th&gt;WAREHOUSE&lt;/th&gt;
&lt;th&gt;CS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Dashboard&lt;/td&gt;
&lt;td&gt;Ya&lt;/td&gt;
&lt;td&gt;Ya&lt;/td&gt;
&lt;td&gt;Ya&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Queue list dan detail&lt;/td&gt;
&lt;td&gt;Ya&lt;/td&gt;
&lt;td&gt;Ya&lt;/td&gt;
&lt;td&gt;Ya&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Queue display publik&lt;/td&gt;
&lt;td&gt;Publik&lt;/td&gt;
&lt;td&gt;Publik&lt;/td&gt;
&lt;td&gt;Publik&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Create/update/status queue&lt;/td&gt;
&lt;td&gt;Ya&lt;/td&gt;
&lt;td&gt;Ya&lt;/td&gt;
&lt;td&gt;Ya&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edit WH notes queue&lt;/td&gt;
&lt;td&gt;Tidak&lt;/td&gt;
&lt;td&gt;Ya&lt;/td&gt;
&lt;td&gt;Tidak&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Master customer&lt;/td&gt;
&lt;td&gt;Ya&lt;/td&gt;
&lt;td&gt;Tidak&lt;/td&gt;
&lt;td&gt;Tidak&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Master gate&lt;/td&gt;
&lt;td&gt;CRUD&lt;/td&gt;
&lt;td&gt;Read&lt;/td&gt;
&lt;td&gt;Read&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Master admin&lt;/td&gt;
&lt;td&gt;Ya&lt;/td&gt;
&lt;td&gt;Tidak&lt;/td&gt;
&lt;td&gt;Tidak&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Master karyawan&lt;/td&gt;
&lt;td&gt;Ya&lt;/td&gt;
&lt;td&gt;Tidak&lt;/td&gt;
&lt;td&gt;Tidak&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Picking progress list&lt;/td&gt;
&lt;td&gt;Ya&lt;/td&gt;
&lt;td&gt;Ya&lt;/td&gt;
&lt;td&gt;Ya&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edit header picking&lt;/td&gt;
&lt;td&gt;Ya&lt;/td&gt;
&lt;td&gt;Tidak&lt;/td&gt;
&lt;td&gt;Ya&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Update WH notes picking&lt;/td&gt;
&lt;td&gt;Tidak&lt;/td&gt;
&lt;td&gt;Ya&lt;/td&gt;
&lt;td&gt;Tidak&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Schedule create/update/delete&lt;/td&gt;
&lt;td&gt;Ya&lt;/td&gt;
&lt;td&gt;Read only&lt;/td&gt;
&lt;td&gt;Ya&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Catatan implementasi:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Route frontend mengarahkan &lt;code&gt;WAREHOUSE&lt;/code&gt; dan &lt;code&gt;CS&lt;/code&gt; ke &lt;code&gt;/antrian-truk&lt;/code&gt; setelah login.&lt;/li&gt;
&lt;li&gt;Route publik tanpa login adalah &lt;code&gt;/login&lt;/code&gt; dan &lt;code&gt;/display/antrian-truk&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Token auth disimpan di &lt;code&gt;localStorage&lt;/code&gt; dan dikirim sebagai &lt;code&gt;Authorization: Bearer &amp;lt;token&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;5. Tech Stack&lt;/h2&gt;
&lt;h3&gt;5.1 Backend&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Node.js&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Express 4&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Prisma ORM 6&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PostgreSQL&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;jsonwebtoken&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;bcryptjs&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;multer&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;exceljs&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;xlsx&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;5.2 Frontend&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Vue 3&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Vite 7&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TypeScript&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Vue Router 4&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Axios&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Tailwind CSS&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Radix Vue&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Chart.js&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vue-chartjs&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;5.3 Infrastruktur Lokal Windows&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Nginx for Windows&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Docker Compose&lt;/code&gt; untuk PostgreSQL opsional&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PowerShell&lt;/code&gt; untuk script operasional&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;6. Arsitektur Sistem&lt;/h2&gt;
&lt;h3&gt;6.1 Arsitektur Runtime&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-mermaid&quot;&gt;flowchart TD
    A[Browser Client] --&amp;gt; B[Nginx Windows port 82]
    B --&amp;gt; C[Frontend dist /material-dashboard-shadcn-vue/]
    B --&amp;gt; D[/api proxy/]
    D --&amp;gt; E[Express API port 3000]
    E --&amp;gt; F[Prisma Client]
    F --&amp;gt; G[PostgreSQL queue_db port 5432]
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;6.2 URL Penting&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Frontend production lokal: &lt;code&gt;http://localhost:82/material-dashboard-shadcn-vue/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Display publik: &lt;code&gt;http://localhost:82/material-dashboard-shadcn-vue/display/antrian-truk&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Backend health check: &lt;code&gt;http://localhost:3000/health&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Nginx health check: &lt;code&gt;http://localhost:82/nginx-health&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;6.3 Port Penting&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Komponen&lt;/th&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Backend Express&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3000&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frontend dev Vite&lt;/td&gt;
&lt;td&gt;&lt;code&gt;5000&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frontend prod via Nginx&lt;/td&gt;
&lt;td&gt;&lt;code&gt;82&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PostgreSQL&lt;/td&gt;
&lt;td&gt;&lt;code&gt;5432&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;7. Struktur Repository&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;backend/                              Backend Express + Prisma
material-dashboard-shadcn-vue-1.0.0/  Frontend Vue + Vite
deploy/windows/                       Script start/stop/backup/restore Windows
docker/                               Docker Compose PostgreSQL
docs/                                 Dokumentasi dan flowchart
nginx-1.28.2/                         Bundled Nginx reference
README.md                             Ringkasan script operasional Windows
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Folder penting:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;backend/src/app.js&lt;/code&gt;: mount route dan middleware.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;backend/src/server.js&lt;/code&gt;: entrypoint backend dan auto-complete job.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;backend/src/routes/&lt;/code&gt;: definisi endpoint per domain.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;backend/src/services/&lt;/code&gt;: business logic dan query database.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;backend/prisma/schema.prisma&lt;/code&gt;: schema relasional utama.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;backend/prisma/migrations/&lt;/code&gt;: histori perubahan schema.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;backend/prisma/seed.js&lt;/code&gt;: seed admin default.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;material-dashboard-shadcn-vue-1.0.0/src/router/index.ts&lt;/code&gt;: route frontend dan guard role.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;material-dashboard-shadcn-vue-1.0.0/src/services/api.ts&lt;/code&gt;: axios client dengan auth interceptor.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;material-dashboard-shadcn-vue-1.0.0/vite.config.ts&lt;/code&gt;: base path, dev server, dan proxy &lt;code&gt;/api&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;deploy/windows/start-local-server.ps1&lt;/code&gt;: start backend dan Nginx.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;deploy/windows/backup-db.ps1&lt;/code&gt;: backup database.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;deploy/windows/restore-db.ps1&lt;/code&gt;: restore database.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;8. Database Relasional&lt;/h2&gt;
&lt;h3&gt;8.1 Database Default&lt;/h3&gt;
&lt;p&gt;Contoh konfigurasi dari &lt;code&gt;backend/.env.example&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-env&quot;&gt;DATABASE_URL=postgresql://sankyu:sankyu39@localhost:5432/queue_db
PORT=3000
NODE_ENV=development
JWT_SECRET=change_this_secret
JWT_EXPIRES_IN=12h
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;8.2 Enum Penting&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;QueueStatus&lt;/code&gt;: &lt;code&gt;MENUNGGU&lt;/code&gt;, &lt;code&gt;IN_WH&lt;/code&gt;, &lt;code&gt;PROSES&lt;/code&gt;, &lt;code&gt;SELESAI&lt;/code&gt;, &lt;code&gt;BATAL&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;QueueCategory&lt;/code&gt;: &lt;code&gt;RECEIVING&lt;/code&gt;, &lt;code&gt;DELIVERY&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AdminRole&lt;/code&gt;: &lt;code&gt;ADMIN&lt;/code&gt;, &lt;code&gt;WAREHOUSE&lt;/code&gt;, &lt;code&gt;CS&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;WarehouseGate&lt;/code&gt;: &lt;code&gt;WH1&lt;/code&gt;, &lt;code&gt;WH2&lt;/code&gt;, &lt;code&gt;DG&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;StoreType&lt;/code&gt;: &lt;code&gt;STORE_IN&lt;/code&gt;, &lt;code&gt;STORE_OUT&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;EmployeePosition&lt;/code&gt;: &lt;code&gt;FOREMAN&lt;/code&gt;, &lt;code&gt;TALLYMAN&lt;/code&gt;, &lt;code&gt;OPR_FORKLIFT&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PickingStatus&lt;/code&gt;: &lt;code&gt;MENUNGGU&lt;/code&gt;, &lt;code&gt;ON_PROCESS&lt;/code&gt;, &lt;code&gt;SELESAI&lt;/code&gt;, &lt;code&gt;BATAL&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TruckType&lt;/code&gt;: &lt;code&gt;CDD&lt;/code&gt;, &lt;code&gt;CDE&lt;/code&gt;, &lt;code&gt;FUSO&lt;/code&gt;, &lt;code&gt;WB&lt;/code&gt;, &lt;code&gt;FT20&lt;/code&gt;, &lt;code&gt;FT40&lt;/code&gt;, &lt;code&gt;OTHER&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;8.3 Entitas Inti&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tabel/Model&lt;/th&gt;
&lt;th&gt;Fungsi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;QueueEntry&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;header antrian truk&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;QueueLog&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;audit log perubahan antrian&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Customer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;master customer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Employee&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;master karyawan/picker/tallyman&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AdminUser&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;user login dan role&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Gate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;master gate warehouse&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ShipmentSchedule&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;header schedule pengiriman&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ShipmentScheduleItem&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;detail truck type per schedule&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PickingProgress&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;header progres picking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PickingProgressLog&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;audit log progres picking&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;8.4 Relasi Database&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-mermaid&quot;&gt;erDiagram
    Customer ||--o{ QueueEntry : has
    Gate ||--o{ QueueEntry : assigned_to
    Employee ||--o{ QueueEntry : tallyman
    QueueEntry ||--o{ QueueLog : logs
    AdminUser ||--o{ QueueLog : acts

    Customer ||--o{ ShipmentSchedule : has
    AdminUser ||--o{ ShipmentSchedule : creates
    ShipmentSchedule ||--o{ ShipmentScheduleItem : contains

    Customer ||--o{ PickingProgress : has
    Employee ||--o{ PickingProgress : picks
    AdminUser ||--o{ PickingProgress : creates
    AdminUser ||--o{ PickingProgress : updates
    PickingProgress ||--o{ PickingProgressLog : logs
    AdminUser ||--o{ PickingProgressLog : acts
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;8.5 Detail Model Operasional&lt;/h3&gt;
&lt;h4&gt;QueueEntry&lt;/h4&gt;
&lt;p&gt;Kolom penting:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;customerId&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gateId&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pickerEmployeeId&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;category&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;driverName&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;truckNumber&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;containerNumber&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transporter&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;registerTime&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;inWhTime&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;startTime&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;finishTime&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;slaWaitingMinutes&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;slaInWhProcessMinutes&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;status&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;notes&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;notesFromWh&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;QueueLog&lt;/h4&gt;
&lt;p&gt;Menyimpan histori status/action antrian, termasuk perubahan otomatis oleh sistem.&lt;/p&gt;
&lt;h4&gt;ShipmentSchedule dan ShipmentScheduleItem&lt;/h4&gt;
&lt;p&gt;Model ini membentuk relasi header-detail schedule:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ShipmentSchedule&lt;/code&gt; menyimpan tanggal, customer, store type, pembuat.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ShipmentScheduleItem&lt;/code&gt; menyimpan truck type, truck type other, dan qty.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;PickingProgress&lt;/h4&gt;
&lt;p&gt;Kolom penting:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;date&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;customerId&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;doNumber&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;destination&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;volumeCbm&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;plTimeRelease&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pickingQty&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pickedQty&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;slaPerBarcodeMinutes&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;startTime&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;finishTime&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;status&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;notesFromWh&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pickerEmployeeId&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;9. API Overview&lt;/h2&gt;
&lt;p&gt;Semua endpoint dipasang di prefix &lt;code&gt;/api&lt;/code&gt;, kecuali &lt;code&gt;/health&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;9.1 Auth&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;POST /api/auth/login&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/auth/me&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POST /api/auth/logout&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;9.2 Queue&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GET /api/queue/display&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POST /api/queue&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/queue&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/queue/export&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/queue/:id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PATCH /api/queue/:id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PATCH /api/queue/:id/wh-notes&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PATCH /api/queue/:id/status&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PATCH /api/queue/:id/set-in-wh&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;9.3 Customers&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GET /api/customers&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POST /api/customers&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/customers/template&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POST /api/customers/import&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/customers/export&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PATCH /api/customers/:id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PUT /api/customers/:id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DELETE /api/customers/:id&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;9.4 Gates&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GET /api/gates&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/master-gates&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POST /api/gates&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PATCH /api/gates/:id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PUT /api/gates/:id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DELETE /api/gates/:id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/gates/template&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POST /api/gates/import&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/gates/export&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;9.5 Employees&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GET /api/employees&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POST /api/employees&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/employees/template&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POST /api/employees/import&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/employees/export&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PATCH /api/employees/:id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PUT /api/employees/:id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DELETE /api/employees/:id&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;9.6 Admin Users&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GET /api/admin-users&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POST /api/admin-users&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PATCH /api/admin-users/:id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DELETE /api/admin-users/:id&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;9.7 Dashboard&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GET /api/dashboard/summary&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/dashboard/schedule-summary&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/dashboard/progress-summary&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/dashboard/picking-progress-summary&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/dashboard/hourly&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/dashboard/status&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/dashboard/top-customers&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/dashboard/over-sla&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/dashboard/monthly-schedule-truck-summary&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/dashboard/monthly-report&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;9.8 Schedules&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;POST /api/schedules&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/schedules&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/schedules/export&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/schedules/print-summary&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/schedules/:id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PUT /api/schedules/:id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DELETE /api/schedules/:id&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;9.9 Picking Progress&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;POST /api/picking-progress&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/picking-progress&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/picking-progress/template&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/picking-progress/print-summary&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POST /api/picking-progress/import&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/picking-progress/export&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GET /api/picking-progress/:id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PATCH /api/picking-progress/:id&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PATCH /api/picking-progress/:id/start&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PATCH /api/picking-progress/:id/picked-qty&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PATCH /api/picking-progress/:id/wh-notes&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PATCH /api/picking-progress/:id/finish&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PATCH /api/picking-progress/:id/cancel&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;10. Frontend Overview&lt;/h2&gt;
&lt;h3&gt;10.1 Base Path dan Routing&lt;/h3&gt;
&lt;p&gt;Frontend dibuild dengan base path:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/material-dashboard-shadcn-vue/&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Implikasinya:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;produksi harus diakses melalui prefix path tersebut,&lt;/li&gt;
&lt;li&gt;router menggunakan &lt;code&gt;createWebHistory(&amp;#39;/material-dashboard-shadcn-vue/&amp;#39;)&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;Vite juga dibuild dengan &lt;code&gt;base: &amp;quot;/material-dashboard-shadcn-vue/&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;10.2 Route Penting&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/login&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/display/antrian-truk&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/dashboard&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/master-customer&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/master-gate&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/master-admin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/master-karyawan&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/antrian-truk&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/antrian-truk/mobile&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/picking-progress&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/schedule-pengiriman&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;10.3 Integrasi API&lt;/h3&gt;
&lt;p&gt;Frontend menggunakan &lt;code&gt;axios&lt;/code&gt; client dengan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;baseURL: &amp;quot;/api&amp;quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;auto-attach bearer token dari &lt;code&gt;localStorage&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;auto logout redirect ke &lt;code&gt;/login&lt;/code&gt; saat menerima &lt;code&gt;401&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;11. Cara Development&lt;/h2&gt;
&lt;h3&gt;11.1 Prasyarat&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Node.js&lt;/code&gt; LTS&lt;/li&gt;
&lt;li&gt;&lt;code&gt;npm&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PostgreSQL&lt;/code&gt; lokal atau &lt;code&gt;Docker&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;opsional &lt;code&gt;Nginx&lt;/code&gt; jika ingin meniru mode production lokal&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;11.2 Setup Database dengan Docker&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cd docker
docker compose up -d
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Database default:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;host: &lt;code&gt;localhost&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;port: &lt;code&gt;5432&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;db: &lt;code&gt;queue_db&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;user: &lt;code&gt;sankyu&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;11.3 Setup Backend&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cd backend
copy .env.example .env
npm ci
npx prisma generate
npx prisma migrate deploy
npm run seed
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Catatan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;migrate:dev&lt;/code&gt; tersedia untuk pengembangan schema.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;migrate:deploy&lt;/code&gt; dipakai untuk sinkronisasi schema yang sudah ada.&lt;/li&gt;
&lt;li&gt;seed default membuat user:&lt;ul&gt;
&lt;li&gt;username: &lt;code&gt;admin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;password: &lt;code&gt;admin123&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;password default harus segera diganti setelah setup awal.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;11.4 Setup Frontend&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cd material-dashboard-shadcn-vue-1.0.0
npm ci
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;11.5 Menjalankan Development Mode&lt;/h3&gt;
&lt;p&gt;Opsi 1, manual:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cd backend
npm run dev
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cd material-dashboard-shadcn-vue-1.0.0
npm run dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Opsi 2, helper script Windows:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bat&quot;&gt;cd deploy\windows
start-dev-fullstack.bat
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Perilaku helper script:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;membuka window backend dan frontend terpisah,&lt;/li&gt;
&lt;li&gt;backend berjalan di port &lt;code&gt;3000&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;frontend mencoba port &lt;code&gt;5000&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;jika port &lt;code&gt;5000&lt;/code&gt; sudah dipakai, script akan mencoba &lt;code&gt;5001&lt;/code&gt; sampai &lt;code&gt;5010&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;11.6 URL Development&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;frontend dev: &lt;code&gt;http://localhost:5000/material-dashboard-shadcn-vue/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;backend health: &lt;code&gt;http://localhost:3000/health&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;11.7 Verifikasi Development&lt;/h3&gt;
&lt;p&gt;Checklist cepat:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;http://localhost:3000/health&lt;/code&gt; mengembalikan &lt;code&gt;{&amp;quot;ok&amp;quot;:true}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Frontend bisa membuka halaman login.&lt;/li&gt;
&lt;li&gt;Login berhasil dengan user valid.&lt;/li&gt;
&lt;li&gt;Data dashboard dan antrian dapat dimuat.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;12. Cara Deployment&lt;/h2&gt;
&lt;p&gt;Dokumen ini merangkum deployment lokal Windows yang memang dipakai repo saat ini.&lt;/p&gt;
&lt;h3&gt;12.1 Pola Deployment Production Lokal&lt;/h3&gt;
&lt;p&gt;Mode ini memakai:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;backend Node.js di port &lt;code&gt;3000&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;frontend hasil build &lt;code&gt;dist&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Nginx&lt;/code&gt; Windows di port &lt;code&gt;82&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;proxy &lt;code&gt;/api&lt;/code&gt; ke &lt;code&gt;http://127.0.0.1:3000&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;12.2 Build Frontend&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cd material-dashboard-shadcn-vue-1.0.0
npm ci
npm run build
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output build:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;material-dashboard-shadcn-vue-1.0.0/dist&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;12.3 Setup Backend Production&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cd backend
npm ci
npx prisma generate
npx prisma migrate deploy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pastikan &lt;code&gt;backend/.env&lt;/code&gt; berisi minimal:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-env&quot;&gt;DATABASE_URL=postgresql://USER:PASSWORD@HOST:5432/queue_db
PORT=3000
NODE_ENV=production
JWT_SECRET=ganti_dengan_secret_yang_aman
JWT_EXPIRES_IN=12h
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;12.4 Start Production Lokal di Windows&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bat&quot;&gt;cd deploy\windows
start-local-server.bat
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Apa yang dilakukan script ini:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;memastikan file backend dan Nginx tersedia,&lt;/li&gt;
&lt;li&gt;mengecek apakah &lt;code&gt;dist/index.html&lt;/code&gt; sudah ada,&lt;/li&gt;
&lt;li&gt;start backend dengan &lt;code&gt;node src/server.js&lt;/code&gt; jika port &lt;code&gt;3000&lt;/code&gt; belum aktif,&lt;/li&gt;
&lt;li&gt;mengetes dan me-reload Nginx,&lt;/li&gt;
&lt;li&gt;menampilkan URL akses lokal dan jaringan.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Konfigurasi penting di script:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;nginxDir = C:\nginx-1.28.2&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;backend port &lt;code&gt;3000&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;frontend/Nginx port &lt;code&gt;82&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Jika lokasi Nginx berbeda, ubah variabel &lt;code&gt;nginxDir&lt;/code&gt; di:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;deploy/windows/start-local-server.ps1&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;deploy/windows/stop-local-server.ps1&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;12.5 Stop Production Lokal&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bat&quot;&gt;cd deploy\windows
stop-local-server.bat
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Script stop akan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;menghentikan proses backend yang listen di port &lt;code&gt;3000&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;menghentikan proses &lt;code&gt;nginx.exe&lt;/code&gt; dari direktori Nginx yang dikonfigurasi.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;12.6 Checklist Deployment&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Build frontend berhasil dan folder &lt;code&gt;dist&lt;/code&gt; terbaru tersedia.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;backend/.env&lt;/code&gt; sudah benar untuk environment target.&lt;/li&gt;
&lt;li&gt;Migrasi database sudah dijalankan.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;http://localhost:3000/health&lt;/code&gt; merespons normal.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;http://localhost:82/material-dashboard-shadcn-vue/&lt;/code&gt; dapat dibuka.&lt;/li&gt;
&lt;li&gt;Login, dashboard, queue, export, dan display publik sudah diuji.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;13. Backup, Restore, dan Migrasi Perangkat&lt;/h2&gt;
&lt;h3&gt;13.1 Backup Database&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bat&quot;&gt;cd deploy\windows
backup-db.bat
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Fitur script backup:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;membaca &lt;code&gt;DATABASE_URL&lt;/code&gt; dari &lt;code&gt;backend/.env&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;mode &lt;code&gt;auto&lt;/code&gt;, &lt;code&gt;host&lt;/code&gt;, atau &lt;code&gt;docker&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;default container docker: &lt;code&gt;queue_system&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;output default ke &lt;code&gt;deploy/windows/backups/*.backup&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Contoh:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bat&quot;&gt;backup-db.bat -Mode docker
backup-db.bat D:\backup\queue_db_manual.backup
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;13.2 Restore Database&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bat&quot;&gt;cd deploy\windows
restore-db.bat
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Fitur script restore:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;membaca &lt;code&gt;DATABASE_URL&lt;/code&gt; dari &lt;code&gt;backend/.env&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;default memakai file backup terbaru jika path tidak diberikan,&lt;/li&gt;
&lt;li&gt;meminta konfirmasi manual &lt;code&gt;YES&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;mendukung mode &lt;code&gt;auto&lt;/code&gt;, &lt;code&gt;host&lt;/code&gt;, dan &lt;code&gt;docker&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Contoh:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bat&quot;&gt;restore-db.bat -Mode docker
restore-db.bat D:\backup\queue_db.backup
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;13.3 Migrasi Perangkat A ke B&lt;/h3&gt;
&lt;p&gt;Panduan rinci sudah tersedia di:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;docs/MIGRATION_A_TO_B.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ringkasan migrasi:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Stop service di perangkat lama.&lt;/li&gt;
&lt;li&gt;Backup database.&lt;/li&gt;
&lt;li&gt;Salin source project ke perangkat baru.&lt;/li&gt;
&lt;li&gt;Install dependency backend dan frontend.&lt;/li&gt;
&lt;li&gt;Build frontend.&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;backend/.env&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Restore database.&lt;/li&gt;
&lt;li&gt;Jalankan &lt;code&gt;npx prisma migrate deploy&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Sesuaikan &lt;code&gt;nginx.conf&lt;/code&gt; dan &lt;code&gt;nginxDir&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Start aplikasi dan verifikasi dari localhost serta jaringan.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;14. Operasional Harian&lt;/h2&gt;
&lt;h3&gt;14.1 Start Service&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bat&quot;&gt;deploy\windows\start-local-server.bat
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;14.2 Stop Service&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bat&quot;&gt;deploy\windows\stop-local-server.bat
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;14.3 Start Development&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bat&quot;&gt;deploy\windows\start-dev-fullstack.bat
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;14.4 Stop Development&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bat&quot;&gt;deploy\windows\stop-dev-fullstack.bat
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;14.5 Backup Berkala&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bat&quot;&gt;deploy\windows\backup-db.bat
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;15. Troubleshooting&lt;/h2&gt;
&lt;h3&gt;15.1 Frontend berubah di source tapi production tidak ikut berubah&lt;/h3&gt;
&lt;p&gt;Penyebab umum:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;frontend belum dibuild ulang,&lt;/li&gt;
&lt;li&gt;folder &lt;code&gt;dist&lt;/code&gt; yang aktif masih versi lama,&lt;/li&gt;
&lt;li&gt;browser cache.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Solusi:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;jalankan &lt;code&gt;npm run build&lt;/code&gt; di folder frontend,&lt;/li&gt;
&lt;li&gt;pastikan folder &lt;code&gt;dist&lt;/code&gt; terbaru yang dilayani Nginx,&lt;/li&gt;
&lt;li&gt;lakukan hard refresh atau incognito.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;15.2 Frontend bisa dibuka tapi API error&lt;/h3&gt;
&lt;p&gt;Penyebab umum:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;backend belum berjalan,&lt;/li&gt;
&lt;li&gt;backend belum ikut di-update,&lt;/li&gt;
&lt;li&gt;database tidak reachable,&lt;/li&gt;
&lt;li&gt;token login sudah tidak valid.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Solusi:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;cek &lt;code&gt;http://localhost:3000/health&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;restart backend,&lt;/li&gt;
&lt;li&gt;cek &lt;code&gt;backend/.env&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;login ulang.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;15.3 &lt;code&gt;404&lt;/code&gt; pada path &lt;code&gt;/material-dashboard-shadcn-vue/&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Penyebab umum:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;base path frontend tidak cocok dengan path yang dilayani server,&lt;/li&gt;
&lt;li&gt;alias Nginx ke folder &lt;code&gt;dist&lt;/code&gt; salah,&lt;/li&gt;
&lt;li&gt;hasil build belum tersedia.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Solusi:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;cek &lt;code&gt;material-dashboard-shadcn-vue-1.0.0/dist/index.html&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;cek path alias di &lt;code&gt;nginx.conf&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;pastikan akses memakai prefix &lt;code&gt;/material-dashboard-shadcn-vue/&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;15.4 &lt;code&gt;pg_dump&lt;/code&gt; atau &lt;code&gt;pg_restore&lt;/code&gt; tidak dikenali&lt;/h3&gt;
&lt;p&gt;Solusi:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;tambahkan PostgreSQL &lt;code&gt;bin&lt;/code&gt; ke &lt;code&gt;PATH&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;atau gunakan mode Docker pada script backup/restore.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;15.5 Port bentrok&lt;/h3&gt;
&lt;p&gt;Port yang perlu dicek:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;3000&lt;/code&gt; untuk backend,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;5000-5010&lt;/code&gt; untuk frontend dev,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;82&lt;/code&gt; untuk Nginx,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;5432&lt;/code&gt; untuk PostgreSQL.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;16. Known Notes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Root &lt;code&gt;package.json&lt;/code&gt; bukan aplikasi utama; package utama ada di &lt;code&gt;backend/&lt;/code&gt; dan &lt;code&gt;material-dashboard-shadcn-vue-1.0.0/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Project saat ini belum menyediakan script automated test di package utama backend/frontend.&lt;/li&gt;
&lt;li&gt;Dokumentasi deploy frontend detail tambahan juga tersedia di &lt;code&gt;docs/deploy-production.md&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Flowchart operasional queue tersedia di &lt;code&gt;docs/flowchart-workflow-antrian-trucking.drawio&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;17. Referensi Dokumen Lain&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;docs/context-project.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docs/deploy-production.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docs/MIGRATION_A_TO_B.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;README.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://ngopidulur.my.id/blog/warehouse-queue-app-project-doc/&quot;&gt;https://ngopidulur.my.id/blog/warehouse-queue-app-project-doc/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>Ngopidulur</dc:creator><pubDate>Fri, 22 May 2026 16:11:00 GMT</pubDate></item><item><title>Di Kaki Bukit Cibalak - Ahmad Tohari</title><link>https://ngopidulur.my.id/blog/di-kaki-bukit-cibalak-ahmad-tohari/</link><guid isPermaLink="true">https://ngopidulur.my.id/blog/di-kaki-bukit-cibalak-ahmad-tohari/</guid><description>Karya sastra Ahmad Tohari yang bercerita tentang kehidupan masyarakat desa di kaki Bukit Cibalak, penuh dengan kritik sosial dan nilai kemanusiaan.</description><content:encoded>&lt;p&gt;&lt;strong&gt;Oleh&lt;/strong&gt;&lt;br&gt;Ahmad Tohari&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Daftar Isi&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#episode-1&quot;&gt;Episode 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#episode-2&quot;&gt;Episode 2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#episode-3&quot;&gt;Episode 3&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#episode-4&quot;&gt;Episode 4&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#episode-5&quot;&gt;Episode 5&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#episode-6&quot;&gt;Episode 6&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#episode-7&quot;&gt;Episode 7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#episode-8&quot;&gt;Episode 8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#episode-9&quot;&gt;Episode 9&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#episode-10&quot;&gt;Episode 10&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#episode-11&quot;&gt;Episode 11&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#episode-12&quot;&gt;Episode 12&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h1&gt;Episode 1&lt;/h1&gt;
&lt;p&gt;Dulu, jalan setapak itu adalah terowongan yang menembus belukar puyengan. Bila iring-iringan kerbau lewat, tubuh mereka tenggelam di bawah terowongan semak itu. Hanya bunyi korakan yang tergantung pada leher mereka terdengar dengan suara berdentang-dentang, iramanya tetap dan datar. Burung-burung kucica yang terkejut, terbang mencicit. Mereka tetap tidak mengerti mengapa kerbau-kerbau senang mengusik ketenteraman belukar puyengan tempat burung-burung kecil itu bersarang.&lt;/p&gt;
&lt;p&gt;Meskipun kerbau-kerbau itu telah jauh memasuki hutan jati Bukit Cibalak, suara korakan mereka masih tetap terdengar. Dan bunyi korakan adalah pertanda yang selalu didengarkan oleh majikan. Para pemilik kerbau di sekitar kaki Bukit Cibalak tidak menggembalakan ternak mereka. Binatang itu bebas berkeliaran mencari rumput, mencari umbut gelagah, atau berkubang di tepi hutan jati.&lt;/p&gt;
&lt;p&gt;Sekarang terowongan di bawah belukar puyengan itu lenyap, berubah menjadi jalan setapak. Tak terdengar lagi suara korakan kerbau karena binatang itu telah banyak diangkut ke kota, dan di sana akan diolah menjadi daging goreng atau makanan anjing. Di sekitar kaki Bukit Cibalak, tenaga kerbau telah digantikan traktor-traktor tangan.&lt;/p&gt;
&lt;p&gt;Burung-burung kucica yang telah turun-temurun mendaulat belukar puyengan itu terpaksa hijrah ke semak-semak kerontang yang menjadi batas antara Bukit Cibalak dan Desa Tanggir di kakinya.&lt;/p&gt;
&lt;p&gt;Orang-orang yang biasa memburuh dengan bajak, kemudian berganti pekerjaan. Pak Danu misalnya, yang dulu dikagumi orang karena kecakapannya memainkan bajak, kini bekerja pada Akiat. Ia menjadi tukang timbang ampas singkong.&lt;/p&gt;
&lt;p&gt;Bekas telapak kerbau yang mengukir jalan-jalan setapak telah terhapus oleh gilasan roda-roda sepeda atau sepeda motor. Dari sebuah lorong setapak yang sempit kini terciptalah sebuah jalan kampung yang agak lebar.&lt;/p&gt;
&lt;p&gt;Orang-orang Tanggir tidak merasa terganggu oleh banyaknya sampah plastik dalam pawuan mereka. Mereka punya kesabaran yang luar biasa untuk menjumputi sampah-sampah pabrik itu bila mereka hendak menjadikan isi pawuan mereka sebagai pupuk kompos.&lt;/p&gt;
&lt;p&gt;Suatu siang Pak Danu pulang dari rumah taukenya. Ia sengaja singgah beberapa kali ke rumah orang-orang yang dikenalnya. Pak Danu ingin memamerkan sebuah tabung yang dicurinya dari rumah Akiat, sambil berpropaganda dengan bangga:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Ya, inilah obat semprot ketiak yang sering disiarkan oleh radio dan televisi. Inilah barangnya. Kalian baru melihat gambarnya atau mendengar namanya saja, bukan? Tetapi aku kini telah memilikinya! Di kampung ini pastilah aku yang pertama kali memiliki barang mahal ini.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Episode 2&lt;/h1&gt;
&lt;p&gt;Selama perjalanannya ke Balai Desa, Jirah yang paling banyak berbicara. Mula-mula ia bercerita tentang pengalamannya menggunakan sampo yang terbaru. Kemudian bercerita tentang sabun yang mengandung minyak zaitun. Jirah tidak perlu merasa bodoh walaupun ia tidak tahu apa itu zaitun. Yang penting ia dapat menirukan kata-kata tukang iklan di radio atau televisi.&lt;/p&gt;
&lt;p&gt;Di halaman Balai Desa telah berkumpul banyak sekali warga Desa Tanggir. Lurah baru akan dipilih hari itu, karena lurah yang lama telah meletakkan jabatan.&lt;/p&gt;
&lt;p&gt;Penduduk Desa Tanggir adalah keturunan dari dua kelompok orang yang berlainan. Kaum kawula yang dulu dipaksa oleh Raja Mataram untuk membuka tanah-tanah rawa di sekitar kaki Bukit Cibalak, adalah nenek moyang kebanyakan orang Tanggir. Seperti nenek moyangnya, orang Tanggir masih berjiwa kawula. Falsafah hidupnya: &lt;strong&gt;nrimo pandum&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Nenek moyang sebagian kecil penduduk Tanggir adalah kerabat ningrat yang menyingkir dari istana Mataram. Di Desa Tanggir mereka menurunkan priyayi-priyayi kecil: opas Kantor Kecamatan, mantri pasar, atau guru-guru sekolah.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Episode 3&lt;/h1&gt;
&lt;p&gt;Dan tiba-tiba perhatian semua orang tertuju ke bawah pohon johar di sudut halaman Balai Desa. Di sana seorang kakek sedang membaca mantra. Tentu ia telah dibayar oleh seorang calon agar “wahyu” datang kepada calon yang telah memberinya uang.&lt;/p&gt;
&lt;p&gt;Tiap-tiap calon mempunyai beberapa orang botoh yang mempunyai tugas sebagai pengumpul suara. Soal cara, tidak diperhatikan benar. Maka para botoh inilah yang hampir selalu mendatangkan onar pada setiap pelaksanaan pemilihan pamong desa.&lt;/p&gt;
&lt;p&gt;Siapa pun yang ingin menjadi lurah Desa Tanggir tidak boleh sayang terhadap uang dua, tiga, atau empat puluh juta rupiah. Kelima orang calon yang hendak dipilih pagi itu telah mengeluarkan uang banyak sekali.&lt;/p&gt;
&lt;p&gt;Meskipun ada lima orang calon, kebanyakan orang mengatakan hanya dua orang yang memiliki peluang. Satu di antaranya adalah &lt;strong&gt;Pak Badi&lt;/strong&gt;. Calon lain yang keadaannya mengimbangi Pak Badi adalah calon yang memegang lambang dengan gambar pedang. Ia bernama &lt;strong&gt;Dirgamulya&lt;/strong&gt;, dan terkenal dengan sebutan &lt;strong&gt;Pak Dirga&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Dan ternyata keluhuran budi, kearifan, serta kejujuran Pak Badi tidak memberikan nasib baik. Ia kalah, karena &lt;strong&gt;Pak Dirga&lt;/strong&gt;-lah yang terpilih.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Episode 4&lt;/h1&gt;
&lt;p&gt;Karena merasa menemukan jalan buntu, Pambudi mulai berpikir untuk mencari pekerjaan lain. Dan keputusannya untuk meninggalkan pekerjaannya yang lama datang dua bulan kemudian.&lt;/p&gt;
&lt;p&gt;Seorang perempuan datang menemui Pambudi. Ia mengajukan permohonan agar diberi pinjaman padi.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Untuk apa padimu nanti, Mbok?”&lt;br&gt;“Akan kujual. Uangnya akan kupergunakan untuk berobat. Lihatlah, leherku membengkak. Sakit sekali rasanya.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Setelah Pak Dirga datang, Pambudi membawa tamunya masuk ke kamar kerja Kepala Desa. Dengan suara lirih dan gemetar, Mbok Ralem mengutarakan maksudnya kepada Pak Dirga.&lt;/p&gt;
&lt;p&gt;Pak Dirga tidak segera memberi jawaban. Ia hanya melihat sepintas saja pada leher Mbok Ralem. Kemudian dengan pandangan mata lurus Pak Dirga berkata:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Mbok Ralem, sebenarnya seorang seperti kamu tidak bisa mendapat pinjaman.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Episode 5&lt;/h1&gt;
&lt;p&gt;“Kali ini saya harus tahu. Soalnya, saya ingin tahu, penting mana rencana Bapak itu dengan keharusan kita menolong Mbok Ralem.”&lt;/p&gt;
&lt;p&gt;Pak Dirga menyembunyikan kagetnya dengan cepat-cepat menyalakan rokok. Ia tidak mengira akan dikejar dengan pertanyaan yang menyelidik seperti itu.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Episode 6&lt;/h1&gt;
&lt;p&gt;Alangkah nyaman hari-hari berikutnya terasa oleh Pambudi. Kenyataan bahwa sekarang ia menjadi penganggur, tidak mengurangi cerahnya perasaannya. Pambudi benar-benar menikmati suasana yang sulit digambarkan.&lt;/p&gt;
&lt;p&gt;Sepedanya dikayuh melalui jalan-jalan kecil yang menyelinap di bawah rumpun-rumpun bambu. Tidak lama, sampailah ia ke halaman sebuah rumah kecil, tanpa pintu.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Mbok Ralem, kau tak perlu takut seperti itu.”&lt;br&gt;“Anu, anu... anu, Nak.”&lt;br&gt;“Anu apa, Mbok?”&lt;br&gt;“Aku takut kau membawa perintah dari Lurah untuk menghukumku.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Episode 7&lt;/h1&gt;
&lt;p&gt;Ketika nama Mbok Ralem disebut, Pambudi ikut masuk ke ruang periksa. Surat keterangan dari Tanggir diperlihatkan kepada mantri yang memeriksa Mbok Ralem.&lt;/p&gt;
&lt;p&gt;Mereka berbicara sebentar, kemudian Pak Mantri bertanya kepada Pambudi:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Apakah Anda anak ibu ini?”&lt;br&gt;“Bukan, tetapi segala sesuatu yang menyangkut perawatan pasien ini dapat dibicarakan dengan saya.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Episode 8&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;“Jadi pertama-tama Anda meminta kesediaan kami untuk memasang iklan. Selanjutnya Anda meminta supaya Kalawarta membuka dompet sumbangan untuk menghimpun dana bagi perawatan Mbok Ralem. Begitu, bukan?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;“Ya, benar, Pak.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Episode 9&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;“Lalu mengapa Bung mengetuk kamar saya? Mengapa tidak mencari penginapan lain?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;“Oh, anu. Begini, ya, Mas, losmen dan hotel di kota ini sedang penuh semua. Dan gadis itu hanya ingin Anda perbolehkan menggelar tikar di lantai kamar Anda.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Episode 10&lt;/h1&gt;
&lt;p&gt;Tiba di Tanggir, Pambudi menemukan kedua anak Mbok Ralem tinggal bersama bibi mereka. Dua minggu ditinggal oleh emaknya, kedua anak itu semakin layu.&lt;/p&gt;
&lt;p&gt;Dari saku celananya Pambudi mengambil uang receh.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Belilah beberapa bungkus meniran,” katanya kepada anak Mbok Ralem yang besar.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Episode 11&lt;/h1&gt;
&lt;p&gt;Keadaan tubuh perempuan Tanggir itu cepat berubah, bersih dan gemuk. Ransumnya bergizi baik dan selalu dimakannya habis.&lt;/p&gt;
&lt;p&gt;Pada hari ke-36 Mbok Ralem diizinkan pulang. Bukan main senang hatinya.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Episode 12&lt;/h1&gt;
&lt;p&gt;“Selamat jalan, Mbok, Pambudi. Aku berterima kasih kepada kalian. Karena kalianlah Kalawarta berkesempatan menunaikan misinya yang paling berarti. Juga karena kalianlah aku merasa yakin bahwa tidak sesuatu pun telah hilang dari diri kita sebagai manusia. Memang, &lt;strong&gt;si Anu&lt;/strong&gt; itu jarang hadir di antara kita. Tetapi bagaimanapun juga &lt;strong&gt;si Anu&lt;/strong&gt; masih ada. Kita sendiri yang baru saja membuktikannya: &lt;strong&gt;Kemanusiaan&lt;/strong&gt;.”&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Penutup&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Di Kaki Bukit Cibalak&lt;/strong&gt; adalah karya Ahmad Tohari yang mengangkat tema kemanusiaan, ketidakadilan sosial, korupsi di tingkat desa, dan perjuangan seorang pemuda bernama Pambudi dalam menolong sesamanya.&lt;/p&gt;
&lt;p&gt;Cerita ini sarat dengan kritik sosial terhadap kondisi masyarakat pedesaan Jawa pada masanya, sekaligus menampilkan harapan melalui tindakan kemanusiaan yang tulus.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Sumber&lt;/strong&gt;: &lt;em&gt;Di Kaki Bukit Cibalak&lt;/em&gt; oleh Ahmad Tohari&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Akhir&lt;/strong&gt;&lt;/p&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://ngopidulur.my.id/blog/di-kaki-bukit-cibalak-ahmad-tohari/&quot;&gt;https://ngopidulur.my.id/blog/di-kaki-bukit-cibalak-ahmad-tohari/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>Ngopidulur</dc:creator><pubDate>Fri, 22 May 2026 15:46:00 GMT</pubDate></item><item><title>AI Harness Engineering: Panduan Lengkap Membangun Production AI Agents</title><link>https://ngopidulur.my.id/blog/ai-harness-engineering-panduan-lengkap-membangun-production-ai-agents/</link><guid isPermaLink="true">https://ngopidulur.my.id/blog/ai-harness-engineering-panduan-lengkap-membangun-production-ai-agents/</guid><description>Panduan lengkap tentang AI Harness Engineering — disiplin untuk membangun lapisan runtime, guardrails, observability, sandboxing, dan governance di sekitar AI Agents. Membahas tujuh lapisan harness, MCP, evaluasi, serta praktik terbaik agar AI Agents bisa diandalkan di production.</description><content:encoded>&lt;p&gt;&lt;strong&gt;Berdasarkan:&lt;/strong&gt; &lt;em&gt;AI Harness Engineering Interview Preparation Handbook&lt;/em&gt; (2026 Edition)&lt;br&gt;&lt;strong&gt;Disusun dalam Bahasa Indonesia&lt;/strong&gt;&lt;br&gt;&lt;strong&gt;Fokus:&lt;/strong&gt; Runtime, Guardrails, MCP, Evals, Observability, dan Production Practices&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Daftar Isi&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;#1-apa-itu-ai-harness-engineering&quot;&gt;Apa Itu AI Harness Engineering?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#2-tujuh-lapisan-harness-untuk-production-ai-agents&quot;&gt;Tujuh Lapisan Harness untuk Production AI Agents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#3-dari-prompt-engineering-ke-harness-engineering&quot;&gt;Dari Prompt Engineering ke Harness Engineering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#4-instruction-engineering-untuk-ai-agents&quot;&gt;Instruction Engineering untuk AI Agents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#5-tool-calling-dan-mcp-model-context-protocol&quot;&gt;Tool Calling dan MCP (Model Context Protocol)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#6-memory-state-dan-retrieval-untuk-ai-agents&quot;&gt;Memory, State, dan Retrieval untuk AI Agents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#7-sandboxing-dan-execution-environment&quot;&gt;Sandboxing dan Execution Environment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#8-evaluasi-observability-dan-reliability-ai-agents&quot;&gt;Evaluasi, Observability, dan Reliability AI Agents&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#9-guardrails-safety-dan-governance&quot;&gt;Guardrails, Safety, dan Governance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#penutup--ringkasan&quot;&gt;Penutup &amp;amp; Ringkasan&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h1&gt;1. Apa Itu AI Harness Engineering?&lt;/h1&gt;
&lt;p&gt;Di tahun 2026, percakapan tentang AI Agents sudah bergeser. Bukan lagi hanya tentang seberapa pintar modelnya, tetapi tentang &lt;strong&gt;seberapa baik kita membungkus model tersebut&lt;/strong&gt; agar bisa diandalkan di production.&lt;/p&gt;
&lt;h2&gt;Definisi AI Harness Engineering&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;AI Harness Engineering&lt;/strong&gt; adalah disiplin ilmu untuk merancang, membangun, dan mengoperasikan lapisan &lt;em&gt;runtime&lt;/em&gt; dan &lt;em&gt;control&lt;/em&gt; yang membungkus language model, sehingga output-nya bisa dipercaya, diaudit, dan dikomposisikan menjadi software production.&lt;/p&gt;
&lt;p&gt;Singkatnya:&lt;br&gt;&lt;strong&gt;Model adalah otaknya. Harness adalah segala sesuatu yang membuat otak itu bisa bekerja dengan aman dan berguna di dunia nyata.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;Agent = Model + Harness&lt;/h2&gt;
&lt;p&gt;Persamaan paling penting dalam bidang ini:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Agent = Model + Harness&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Model&lt;/strong&gt; bersifat komoditas (bisa diganti dengan mudah).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Harness&lt;/strong&gt; adalah &lt;em&gt;capital&lt;/em&gt; yang kamu bangun sendiri dan menjadi pembeda utama.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dua perusahaan yang menggunakan model yang sama bisa menghasilkan produk yang sangat berbeda, tergantung seberapa baik &lt;em&gt;harness&lt;/em&gt; yang mereka miliki.&lt;/p&gt;
&lt;h3&gt;Mengapa Model yang Lebih Pintar Tidak Cukup?&lt;/h3&gt;
&lt;p&gt;Banyak orang berpikir: &amp;quot;Kalau modelnya sudah sangat pintar, harness tidak terlalu penting.&amp;quot; Pengalaman production membuktikan sebaliknya.&lt;/p&gt;
&lt;p&gt;Model yang lebih pintar &lt;strong&gt;tidak secara otomatis&lt;/strong&gt; memberikan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Determinisme saat dibutuhkan&lt;/li&gt;
&lt;li&gt;Auditability (catatan apa yang dilakukan agent)&lt;/li&gt;
&lt;li&gt;Enforcemen izin dan batasan&lt;/li&gt;
&lt;li&gt;Kontrol biaya&lt;/li&gt;
&lt;li&gt;Ketahanan terhadap serangan (prompt injection)&lt;/li&gt;
&lt;li&gt;Komposisi yang baik dengan sistem lain&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Semua hal di atas adalah tanggung jawab &lt;strong&gt;harness&lt;/strong&gt;, bukan model.&lt;/p&gt;
&lt;h2&gt;Empat Lapisan AI Software&lt;/h2&gt;
&lt;p&gt;Untuk memahami posisi harness engineering, kita perlu melihat empat lapisan:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Lapisan&lt;/th&gt;
&lt;th&gt;Penjelasan&lt;/th&gt;
&lt;th&gt;Contoh&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Model&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Neural network itu sendiri&lt;/td&gt;
&lt;td&gt;GPT-4o, Claude 4, DeepSeek&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Agent&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Loop yang menggunakan model untuk observe-plan-act&lt;/td&gt;
&lt;td&gt;ReAct agent, Coding agent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Workflow&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Komposisi beberapa agent + langkah deterministik&lt;/td&gt;
&lt;td&gt;Pipeline CI/CD otomatis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Harness&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Lapisan runtime lintas cutting yang mendukung semua lapisan di atas&lt;/td&gt;
&lt;td&gt;Sandbox, Guardrails, Observability, Evals&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Harness&lt;/strong&gt; adalah &lt;em&gt;platform&lt;/em&gt;-nya. Ia menyediakan lingkungan agar agent bisa berjalan dengan aman.&lt;/p&gt;
&lt;h2&gt;Analogi Kuda dan Harness&lt;/h2&gt;
&lt;p&gt;Analogi yang paling sering digunakan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Kuda&lt;/strong&gt; = Model (kuat, kadang brilian, tapi tidak bisa diandalkan begitu saja)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Harness&lt;/strong&gt; = Segala perlengkapan yang menghubungkan kuda dengan kereta dan pengendara&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pengendara&lt;/strong&gt; = Manusia yang memiliki tujuan dan bertanggung jawab penuh&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tanpa harness yang baik, seekor kuda yang kuat justru menjadi bahaya di tengah kota. Dengan harness yang baik, kekuatannya menjadi sangat berguna.&lt;/p&gt;
&lt;h2&gt;Di Mana AI Agents Digunakan Saat Ini?&lt;/h2&gt;
&lt;p&gt;Beberapa kategori penggunaan production AI Agents yang paling matang:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Coding Agents&lt;/strong&gt; (paling matang)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CI/CD &amp;amp; Pipeline Automation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Customer Support &amp;amp; Triage&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Security Remediation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Document-grounded Assistants&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Incident Investigation&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Setiap kategori memiliki tantangan harness yang berbeda-beda.&lt;/p&gt;
&lt;h2&gt;Kesimpulan Bagian 1&lt;/h2&gt;
&lt;p&gt;AI Harness Engineering adalah disiplin yang fokus pada &lt;strong&gt;engineering di sekitar model&lt;/strong&gt;, bukan hanya pada modelnya. Di production, harness jauh lebih penting daripada seberapa pintar model yang digunakan.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Sumber&lt;/strong&gt;: &lt;em&gt;AI Harness Engineering Interview Preparation Handbook&lt;/em&gt; (2026)&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;2. Tujuh Lapisan Harness untuk Production AI Agents&lt;/h1&gt;
&lt;p&gt;Salah satu kontribusi terpenting dari buku ini adalah &lt;strong&gt;model tujuh lapisan harness&lt;/strong&gt;. Model ini membantu engineer memahami secara sistematis apa saja yang perlu dibangun di sekitar sebuah AI Agent.&lt;/p&gt;
&lt;h2&gt;Mengapa Tujuh Lapisan?&lt;/h2&gt;
&lt;p&gt;Tujuh lapisan ini bukan sekadar teori. Ia mencerminkan lapisan-lapisan yang secara berulang muncul di berbagai production incident. Setiap lapisan memiliki tanggung jawab yang jelas dan saling bergantung.&lt;/p&gt;
&lt;h2&gt;Tujuh Lapisan Harness&lt;/h2&gt;
&lt;p&gt;Berikut adalah tujuh lapisan tersebut:&lt;/p&gt;
&lt;h3&gt;Layer 1: Instruction&lt;/h3&gt;
&lt;p&gt;System prompt, task definition, constraints, dan persona agent. Lapisan ini menentukan &amp;quot;siapa&amp;quot; agent itu dan &amp;quot;apa&amp;quot; yang boleh/tidak boleh dilakukannya.&lt;/p&gt;
&lt;h3&gt;Layer 2: Tools&lt;/h3&gt;
&lt;p&gt;Tool registry, function schemas, input validation, dan permission model. Agent hanya bisa bertindak melalui tools yang disediakan harness.&lt;/p&gt;
&lt;h3&gt;Layer 3: Memory and Retrieval&lt;/h3&gt;
&lt;p&gt;Jenis-jenis memory (scratch, episodic, semantic), retrieval pipeline, chunking, embedding, dan grounding. Lapisan ini menentukan seberapa baik agent &amp;quot;mengingat&amp;quot; dan &amp;quot;mencari informasi&amp;quot;.&lt;/p&gt;
&lt;h3&gt;Layer 4: Execution&lt;/h3&gt;
&lt;p&gt;Sandboxing, runtime environment, network control, filesystem isolation, dan credential scoping. Lapisan ini menjawab pertanyaan: &amp;quot;Seberapa aman agent ini bisa menjalankan kode atau memanggil tools?&amp;quot;&lt;/p&gt;
&lt;h3&gt;Layer 5: Policy and Approval&lt;/h3&gt;
&lt;p&gt;Guardrails, policy engine, human-in-the-loop, approval gates, dan dry-run mode. Lapisan ini mengatur &amp;quot;kapan agent boleh bertindak sendiri dan kapan harus minta persetujuan manusia&amp;quot;.&lt;/p&gt;
&lt;h3&gt;Layer 6: Observability&lt;/h3&gt;
&lt;p&gt;Tracing, logging, cost tracking, prompt/completion capture, dan anomaly detection. Tanpa observability yang baik, kita buta saat agent berjalan di production.&lt;/p&gt;
&lt;h3&gt;Layer 7: Evaluation&lt;/h3&gt;
&lt;p&gt;Golden datasets, LLM-as-judge, regression testing, trajectory evaluation, dan production monitoring. Lapisan ini menjawab: &amp;quot;Seberapa baik sebenarnya agent ini bekerja?&amp;quot;&lt;/p&gt;
&lt;h2&gt;Dependency Graph&lt;/h2&gt;
&lt;p&gt;Ketujuh lapisan ini saling bergantung. Contoh:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tools (Layer 2) membutuhkan Policy (Layer 5) sebelum dieksekusi.&lt;/li&gt;
&lt;li&gt;Observability (Layer 6) dibutuhkan untuk melakukan Evaluation (Layer 7).&lt;/li&gt;
&lt;li&gt;Memory (Layer 3) sangat bergantung pada Instruction (Layer 1) yang baik.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Lapisan Mana yang Harus Dibangun Duluan?&lt;/h2&gt;
&lt;p&gt;Urutan yang umum direkomendasikan:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Instruction + Tools&lt;/strong&gt; (paling fundamental)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Execution (Sandbox)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Policy &amp;amp; Guardrails&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Observability&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Evaluation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Memory &amp;amp; Retrieval&lt;/strong&gt; (bisa dikembangkan secara bertahap)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Kesimpulan Bagian 2&lt;/h2&gt;
&lt;p&gt;Model tujuh lapisan memberikan kerangka berpikir yang sangat berguna saat merancang AI Agent untuk production. Dengan memahami setiap lapisan dan ketergantungannya, engineer bisa membangun sistem yang lebih sistematis dan lebih mudah di-debug.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;3. Dari Prompt Engineering ke Harness Engineering&lt;/h1&gt;
&lt;p&gt;Memahami evolusi disiplin ini penting agar kita tidak terjebak pada cara berpikir lama.&lt;/p&gt;
&lt;h2&gt;Timeline Singkat&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tahun&lt;/th&gt;
&lt;th&gt;Fokus Utama&lt;/th&gt;
&lt;th&gt;Karakteristik&lt;/th&gt;
&lt;th&gt;Keterbatasan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;2022–2023&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Prompt Engineering&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Membuat prompt yang bagus&lt;/td&gt;
&lt;td&gt;Tidak scalable, tidak versionable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2024&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Agent Frameworks&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;LangChain, AutoGen, CrewAI, dll&lt;/td&gt;
&lt;td&gt;Masih tipis, banyak hal diserahkan ke developer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2025&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Convergence ke Harness&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Mulai muncul istilah harness secara luas&lt;/td&gt;
&lt;td&gt;Masih belum terstruktur&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Harness Engineering&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Menjadi disiplin tersendiri&lt;/td&gt;
&lt;td&gt;Masih berkembang&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;Mengapa Prompt Saja Tidak Cukup untuk Production?&lt;/h2&gt;
&lt;p&gt;Beberapa alasan utama:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Prompt bersifat &lt;strong&gt;artisanal&lt;/strong&gt; (sulit di-review dan di-version)&lt;/li&gt;
&lt;li&gt;Sulit &lt;strong&gt;menggeneralisasi&lt;/strong&gt; ke banyak tugas&lt;/li&gt;
&lt;li&gt;Tidak tahan terhadap &lt;strong&gt;model upgrade&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Tidak memberikan &lt;strong&gt;auditability&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Tidak menangani &lt;strong&gt;failure modes&lt;/strong&gt; secara sistematis&lt;/li&gt;
&lt;li&gt;Tidak mengatur &lt;strong&gt;cost&lt;/strong&gt; dan &lt;strong&gt;safety&lt;/strong&gt; dengan baik&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Apa yang Berubah di Harness Engineering?&lt;/h2&gt;
&lt;p&gt;Harness engineering berfokus pada &lt;strong&gt;infrastructure&lt;/strong&gt; yang membuat ribuan percakapan berjalan dengan baik, bahkan ketika:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tidak ada yang mengawasi&lt;/li&gt;
&lt;li&gt;Input bersifat adversarial&lt;/li&gt;
&lt;li&gt;Model provider mengubah bobot secara diam-diam&lt;/li&gt;
&lt;li&gt;Tim keuangan meminta penghematan biaya 5x lipat&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Seorang &lt;strong&gt;Harness Engineer&lt;/strong&gt; bukanlah &amp;quot;prompt whisperer&amp;quot;. Ia adalah orang yang membangun fondasi agar agent bisa diandalkan di skala production.&lt;/p&gt;
&lt;h2&gt;Tiga Skill yang Paling Diuji di Interview&lt;/h2&gt;
&lt;p&gt;Dari banyak interview loop di bidang ini, tiga skill berikut paling sering menjadi pembeda:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Design Judgment&lt;/strong&gt; — Kemampuan memilih arsitektur yang tepat di bawah tekanan waktu dan membela pilihannya.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Operational Instinct&lt;/strong&gt; — Kemampuan membayangkan apa yang sebenarnya terjadi saat agent berjalan di production (latency, cost, failure).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Failure Fluency&lt;/strong&gt; — Kemampuan menyebutkan cara sistem bisa rusak sebelum benar-benar rusak, serta merancang recovery path.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Kesimpulan Bagian 3&lt;/h2&gt;
&lt;p&gt;Prompt engineering adalah keterampilan penting, tetapi tidak cukup untuk production. Harness engineering adalah evolusi alami yang menjadikan AI Agents bisa diandalkan secara sistematis.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;4. Instruction Engineering untuk AI Agents&lt;/h1&gt;
&lt;p&gt;Instruction layer adalah fondasi dari segala hal. Tanpa instruction yang baik, lapisan-lapisan lain akan kesulitan mengkompensasi.&lt;/p&gt;
&lt;h2&gt;Tiga Tier Konteks Agent&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;System-level context&lt;/strong&gt; — Instruksi permanen yang mendefinisikan identitas dan batasan agent.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Task-level context&lt;/strong&gt; — Instruksi spesifik untuk tugas saat ini.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Runtime context&lt;/strong&gt; — Informasi yang dikumpulkan selama agent berjalan (tool results, retrieved documents, previous thoughts).&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Apa yang Harus Ada di System Prompt?&lt;/h2&gt;
&lt;p&gt;Beberapa elemen penting:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Role &amp;amp; Persona&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Core Objectives&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hard Constraints&lt;/strong&gt; (apa yang tidak boleh dilakukan)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Output Format&lt;/strong&gt; (structured output)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Failure Handling&lt;/strong&gt; (bagaimana agent harus bereaksi saat gagal)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Escalation Policy&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Structured Outputs&lt;/h2&gt;
&lt;p&gt;Menggunakan structured output (JSON Schema, Pydantic, dll) sangat direkomendasikan di production karena:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lebih mudah di-parse&lt;/li&gt;
&lt;li&gt;Lebih mudah divalidasi&lt;/li&gt;
&lt;li&gt;Mengurangi hallucination pada format&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Constraint Design&lt;/h2&gt;
&lt;p&gt;Salah satu praktik terbaik adalah membuat &lt;strong&gt;jalan yang aman menjadi jalan yang paling mudah&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Contoh:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Default &lt;code&gt;dry_run = true&lt;/code&gt; pada tool yang berbahaya&lt;/li&gt;
&lt;li&gt;Agent harus secara eksplisit memilih untuk melakukan aksi destruktif&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Failure-Aware Prompting&lt;/h2&gt;
&lt;p&gt;Agent yang baik tidak hanya tahu cara sukses, tetapi juga tahu cara gagal dengan baik. System prompt sebaiknya berisi instruksi tentang:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Kapan harus menyerah&lt;/li&gt;
&lt;li&gt;Kapan harus meminta bantuan manusia&lt;/li&gt;
&lt;li&gt;Bagaimana melaporkan ketidakpastian&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Prompt Versioning&lt;/h2&gt;
&lt;p&gt;Di production, prompt harus di-version control, direview, dan bisa di-roll back — sama seperti kode.&lt;/p&gt;
&lt;h2&gt;Kesimpulan Bagian 4&lt;/h2&gt;
&lt;p&gt;Instruction Engineering di konteks production jauh lebih dari sekadar menulis prompt yang bagus. Ia mencakup constraint design, structured output, versioning, dan failure handling.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;5. Tool Calling dan MCP (Model Context Protocol)&lt;/h1&gt;
&lt;p&gt;Tools adalah cara agent berinteraksi dengan dunia luar. Kualitas tool design sangat menentukan kualitas agent secara keseluruhan.&lt;/p&gt;
&lt;h2&gt;Trust Ladder untuk Tools&lt;/h2&gt;
&lt;p&gt;Tidak semua tool diciptakan sama. Ada tingkatan kepercayaan:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Read-only tools (paling aman)&lt;/li&gt;
&lt;li&gt;Write tools dengan dry-run&lt;/li&gt;
&lt;li&gt;Write tools dengan human approval&lt;/li&gt;
&lt;li&gt;Irreversible actions (paling berisiko)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Prinsip Desain Function Schema&lt;/h2&gt;
&lt;p&gt;Beberapa prinsip penting:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Nama tool harus jelas dan deskriptif (&lt;code&gt;delete_file&lt;/code&gt;, bukan &lt;code&gt;file_op&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Deskripsi harus ditulis untuk &lt;strong&gt;model&lt;/strong&gt;, bukan untuk manusia&lt;/li&gt;
&lt;li&gt;Setiap parameter harus punya deskripsi yang baik&lt;/li&gt;
&lt;li&gt;Gunakan &lt;code&gt;enum&lt;/code&gt; dan &lt;code&gt;required&lt;/code&gt; fields secara bijak&lt;/li&gt;
&lt;li&gt;Sediakan mode &lt;code&gt;dry_run&lt;/code&gt; untuk aksi berbahaya&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;MCP — Model Context Protocol&lt;/h2&gt;
&lt;p&gt;MCP adalah standar yang muncul untuk memudahkan integrasi antara agent dengan berbagai tools dan platform. Beberapa poin penting:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MCP mendefinisikan cara agent menemukan dan memanggil tools&lt;/li&gt;
&lt;li&gt;Mendukung authentication dan authorization&lt;/li&gt;
&lt;li&gt;Memungkinkan komposisi beberapa MCP server&lt;/li&gt;
&lt;li&gt;Semakin banyak platform (termasuk Harness) yang menyediakan MCP Server&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Read vs Write Separation&lt;/h2&gt;
&lt;p&gt;Salah satu praktik keamanan terbaik adalah memisahkan tool yang hanya membaca dengan tool yang bisa menulis/mengubah data.&lt;/p&gt;
&lt;h2&gt;Kesimpulan Bagian 5&lt;/h2&gt;
&lt;p&gt;Tool calling adalah salah satu lapisan paling kritis dalam harness. Desain schema yang buruk bisa menyebabkan agent melakukan hal yang tidak diinginkan atau gagal memahami cara menggunakan tool dengan benar.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;6. Memory, State, dan Retrieval untuk AI Agents&lt;/h1&gt;
&lt;p&gt;Memory dan retrieval adalah lapisan yang menentukan seberapa &amp;quot;pintar&amp;quot; agent dalam jangka panjang dan seberapa akurat ia dalam menjawab pertanyaan berbasis pengetahuan.&lt;/p&gt;
&lt;h2&gt;Tiga Jenis Memory&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Jenis Memory&lt;/th&gt;
&lt;th&gt;Fungsi&lt;/th&gt;
&lt;th&gt;Contoh Penggunaan&lt;/th&gt;
&lt;th&gt;Tantangan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Scratch Memory&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Konteks dalam satu sesi&lt;/td&gt;
&lt;td&gt;Conversation history&lt;/td&gt;
&lt;td&gt;Context window limit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Episodic Memory&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Pengalaman dari run sebelumnya&lt;/td&gt;
&lt;td&gt;Reflection, past mistakes&lt;/td&gt;
&lt;td&gt;Memory poisoning&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Semantic Memory&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Pengetahuan domain / dokumen&lt;/td&gt;
&lt;td&gt;RAG, company knowledge base&lt;/td&gt;
&lt;td&gt;Stale data, retrieval quality&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;Retrieval yang Baik&lt;/h2&gt;
&lt;p&gt;Beberapa praktik penting dalam retrieval:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Chunking&lt;/strong&gt; yang tepat sangat berpengaruh&lt;/li&gt;
&lt;li&gt;Hybrid retrieval (BM25 + Vector) sering lebih baik daripada hanya vector&lt;/li&gt;
&lt;li&gt;Reranking biasanya meningkatkan kualitas hasil&lt;/li&gt;
&lt;li&gt;Selalu sertakan &lt;strong&gt;citation/provenance&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Deteksi data yang sudah usang (stale data)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Memory Poisoning&lt;/h2&gt;
&lt;p&gt;Salah satu risiko serius adalah memory poisoning — ketika agent menyimpan informasi yang salah dan kemudian menggunakannya lagi di masa depan. Harness harus memiliki mekanisme untuk memvalidasi dan membersihkan memory.&lt;/p&gt;
&lt;h2&gt;Kesimpulan Bagian 6&lt;/h2&gt;
&lt;p&gt;Memory dan retrieval yang baik adalah salah satu pembeda utama antara agent yang hanya terlihat pintar dengan agent yang benar-benar berguna di production.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;7. Sandboxing dan Execution Environment&lt;/h1&gt;
&lt;p&gt;Ketika agent diberi kemampuan untuk menjalankan kode atau memanggil tools yang powerful, keamanan menjadi sangat penting.&lt;/p&gt;
&lt;h2&gt;Mengapa Default Docker Tidak Cukup?&lt;/h2&gt;
&lt;p&gt;Docker bagus untuk deployment, tetapi untuk agent execution, kita membutuhkan isolasi yang lebih kuat karena:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Agent bisa mencoba escape&lt;/li&gt;
&lt;li&gt;Agent bisa mencoba mengakses resource sensitif&lt;/li&gt;
&lt;li&gt;Blast radius harus seminimal mungkin&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Teknologi Sandboxing Modern&lt;/h2&gt;
&lt;p&gt;Beberapa teknologi yang sering digunakan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;gVisor&lt;/strong&gt; — User-space kernel&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Firecracker&lt;/strong&gt; — MicroVM (ringan dan cepat)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Worktree isolation&lt;/strong&gt; per task&lt;/li&gt;
&lt;li&gt;Network egress policy yang ketat&lt;/li&gt;
&lt;li&gt;Filesystem yang read-only atau terbatas&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Prinsip Utama Sandboxing&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Least privilege&lt;/li&gt;
&lt;li&gt;Fast start time&lt;/li&gt;
&lt;li&gt;Observable &amp;amp; auditable&lt;/li&gt;
&lt;li&gt;Easy to destroy setelah selesai&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Kesimpulan Bagian 7&lt;/h2&gt;
&lt;p&gt;Sandboxing adalah lapisan pertahanan terakhir. Jika agent berhasil mengeksploitasi sandbox, maka seluruh sistem bisa berada dalam bahaya. Investasi di lapisan ini sangat penting untuk agent yang memiliki akses ke tools yang powerful.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;8. Evaluasi, Observability, dan Reliability AI Agents&lt;/h1&gt;
&lt;p&gt;&amp;quot;Anda tidak bisa memperbaiki apa yang tidak bisa Anda ukur.&amp;quot;&lt;/p&gt;
&lt;h2&gt;Evaluasi Bukan QA Biasa&lt;/h2&gt;
&lt;p&gt;Di AI Agents, evaluasi adalah &lt;strong&gt;engineering discipline&lt;/strong&gt;, bukan hanya aktivitas QA. Evaluasi harus dilakukan secara terus-menerus, termasuk setelah deployment.&lt;/p&gt;
&lt;h2&gt;Komponen Evaluasi yang Penting&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Golden datasets&lt;/li&gt;
&lt;li&gt;LLM-as-judge (dengan hati-hati)&lt;/li&gt;
&lt;li&gt;Trajectory evaluation&lt;/li&gt;
&lt;li&gt;Regression testing di CI/CD&lt;/li&gt;
&lt;li&gt;Statistical rigor&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Observability untuk AI Agents&lt;/h2&gt;
&lt;p&gt;Observability tradisional tidak cukup. Kita membutuhkan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Trace setiap langkah agent (bukan hanya request-response)&lt;/li&gt;
&lt;li&gt;Capture prompt dan completion&lt;/li&gt;
&lt;li&gt;Cost tracking per run&lt;/li&gt;
&lt;li&gt;Anomaly detection pada trace&lt;/li&gt;
&lt;li&gt;Feedback signal integration&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Failure Modes yang Sering Terjadi&lt;/h2&gt;
&lt;p&gt;Beberapa failure mode umum:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Infinite loops&lt;/li&gt;
&lt;li&gt;Partially-applied state&lt;/li&gt;
&lt;li&gt;Silent failures&lt;/li&gt;
&lt;li&gt;Cost explosion&lt;/li&gt;
&lt;li&gt;Context poisoning&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Kesimpulan Bagian 8&lt;/h2&gt;
&lt;p&gt;Tanpa observability dan evaluasi yang baik, agent yang terlihat berfungsi di development bisa gagal total di production. Lapisan ini adalah salah satu yang paling sering diremehkan.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;9. Guardrails, Safety, dan Governance&lt;/h1&gt;
&lt;p&gt;Ini adalah lapisan yang menentukan apakah agent bisa dipercaya untuk dijalankan di lingkungan enterprise atau production yang sensitif.&lt;/p&gt;
&lt;h2&gt;Jenis Guardrails&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Input Guardrails&lt;/strong&gt; — Memeriksa input sebelum masuk ke model&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inline Guardrails&lt;/strong&gt; — Memeriksa selama proses berjalan&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Output Guardrails&lt;/strong&gt; — Memeriksa output sebelum dikembalikan ke user&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Ancaman Utama&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Prompt Injection (ancaman paling serius)&lt;/li&gt;
&lt;li&gt;Data leakage / PII exposure&lt;/li&gt;
&lt;li&gt;Unauthorized actions&lt;/li&gt;
&lt;li&gt;Model misuse&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Governance di Enterprise&lt;/h2&gt;
&lt;p&gt;Beberapa aspek penting:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;RBAC dan delegated permissions&lt;/li&gt;
&lt;li&gt;Audit trail yang lengkap&lt;/li&gt;
&lt;li&gt;Approval workflows&lt;/li&gt;
&lt;li&gt;Data residency &amp;amp; egress control&lt;/li&gt;
&lt;li&gt;Incident response integration&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Kesimpulan Bagian 9&lt;/h2&gt;
&lt;p&gt;Guardrails dan governance bukan penghalang inovasi, melainkan fondasi agar AI Agents bisa digunakan secara bertanggung jawab di skala production.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Penutup &amp;amp; Ringkasan&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;AI Harness Engineering&lt;/strong&gt; adalah disiplin yang sedang berkembang pesat di tahun 2026. Fokus utamanya adalah membangun lapisan engineering di sekitar model AI agar bisa diandalkan dalam skala production.&lt;/p&gt;
&lt;h3&gt;Ringkasan 9 Topik Utama:&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;No&lt;/th&gt;
&lt;th&gt;Topik&lt;/th&gt;
&lt;th&gt;Fokus Utama&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Pengantar Harness Engineering&lt;/td&gt;
&lt;td&gt;Agent = Model + Harness&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Tujuh Lapisan Harness&lt;/td&gt;
&lt;td&gt;Instruction → Evaluation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Evolusi Disiplin&lt;/td&gt;
&lt;td&gt;Prompt → Agent → Harness&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Instruction Engineering&lt;/td&gt;
&lt;td&gt;Prompt, constraint, structured output&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Tool Calling &amp;amp; MCP&lt;/td&gt;
&lt;td&gt;Schema design, protocol integrasi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Memory &amp;amp; Retrieval&lt;/td&gt;
&lt;td&gt;Scratch, episodic, semantic memory + RAG&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;Sandboxing&lt;/td&gt;
&lt;td&gt;Isolasi eksekusi yang aman&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Evaluasi &amp;amp; Observability&lt;/td&gt;
&lt;td&gt;Evals, tracing, reliability&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;Guardrails &amp;amp; Governance&lt;/td&gt;
&lt;td&gt;Safety, policy, enterprise readiness&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Pesan Akhir:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Model akan terus berkembang dan menjadi lebih pintar.&lt;br&gt;Tetapi prinsip-prinsip &lt;strong&gt;Harness Engineering&lt;/strong&gt; — bagaimana membungkus model agar aman, dapat diaudit, dan bisa diandalkan — akan tetap relevan dalam waktu yang lama.&lt;/p&gt;
&lt;p&gt;Structure in. Structure out.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Sumber Utama&lt;/strong&gt;:&lt;br&gt;&lt;em&gt;AI Harness Engineering Interview Preparation Handbook&lt;/em&gt; — 2026 Edition oleh AI Engineering Insider&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Akhir dari Ebook&lt;/strong&gt;&lt;/p&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://ngopidulur.my.id/blog/ai-harness-engineering-panduan-lengkap-membangun-production-ai-agents/&quot;&gt;https://ngopidulur.my.id/blog/ai-harness-engineering-panduan-lengkap-membangun-production-ai-agents/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>Ngopidulur</dc:creator><pubDate>Fri, 22 May 2026 15:33:00 GMT</pubDate></item><item><title>AI untuk Data Science: Panduan Lengkap dari Dasar hingga Praktik Bisnis</title><link>https://ngopidulur.my.id/blog/ai-untuk-data-science-panduan-lengkap-dari-dasar-hingga-praktik-bisnis/</link><guid isPermaLink="true">https://ngopidulur.my.id/blog/ai-untuk-data-science-panduan-lengkap-dari-dasar-hingga-praktik-bisnis/</guid><description>Panduan lengkap dalam Bahasa Indonesia yang merangkum penerapan Artificial Intelligence dalam dunia data science. Mulai dari konsep dasar AI, deep learning frameworks (TensorFlow, Keras, MXNet), algoritma optimisasi, CNN, RNN, Transfer Learning, GANs, hingga aspek bisnis dalam proyek AI. Berdasarkan buku AI for Data Science karya Zacharias Voulgaris &amp; Yunus Emrah Bulut.</description><content:encoded>&lt;p&gt;&lt;strong&gt;Berdasarkan buku:&lt;/strong&gt; &lt;em&gt;AI for Data Science&lt;/em&gt; oleh Zacharias Voulgaris, PhD &amp;amp; Yunus Emrah Bulut&lt;br&gt;&lt;strong&gt;Disusun ulang dalam Bahasa Indonesia&lt;/strong&gt;&lt;br&gt;&lt;strong&gt;Versi:&lt;/strong&gt; Mei 2026&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Daftar Isi&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;#bagian-1-apa-itu-ai-dan-mengapa-penting-untuk-data-scientist&quot;&gt;Bagian 1: Apa Itu AI dan Mengapa Penting untuk Data Scientist?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bagian-2-mengenal-deep-learning-frameworks&quot;&gt;Bagian 2: Mengenal Deep Learning Frameworks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bagian-3-membangun-neural-network-dengan-mxnet&quot;&gt;Bagian 3: Membangun Neural Network dengan MXNet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bagian-4-tensorflow--keras&quot;&gt;Bagian 4: TensorFlow &amp;amp; Keras&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bagian-5-optimization-algorithms-pso-genetic-algorithm-simulated-annealing&quot;&gt;Bagian 5: Optimization Algorithms (PSO, Genetic Algorithm, Simulated Annealing)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bagian-6-cnn-rnn-dan-optimization-ensemble&quot;&gt;Bagian 6: CNN, RNN, dan Optimization Ensemble&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bagian-7-alternative-ai-frameworks-elm-capsnet-fuzzy-logic&quot;&gt;Bagian 7: Alternative AI Frameworks (ELM, CapsNet, Fuzzy Logic)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bagian-8-transfer-learning-reinforcement-learning-autoencoder--gans&quot;&gt;Bagian 8: Transfer Learning, Reinforcement Learning, Autoencoder &amp;amp; GANs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#bagian-9-aspek-bisnis-penerapan-ai-dalam-proyek-data-science&quot;&gt;Bagian 9: Aspek Bisnis Penerapan AI dalam Proyek Data Science&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#penutup--ringkasan-seri&quot;&gt;Penutup &amp;amp; Ringkasan Seri&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h1&gt;Bagian 1: Apa Itu AI dan Mengapa Penting untuk Data Scientist?&lt;/h1&gt;
&lt;p&gt;Buku &lt;strong&gt;&amp;quot;AI for Data Science&amp;quot;&lt;/strong&gt; karya Zacharias Voulgaris, PhD dan Yunus Emrah Bulut adalah salah satu buku paling komprehensif yang membahas penerapan Artificial Intelligence dalam dunia data science secara praktis.&lt;/p&gt;
&lt;p&gt;Dalam seri artikel ini, saya akan merangkum dan membahas isi buku tersebut dalam bahasa Indonesia, agar lebih mudah dipahami oleh developer, data scientist, dan praktisi teknologi di Indonesia.&lt;/p&gt;
&lt;h2&gt;Apa Itu AI Sebenarnya?&lt;/h2&gt;
&lt;p&gt;Banyak orang masih menganggap AI seperti yang ada di film sci-fi — robot cerdas yang bisa mengambil alih dunia. Padahal, &lt;strong&gt;AI modern&lt;/strong&gt; jauh lebih sederhana dan fungsional.&lt;/p&gt;
&lt;p&gt;Menurut buku ini, AI adalah &lt;strong&gt;kumpulan algoritma&lt;/strong&gt; yang menggunakan data untuk membuat keputusan dan menyelesaikan tugas, mirip seperti manusia. Namun, AI saat ini masih bersifat &lt;strong&gt;narrow AI&lt;/strong&gt; (kecerdasan sempit). Artinya:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AI sangat bagus dalam satu atau beberapa tugas tertentu.&lt;/li&gt;
&lt;li&gt;AI masih lemah jika diberi tugas di luar spesialisasinya.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Contoh:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AI bisa sangat akurat dalam mengenali wajah atau merekomendasikan lagu di Spotify.&lt;/li&gt;
&lt;li&gt;Tapi AI yang sama belum tentu bisa membedakan musik klasik dan pop dengan baik.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Mengapa AI Penting untuk Data Science?&lt;/h2&gt;
&lt;p&gt;Data science sudah ada jauh sebelum AI populer. Namun, dengan munculnya AI, performa model data science bisa meningkat secara signifikan, terutama di industri yang sangat kompetitif.&lt;/p&gt;
&lt;p&gt;Beberapa alasan mengapa AI semakin penting dalam data science:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Performa lebih baik&lt;/strong&gt;: Banyak algoritma AI (seperti Deep Learning) mampu menangkap pola yang lebih kompleks dibanding metode tradisional.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data yang melimpah&lt;/strong&gt;: Banyak perusahaan sudah memiliki data dalam jumlah besar (AI-ready data).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Komputasi yang lebih murah&lt;/strong&gt;: GPU dan cloud computing membuat training model AI menjadi lebih terjangkau.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Framework yang matang&lt;/strong&gt;: Library seperti TensorFlow, Keras, PyTorch, dan MXNet membuat AI lebih mudah diakses.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Singkatnya: Data science bisa dilakukan tanpa AI, tetapi di banyak kasus, &lt;strong&gt;mengabaikan AI berarti kehilangan keunggulan kompetitif&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Narrow AI vs Artificial General Intelligence (AGI)&lt;/h2&gt;
&lt;p&gt;Saat ini kita hanya memiliki &lt;strong&gt;Narrow AI&lt;/strong&gt;. AI ini dirancang untuk tugas spesifik.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Artificial General Intelligence (AGI)&lt;/strong&gt; — AI yang bisa melakukan hampir semua tugas intelektual seperti manusia — masih jauh dari kenyataan. Buku ini menekankan bahwa sebagai praktisi, kita harus fokus pada apa yang bisa dilakukan AI saat ini, bukan pada fantasi masa depan.&lt;/p&gt;
&lt;h2&gt;Kesimpulan Bagian 1&lt;/h2&gt;
&lt;p&gt;AI bukan ancaman, melainkan &lt;strong&gt;alat&lt;/strong&gt; yang sangat powerful untuk memperkuat kemampuan data science. Dengan framework modern dan sumber daya komputasi yang semakin terjangkau, sekarang adalah waktu yang tepat untuk mulai mempelajari dan menerapkan AI dalam proyek data science.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Sumber&lt;/strong&gt;: Buku &lt;em&gt;AI for Data Science&lt;/em&gt; oleh Zacharias Voulgaris, PhD &amp;amp; Yunus Emrah Bulut (Technics Publications, 2018)&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Bagian 2: Mengenal Deep Learning Frameworks&lt;/h1&gt;
&lt;p&gt;Di &lt;strong&gt;Bagian 1&lt;/strong&gt;, kita sudah membahas apa itu AI secara realistis dan mengapa AI semakin penting dalam dunia data science. Sekarang kita masuk ke salah satu topik paling penting: &lt;strong&gt;Deep Learning Frameworks&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Apa Itu Deep Learning Framework?&lt;/h2&gt;
&lt;p&gt;Deep Learning Framework adalah &lt;strong&gt;perpustakaan (library) atau platform&lt;/strong&gt; yang menyediakan tools, fungsi, dan infrastruktur untuk membangun, melatih, dan menjalankan model deep learning dengan lebih mudah dan efisien.&lt;/p&gt;
&lt;p&gt;Tanpa framework, kita harus menulis hampir semua komponen dari nol (seperti neural network layer, backpropagation, optimisasi, dll). Framework membuat proses ini jauh lebih cepat dan lebih aman dari error.&lt;/p&gt;
&lt;h2&gt;Bagaimana Deep Learning System Bekerja?&lt;/h2&gt;
&lt;p&gt;Secara sederhana, deep learning system terdiri dari beberapa komponen utama:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Data&lt;/strong&gt; — Input yang digunakan untuk melatih model (gambar, teks, angka, dll).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Model/Neural Network&lt;/strong&gt; — Struktur yang terdiri dari banyak layer neuron.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Loss Function&lt;/strong&gt; — Fungsi yang mengukur seberapa baik model dalam memprediksi.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optimizer&lt;/strong&gt; — Algoritma yang menyesuaikan bobot (weight) model agar loss semakin kecil.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Training Loop&lt;/strong&gt; — Proses iteratif di mana model belajar dari data.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Framework deep learning menyediakan semua komponen ini dalam bentuk yang mudah digunakan.&lt;/p&gt;
&lt;h2&gt;Deep Learning Frameworks Populer Saat Ini&lt;/h2&gt;
&lt;p&gt;Berikut adalah beberapa framework deep learning utama yang dibahas dalam buku &lt;em&gt;AI for Data Science&lt;/em&gt;:&lt;/p&gt;
&lt;div style=&quot;overflow-x: auto; -webkit-overflow-scrolling: touch;&quot;&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Framework&lt;/th&gt;
&lt;th&gt;Bahasa Utama&lt;/th&gt;
&lt;th&gt;Kelebihan&lt;/th&gt;
&lt;th&gt;Kekurangan&lt;/th&gt;
&lt;th&gt;Cocok Untuk&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TensorFlow&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;Sangat matang, produksi-ready, TensorBoard&lt;/td&gt;
&lt;td&gt;Kurva belajar cukup curam&lt;/td&gt;
&lt;td&gt;Production &amp;amp; Research&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Keras&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;Sangat user-friendly, cepat untuk prototyping&lt;/td&gt;
&lt;td&gt;Kurang fleksibel untuk custom model&lt;/td&gt;
&lt;td&gt;Pemula &amp;amp; Rapid Prototyping&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MXNet&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Python, Scala, R&lt;/td&gt;
&lt;td&gt;Ringan, cepat, mendukung banyak bahasa&lt;/td&gt;
&lt;td&gt;Komunitas lebih kecil&lt;/td&gt;
&lt;td&gt;Deployment &amp;amp; Edge Devices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PyTorch&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;Sangat fleksibel (dynamic graph), populer di research&lt;/td&gt;
&lt;td&gt;Deployment agak lebih rumit&lt;/td&gt;
&lt;td&gt;Research &amp;amp; Experimentation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CNTK&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Python, C++&lt;/td&gt;
&lt;td&gt;Performa baik&lt;/td&gt;
&lt;td&gt;Sudah kurang aktif dikembangkan&lt;/td&gt;
&lt;td&gt;Kasus tertentu&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Catatan&lt;/strong&gt;: Buku ini diterbitkan tahun 2018, sehingga saat itu MXNet, TensorFlow, dan Keras masih sangat dominan. Saat ini (2026), &lt;strong&gt;PyTorch&lt;/strong&gt; sudah jauh lebih populer di kalangan researcher, sementara &lt;strong&gt;TensorFlow&lt;/strong&gt; dan &lt;strong&gt;JAX&lt;/strong&gt; lebih kuat di sisi production.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Bahasa Pemrograman untuk Deep Learning&lt;/h2&gt;
&lt;p&gt;Meskipun Python adalah bahasa paling dominan, beberapa framework juga mendukung bahasa lain:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Python&lt;/strong&gt; → Paling populer dan memiliki ekosistem terlengkap&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Julia&lt;/strong&gt; → Performa tinggi, cocok untuk komputasi ilmiah&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scala&lt;/strong&gt; → Sering digunakan bersama Spark&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;R&lt;/strong&gt; → Masih digunakan di beberapa kalangan statistik&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;C++&lt;/strong&gt; → Untuk performa maksimal dan deployment&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Cara Memilih Deep Learning Framework&lt;/h2&gt;
&lt;p&gt;Menurut buku ini, ada beberapa faktor yang perlu dipertimbangkan saat memilih framework:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Kemudahan Penggunaan&lt;/strong&gt; — Seberapa cepat kamu bisa membuat model pertama?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Performa&lt;/strong&gt; — Seberapa cepat training dan inference-nya?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fleksibilitas&lt;/strong&gt; — Seberapa mudah membuat arsitektur custom?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deployment&lt;/strong&gt; — Seberapa mudah model dideploy ke production?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Komunitas &amp;amp; Dokumentasi&lt;/strong&gt; — Seberapa besar dukungan komunitas?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Integrasi&lt;/strong&gt; — Seberapa baik terintegrasi dengan tools lain yang kamu pakai?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Rekomendasi praktis saat ini (2026):&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pemula / Prototyping cepat&lt;/strong&gt; → Mulai dengan &lt;strong&gt;Keras&lt;/strong&gt; (atau PyTorch Lightning)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Research &amp;amp; Eksperimen&lt;/strong&gt; → &lt;strong&gt;PyTorch&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Production &amp;amp; Scalability&lt;/strong&gt; → &lt;strong&gt;TensorFlow&lt;/strong&gt; atau &lt;strong&gt;JAX&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deployment ke perangkat kecil/edge&lt;/strong&gt; → &lt;strong&gt;MXNet&lt;/strong&gt; atau &lt;strong&gt;ONNX&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Deep Learning Methodologies &amp;amp; Applications&lt;/h2&gt;
&lt;p&gt;Deep learning tidak hanya tentang neural network biasa. Beberapa metodologi penting yang dibahas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Feedforward Neural Networks (MLP)&lt;/strong&gt; — Untuk data tabular&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Convolutional Neural Networks (CNN)&lt;/strong&gt; — Untuk data gambar &amp;amp; spasial&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Recurrent Neural Networks (RNN) &amp;amp; LSTM&lt;/strong&gt; — Untuk data sekuensial (teks, time series)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Autoencoders&lt;/strong&gt; — Untuk dimensionality reduction &amp;amp; anomaly detection&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Generative Adversarial Networks (GANs)&lt;/strong&gt; — Untuk generate data baru&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Kesimpulan Bagian 2&lt;/h2&gt;
&lt;p&gt;Deep learning framework adalah &lt;strong&gt;senjata utama&lt;/strong&gt; bagi data scientist modern. Memahami karakteristik masing-masing framework akan membantu kamu memilih tools yang tepat sesuai kebutuhan proyek.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Bagian 3: Membangun Neural Network dengan MXNet&lt;/h1&gt;
&lt;p&gt;Di &lt;strong&gt;Bagian 2&lt;/strong&gt;, kita sudah membahas berbagai deep learning framework. Sekarang kita akan mulai &lt;strong&gt;hands-on&lt;/strong&gt; dengan salah satu framework yang dibahas cukup detail di buku, yaitu &lt;strong&gt;Apache MXNet&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Mengapa MXNet?&lt;/h2&gt;
&lt;p&gt;MXNet dipilih karena beberapa kelebihan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ringan dan cepat&lt;/li&gt;
&lt;li&gt;Mendukung banyak bahasa pemrograman&lt;/li&gt;
&lt;li&gt;Memiliki &lt;strong&gt;Gluon&lt;/strong&gt; — interface yang lebih mudah digunakan&lt;/li&gt;
&lt;li&gt;Cocok untuk deployment ke berbagai platform (termasuk perangkat edge)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Meskipun saat ini PyTorch dan TensorFlow lebih populer, memahami MXNet tetap bermanfaat karena konsep dasarnya mirip dengan framework lain.&lt;/p&gt;
&lt;h2&gt;Komponen Utama MXNet&lt;/h2&gt;
&lt;h3&gt;1. Gluon Interface&lt;/h3&gt;
&lt;p&gt;Gluon adalah &lt;strong&gt;high-level API&lt;/strong&gt; di MXNet yang membuat pembuatan neural network menjadi jauh lebih mudah. Kamu bisa menginstallnya dengan:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;pip install mxnet --pre --user
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Kelebihan Gluon:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lebih sederhana dibandingkan low-level API&lt;/li&gt;
&lt;li&gt;Mendukung &lt;strong&gt;dynamic graph&lt;/strong&gt; (lebih fleksibel)&lt;/li&gt;
&lt;li&gt;Performa tetap tinggi&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. NDArray&lt;/h3&gt;
&lt;p&gt;NDArray adalah struktur data utama di MXNet, mirip dengan NumPy array, tapi dengan kelebihan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Mendukung komputasi asinkron di CPU/GPU&lt;/li&gt;
&lt;li&gt;Bisa digunakan di distributed computing&lt;/li&gt;
&lt;li&gt;Mendukung automatic differentiation&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Contoh penggunaan NDArray:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from mxnet import nd
import mxnet as mx

# Membuat array kosong
x = nd.empty((4, 5))

# Membuat array berisi nol
x = nd.zeros((4, 5))

# Mengecek shape dan size
print(x.shape)
print(x.size)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Kamu juga bisa menentukan &lt;strong&gt;context&lt;/strong&gt; (CPU atau GPU):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# Data di CPU
data_ctx = mx.cpu()

# Model di GPU pertama
model_ctx = mx.gpu(0)
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Membangun MLP (Multi-Layer Perceptron) dengan MXNet&lt;/h2&gt;
&lt;p&gt;Berikut adalah langkah-langkah membangun neural network sederhana untuk &lt;strong&gt;klasifikasi&lt;/strong&gt; menggunakan MXNet + Gluon.&lt;/p&gt;
&lt;h3&gt;Langkah 1: Persiapan Data&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import mxnet as mx
from mxnet import gluon, nd
import numpy as np

# Parameter
BatchSize = 64
DataCtx = mx.cpu()
ModelCtx = mx.cpu()   # ganti ke mx.gpu(0) jika pakai GPU

# Load data (contoh menggunakan data sintetis)
with open(&amp;quot;../data/data1.csv&amp;quot;) as f:
    data_raw = f.read()

lines = data_raw.splitlines()
ndp = len(lines)

X = nd.zeros((ndp, 3), ctx=DataCtx)
Y = nd.zeros((ndp, 1), ctx=DataCtx)

for i, line in enumerate(lines):
    tokens = line.split()
    Y[i] = int(tokens[0])
    for token in tokens[1:]:
        index = int(token[:-2]) - 1
        X[i, index] = 1
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Langkah 2: Membagi Data Train &amp;amp; Test&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;r = 0.8
n = int(np.round(ndp * r))

train_data = gluon.data.DataLoader(
    gluon.data.ArrayDataset(X[:n], Y[:n]),
    batch_size=BatchSize, shuffle=True
)

test_data = gluon.data.DataLoader(
    gluon.data.ArrayDataset(X[n:], Y[n:]),
    batch_size=BatchSize, shuffle=False
)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Langkah 3: Membangun Model&lt;/h3&gt;
&lt;p&gt;Kita akan membuat MLP sederhana dengan 2 hidden layer:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from mxnet.gluon import nn

net = nn.Sequential()
net.add(nn.Dense(256, activation=&amp;#39;relu&amp;#39;))   # Hidden layer 1
net.add(nn.Dense(256, activation=&amp;#39;relu&amp;#39;))   # Hidden layer 2
net.add(nn.Dense(3))                        # Output layer (3 kelas)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Langkah 4: Inisialisasi Parameter&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;net.initialize(mx.init.Normal(sigma=0.01), ctx=ModelCtx)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Langkah 5: Mendefinisikan Loss Function &amp;amp; Optimizer&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;softmax_cross_entropy = gluon.loss.SoftmaxCrossEntropyLoss()
trainer = gluon.Trainer(net.collect_params(), &amp;#39;sgd&amp;#39;, {&amp;#39;learning_rate&amp;#39;: 0.001})
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Langkah 6: Training Loop&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;epochs = 10

for epoch in range(epochs):
    cumulative_loss = 0
    for i, (data, label) in enumerate(train_data):
        data = data.as_in_context(ModelCtx)
        label = label.as_in_context(ModelCtx)
        
        with mx.autograd.record():
            output = net(data)
            loss = softmax_cross_entropy(output, label)
        loss.backward()
        trainer.step(BatchSize)
        
        cumulative_loss += nd.sum(loss).asscalar()
    
    print(f&amp;quot;Epoch {epoch}. Loss: {cumulative_loss/ndp}&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Langkah 7: Evaluasi Model&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def evaluate_accuracy(data_iterator, net):
    numerator = 0.
    denominator = 0.
    for i, (data, label) in enumerate(data_iterator):
        data = data.as_in_context(ModelCtx)
        label = label.as_in_context(ModelCtx)
        output = net(data)
        predictions = nd.argmax(output, axis=1)
        numerator += nd.sum(predictions == label)
        denominator += data.shape[0]
    return (numerator / denominator).asscalar()

print(&amp;quot;Train Accuracy:&amp;quot;, evaluate_accuracy(train_data, net))
print(&amp;quot;Test Accuracy:&amp;quot;, evaluate_accuracy(test_data, net))
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Tips dari Buku&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Gunakan &lt;strong&gt;NDArray&lt;/strong&gt; untuk data yang membutuhkan komputasi berat.&lt;/li&gt;
&lt;li&gt;Manfaatkan &lt;strong&gt;Gluon&lt;/strong&gt; untuk mempercepat development.&lt;/li&gt;
&lt;li&gt;Selalu pisahkan &lt;strong&gt;context&lt;/strong&gt; antara data dan model jika menggunakan GPU.&lt;/li&gt;
&lt;li&gt;Simpan model setelah training menggunakan &lt;code&gt;net.save_parameters(&amp;quot;model.params&amp;quot;)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Kesimpulan Bagian 3&lt;/h2&gt;
&lt;p&gt;MXNet dengan Gluon memberikan keseimbangan yang baik antara &lt;strong&gt;kemudahan penggunaan&lt;/strong&gt; dan &lt;strong&gt;performa&lt;/strong&gt;. Meskipun tidak sepopuler PyTorch atau TensorFlow saat ini, konsep yang dipelajari di MXNet sangat transferable ke framework lain.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Bagian 4: TensorFlow &amp;amp; Keras&lt;/h1&gt;
&lt;p&gt;Di &lt;strong&gt;Bagian 3&lt;/strong&gt;, kita sudah praktik membangun neural network menggunakan &lt;strong&gt;MXNet + Gluon&lt;/strong&gt;. Sekarang kita beralih ke dua framework yang sangat populer: &lt;strong&gt;TensorFlow&lt;/strong&gt; dan &lt;strong&gt;Keras&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;TensorFlow: Framework Paling Matang untuk Production&lt;/h2&gt;
&lt;p&gt;TensorFlow dikembangkan oleh Google dan saat ini menjadi salah satu framework deep learning paling powerful, terutama untuk kebutuhan &lt;strong&gt;production&lt;/strong&gt; dan &lt;strong&gt;scalability&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;Arsitektur TensorFlow&lt;/h3&gt;
&lt;p&gt;TensorFlow bekerja berdasarkan &lt;strong&gt;computational graph&lt;/strong&gt;. Artinya:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Kamu mendefinisikan graph terlebih dahulu (operasi dan variabel)&lt;/li&gt;
&lt;li&gt;Kemudian menjalankan graph tersebut dalam session&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Meskipun di versi terbaru (TensorFlow 2.x) sudah lebih eager execution (mirip PyTorch), pemahaman tentang graph tetap penting.&lt;/p&gt;
&lt;h3&gt;Core Components TensorFlow&lt;/h3&gt;
&lt;p&gt;Beberapa komponen utama:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tensor&lt;/strong&gt; — Struktur data dasar (mirip array multi-dimensi)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Variable&lt;/strong&gt; — Variabel yang bisa diubah selama training (biasanya bobot model)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Placeholder&lt;/strong&gt; (di TF 1.x) / &lt;code&gt;tf.data&lt;/code&gt; (di TF 2.x) — Untuk memasukkan data&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Session&lt;/strong&gt; (di TF 1.x) — Untuk menjalankan graph&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;tf.function&lt;/strong&gt; (di TF 2.x) — Untuk mengubah Python function menjadi graph&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;TensorFlow in Action (Contoh Sederhana)&lt;/h3&gt;
&lt;p&gt;Berikut contoh membuat model sederhana di TensorFlow 2.x:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import tensorflow as tf
from tensorflow.keras import layers, models

# Membuat model Sequential
model = models.Sequential([
    layers.Dense(256, activation=&amp;#39;relu&amp;#39;, input_shape=(3,)),
    layers.Dense(256, activation=&amp;#39;relu&amp;#39;),
    layers.Dense(3, activation=&amp;#39;softmax&amp;#39;)
])

# Compile model
model.compile(optimizer=&amp;#39;adam&amp;#39;,
              loss=&amp;#39;sparse_categorical_crossentropy&amp;#39;,
              metrics=[&amp;#39;accuracy&amp;#39;])

# Training
model.fit(train_data, train_labels, epochs=10, batch_size=64)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;TensorBoard: Visualisasi Training&lt;/h3&gt;
&lt;p&gt;Salah satu keunggulan besar TensorFlow adalah &lt;strong&gt;TensorBoard&lt;/strong&gt; — tools visualisasi yang sangat powerful.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import tensorflow as tf

# Callback TensorBoard
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=&amp;quot;./logs&amp;quot;)

model.fit(train_data, train_labels, 
          epochs=10, 
          callbacks=[tensorboard_callback])
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Kamu bisa melihat:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Grafik loss dan akurasi&lt;/li&gt;
&lt;li&gt;Arsitektur model&lt;/li&gt;
&lt;li&gt;Distribusi bobot&lt;/li&gt;
&lt;li&gt;Profiling performa&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;High-Level API: Estimators&lt;/h3&gt;
&lt;p&gt;TensorFlow juga menyediakan &lt;strong&gt;Estimators&lt;/strong&gt; — high-level API yang lebih abstrak dan cocok untuk production.&lt;/p&gt;
&lt;p&gt;Kelebihan Estimators:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Lebih mudah untuk scaling&lt;/li&gt;
&lt;li&gt;Built-in support untuk distributed training&lt;/li&gt;
&lt;li&gt;Lebih aman untuk production&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Keras: Deep Learning yang User-Friendly&lt;/h2&gt;
&lt;p&gt;Keras awalnya adalah library terpisah, tapi sekarang sudah terintegrasi penuh ke dalam TensorFlow sebagai &lt;code&gt;tf.keras&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Mengapa Keras Sangat Populer?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sangat mudah dipelajari&lt;/strong&gt; — Cocok untuk pemula&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cepat untuk prototyping&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dokumentasi sangat baik&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bisa berjalan di atas TensorFlow, Theano, atau CNTK&lt;/strong&gt; (dulu)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Membangun Model dengan Keras&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense

model = Sequential()
model.add(Dense(256, activation=&amp;#39;relu&amp;#39;, input_dim=3))
model.add(Dense(256, activation=&amp;#39;relu&amp;#39;))
model.add(Dense(3, activation=&amp;#39;softmax&amp;#39;))

model.compile(optimizer=&amp;#39;adam&amp;#39;,
              loss=&amp;#39;categorical_crossentropy&amp;#39;,
              metrics=[&amp;#39;accuracy&amp;#39;])
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Model Summary &amp;amp; Visualization&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;model.summary()                    # Melihat ringkasan model

from tensorflow.keras.utils import plot_model
plot_model(model, to_file=&amp;#39;model.png&amp;#39;, show_shapes=True)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Mengubah Keras Model ke TensorFlow Estimators&lt;/h3&gt;
&lt;p&gt;Salah satu fitur menarik adalah kemampuan mengubah model Keras menjadi Estimator:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;import tensorflow as tf

estimator = tf.keras.estimator.model_to_estimator(
    keras_model=model,
    model_dir=&amp;quot;./estimator_model&amp;quot;
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ini sangat berguna jika kamu ingin memanfaatkan kelebihan Estimator untuk production.&lt;/p&gt;
&lt;h2&gt;Perbandingan TensorFlow vs Keras&lt;/h2&gt;
&lt;div style=&quot;overflow-x: auto; -webkit-overflow-scrolling: touch;&quot;&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspek&lt;/th&gt;
&lt;th&gt;TensorFlow&lt;/th&gt;
&lt;th&gt;Keras&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Tingkat Kesulitan&lt;/td&gt;
&lt;td&gt;Sedang - Tinggi&lt;/td&gt;
&lt;td&gt;Sangat Mudah&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fleksibilitas&lt;/td&gt;
&lt;td&gt;Sangat Tinggi&lt;/td&gt;
&lt;td&gt;Sedang&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kecepatan Prototyping&lt;/td&gt;
&lt;td&gt;Sedang&lt;/td&gt;
&lt;td&gt;Sangat Cepat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cocok untuk Production&lt;/td&gt;
&lt;td&gt;Sangat Baik&lt;/td&gt;
&lt;td&gt;Baik (terutama lewat TF)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Visualisasi&lt;/td&gt;
&lt;td&gt;TensorBoard (sangat kuat)&lt;/td&gt;
&lt;td&gt;Terbatas&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rekomendasi Saat Ini&lt;/td&gt;
&lt;td&gt;Production &amp;amp; Large-scale projects&lt;/td&gt;
&lt;td&gt;Pemula, Research, Rapid Prototyping&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;h2&gt;Kesimpulan Bagian 4&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;TensorFlow&lt;/strong&gt; adalah pilihan yang kuat untuk proyek yang sudah masuk tahap production dan membutuhkan skalabilitas tinggi.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keras&lt;/strong&gt; adalah pilihan terbaik untuk pemula dan untuk prototyping cepat.&lt;/li&gt;
&lt;li&gt;Saat ini, hampir semua orang menggunakan &lt;strong&gt;tf.keras&lt;/strong&gt; (Keras yang terintegrasi dengan TensorFlow).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Bagian 5: Optimization Algorithms (PSO, Genetic Algorithm, Simulated Annealing)&lt;/h1&gt;
&lt;p&gt;Di bagian sebelumnya kita banyak membahas &lt;strong&gt;Deep Learning Frameworks&lt;/strong&gt;. Sekarang kita akan membahas topik yang sangat penting tapi sering kurang mendapat perhatian: &lt;strong&gt;Optimization Algorithms&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Mengapa Optimization Penting dalam Data Science?&lt;/h2&gt;
&lt;p&gt;Dalam machine learning dan deep learning, kita selalu berusaha menemukan parameter terbaik untuk model kita. Proses ini disebut &lt;strong&gt;optimization&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Tujuan utama optimization adalah:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Meminimalkan &lt;strong&gt;loss function&lt;/strong&gt; (error)&lt;/li&gt;
&lt;li&gt;Memaksimalkan performa model&lt;/li&gt;
&lt;li&gt;Menemukan solusi terbaik dalam ruang parameter yang sangat besar&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Algoritma optimisasi klasik seperti &lt;strong&gt;Gradient Descent&lt;/strong&gt; sangat populer, tapi ada algoritma lain yang lebih powerful untuk kasus tertentu, terutama ketika:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fungsi loss sangat kompleks dan non-konveks&lt;/li&gt;
&lt;li&gt;Terdapat banyak local minima&lt;/li&gt;
&lt;li&gt;Butuh eksplorasi global yang lebih baik&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tiga algoritma yang akan kita bahas di sini adalah:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Particle Swarm Optimization (PSO)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Genetic Algorithm (GA)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simulated Annealing (SA)&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;1. Particle Swarm Optimization (PSO)&lt;/h2&gt;
&lt;p&gt;PSO terinspirasi dari perilaku kawanan burung atau ikan yang bergerak bersama mencari makanan.&lt;/p&gt;
&lt;h3&gt;Konsep Dasar PSO:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Ada sekumpulan &lt;strong&gt;partikel&lt;/strong&gt; yang bergerak di ruang pencarian.&lt;/li&gt;
&lt;li&gt;Setiap partikel punya &lt;strong&gt;posisi&lt;/strong&gt; dan &lt;strong&gt;kecepatan&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Setiap partikel mengingat posisi terbaik yang pernah dicapainya (&lt;strong&gt;personal best&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;Ada juga posisi terbaik secara global (&lt;strong&gt;global best&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;Partikel bergerak mengikuti kombinasi personal best dan global best.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Kelebihan PSO:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Relatif sederhana dan mudah diimplementasikan&lt;/li&gt;
&lt;li&gt;Bagus untuk optimisasi global&lt;/li&gt;
&lt;li&gt;Tidak membutuhkan gradient (derivative-free)&lt;/li&gt;
&lt;li&gt;Cocok untuk masalah dengan banyak local minima&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Kelemahan:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Bisa stuck di local optimum jika parameter tidak diatur dengan baik&lt;/li&gt;
&lt;li&gt;Performa bisa menurun pada dimensi yang sangat tinggi&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;2. Genetic Algorithm (GA)&lt;/h2&gt;
&lt;p&gt;Genetic Algorithm terinspirasi dari proses evolusi dan seleksi alam.&lt;/p&gt;
&lt;h3&gt;Cara Kerja GA:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Inisialisasi&lt;/strong&gt; — Membuat populasi solusi secara acak&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Evaluasi&lt;/strong&gt; — Menghitung fitness setiap individu&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Seleksi&lt;/strong&gt; — Memilih individu terbaik untuk bereproduksi&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Crossover&lt;/strong&gt; — Menggabungkan gen dari dua individu&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mutasi&lt;/strong&gt; — Mengubah sedikit gen secara acak (untuk eksplorasi)&lt;/li&gt;
&lt;li&gt;Ulangi sampai kondisi berhenti terpenuhi&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Kelebihan GA:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Sangat bagus untuk masalah optimisasi kombinatorial&lt;/li&gt;
&lt;li&gt;Bisa mengeksplorasi ruang solusi yang sangat luas&lt;/li&gt;
&lt;li&gt;Robust terhadap noise dan local minima&lt;/li&gt;
&lt;li&gt;Bisa digunakan untuk optimisasi dengan banyak constraint&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Kelemahan:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Butuh banyak komputasi (evaluasi fitness berulang kali)&lt;/li&gt;
&lt;li&gt;Parameter (population size, mutation rate, dll) harus diatur dengan hati-hati&lt;/li&gt;
&lt;li&gt;Konvergensi bisa lambat&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;3. Simulated Annealing (SA)&lt;/h2&gt;
&lt;p&gt;Simulated Annealing terinspirasi dari proses &lt;strong&gt;annealing&lt;/strong&gt; dalam metalurgi (pemanasan dan pendinginan logam secara perlahan).&lt;/p&gt;
&lt;h3&gt;Konsep Utama:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Mulai dengan suhu tinggi → solusi bisa bergerak bebas (banyak eksplorasi)&lt;/li&gt;
&lt;li&gt;Suhu diturunkan secara bertahap&lt;/li&gt;
&lt;li&gt;Pada suhu rendah, hanya solusi yang lebih baik yang diterima&lt;/li&gt;
&lt;li&gt;Memberi kesempatan untuk keluar dari local minimum di awal proses&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Kelebihan SA:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Bagus untuk menghindari local minima&lt;/li&gt;
&lt;li&gt;Relatif sederhana&lt;/li&gt;
&lt;li&gt;Bisa digunakan untuk masalah diskrit maupun kontinu&lt;/li&gt;
&lt;li&gt;Tidak membutuhkan gradient&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Kelemahan:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Konvergensi bisa sangat lambat jika cooling schedule tidak tepat&lt;/li&gt;
&lt;li&gt;Performa sangat bergantung pada parameter suhu awal dan laju pendinginan&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Perbandingan Ketiga Algoritma&lt;/h2&gt;
&lt;div style=&quot;overflow-x: auto; -webkit-overflow-scrolling: touch;&quot;&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspek&lt;/th&gt;
&lt;th&gt;PSO&lt;/th&gt;
&lt;th&gt;Genetic Algorithm&lt;/th&gt;
&lt;th&gt;Simulated Annealing&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Inspirasi&lt;/td&gt;
&lt;td&gt;Perilaku kawanan&lt;/td&gt;
&lt;td&gt;Evolusi &amp;amp; seleksi alam&lt;/td&gt;
&lt;td&gt;Proses annealing logam&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Eksplorasi vs Eksploitasi&lt;/td&gt;
&lt;td&gt;Cukup seimbang&lt;/td&gt;
&lt;td&gt;Eksplorasi sangat baik&lt;/td&gt;
&lt;td&gt;Mulai eksplorasi, lalu eksploitasi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kebutuhan Gradient&lt;/td&gt;
&lt;td&gt;Tidak butuh&lt;/td&gt;
&lt;td&gt;Tidak butuh&lt;/td&gt;
&lt;td&gt;Tidak butuh&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kecepatan Konvergensi&lt;/td&gt;
&lt;td&gt;Sedang&lt;/td&gt;
&lt;td&gt;Lambat&lt;/td&gt;
&lt;td&gt;Bisa lambat&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kemampuan Hindari Local Minima&lt;/td&gt;
&lt;td&gt;Baik&lt;/td&gt;
&lt;td&gt;Sangat Baik&lt;/td&gt;
&lt;td&gt;Baik&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kompleksitas Implementasi&lt;/td&gt;
&lt;td&gt;Rendah&lt;/td&gt;
&lt;td&gt;Sedang&lt;/td&gt;
&lt;td&gt;Rendah&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cocok Untuk&lt;/td&gt;
&lt;td&gt;Continuous optimization&lt;/td&gt;
&lt;td&gt;Kombinatorial &amp;amp; kompleks&lt;/td&gt;
&lt;td&gt;Masalah dengan banyak local minima&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;h2&gt;Kapan Menggunakan Optimization Algorithm Ini?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Gunakan &lt;strong&gt;PSO&lt;/strong&gt; jika kamu butuh optimisasi yang relatif cepat dan sederhana pada masalah continuous.&lt;/li&gt;
&lt;li&gt;Gunakan &lt;strong&gt;Genetic Algorithm&lt;/strong&gt; jika masalahmu sangat kompleks, memiliki banyak constraint, atau bersifat kombinatorial.&lt;/li&gt;
&lt;li&gt;Gunakan &lt;strong&gt;Simulated Annealing&lt;/strong&gt; jika kamu sering stuck di local minimum dan butuh metode yang memberikan kesempatan untuk &amp;quot;melompat&amp;quot; keluar.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Banyak praktisi juga menggunakan &lt;strong&gt;hybrid approach&lt;/strong&gt; (kombinasi beberapa algoritma) atau &lt;strong&gt;Optimization Ensemble&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Kesimpulan Bagian 5&lt;/h2&gt;
&lt;p&gt;Algoritma optimisasi seperti &lt;strong&gt;PSO, Genetic Algorithm, dan Simulated Annealing&lt;/strong&gt; memberikan alternatif yang powerful dibandingkan Gradient Descent, terutama ketika kita menghadapi masalah optimisasi yang sulit dan kompleks.&lt;/p&gt;
&lt;p&gt;Meskipun saat ini deep learning lebih banyak menggunakan optimizer berbasis gradient (Adam, RMSprop, dll), pemahaman tentang algoritma optimisasi metaheuristic ini sangat berguna untuk:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Hyperparameter tuning&lt;/li&gt;
&lt;li&gt;Feature selection&lt;/li&gt;
&lt;li&gt;Model optimization di luar deep learning&lt;/li&gt;
&lt;li&gt;Masalah optimisasi kombinatorial&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Bagian 6: CNN, RNN, dan Optimization Ensemble&lt;/h1&gt;
&lt;p&gt;Di &lt;strong&gt;Bagian 5&lt;/strong&gt;, kita membahas algoritma optimisasi metaheuristic seperti PSO, Genetic Algorithm, dan Simulated Annealing. Sekarang kita akan membahas dua arsitektur deep learning yang sangat penting, serta teknik lanjutan bernama &lt;strong&gt;Optimization Ensemble&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Convolutional Neural Networks (CNN)&lt;/h2&gt;
&lt;p&gt;CNN adalah salah satu arsitektur deep learning paling sukses, terutama untuk data yang memiliki struktur &lt;strong&gt;spasial&lt;/strong&gt; seperti gambar, video, dan data sensor.&lt;/p&gt;
&lt;h3&gt;Mengapa CNN Sangat Efektif untuk Gambar?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Convolutional Layer&lt;/strong&gt; — Menggunakan filter (kernel) untuk mengekstrak fitur lokal (edge, texture, shape).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pooling Layer&lt;/strong&gt; — Mengurangi dimensi sambil mempertahankan informasi penting.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hierarchical Feature Learning&lt;/strong&gt; — Layer awal belajar fitur sederhana, layer dalam belajar fitur yang lebih kompleks.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CNN secara otomatis belajar fitur dari data, sehingga tidak perlu feature engineering manual yang rumit seperti pada metode tradisional.&lt;/p&gt;
&lt;h3&gt;Kegunaan Utama CNN:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Image Classification&lt;/li&gt;
&lt;li&gt;Object Detection&lt;/li&gt;
&lt;li&gt;Image Segmentation&lt;/li&gt;
&lt;li&gt;Medical Image Analysis&lt;/li&gt;
&lt;li&gt;Autonomous Driving&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Recurrent Neural Networks (RNN)&lt;/h2&gt;
&lt;p&gt;RNN dirancang untuk menangani data &lt;strong&gt;sekuensial&lt;/strong&gt; atau data yang memiliki ketergantungan waktu.&lt;/p&gt;
&lt;h3&gt;Masalah dengan Neural Network Biasa:&lt;/h3&gt;
&lt;p&gt;Neural network biasa (termasuk MLP dan CNN) memperlakukan setiap input secara independen. Padahal banyak data di dunia nyata bersifat sekuensial, seperti:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Teks / Bahasa&lt;/li&gt;
&lt;li&gt;Time Series&lt;/li&gt;
&lt;li&gt;Audio / Speech&lt;/li&gt;
&lt;li&gt;Video&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Bagaimana RNN Bekerja?&lt;/h3&gt;
&lt;p&gt;RNN memiliki &lt;strong&gt;hidden state&lt;/strong&gt; yang membawa informasi dari langkah sebelumnya ke langkah berikutnya. Ini memungkinkan model &amp;quot;mengingat&amp;quot; konteks sebelumnya.&lt;/p&gt;
&lt;p&gt;Varian RNN yang populer:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;LSTM (Long Short-Term Memory)&lt;/strong&gt; — Lebih baik dalam menangani long-term dependency&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GRU (Gated Recurrent Unit)&lt;/strong&gt; — Lebih ringan dari LSTM, performa sering kompetitif&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Kegunaan RNN / LSTM:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Machine Translation&lt;/li&gt;
&lt;li&gt;Text Generation&lt;/li&gt;
&lt;li&gt;Speech Recognition&lt;/li&gt;
&lt;li&gt;Time Series Forecasting&lt;/li&gt;
&lt;li&gt;Sentiment Analysis&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Optimization Ensemble&lt;/h2&gt;
&lt;p&gt;Salah satu ide menarik yang dibahas di buku adalah &lt;strong&gt;Optimization Ensemble&lt;/strong&gt; — yaitu menggabungkan beberapa algoritma optimisasi untuk mendapatkan performa yang lebih baik.&lt;/p&gt;
&lt;h3&gt;Mengapa Perlu Ensemble dalam Optimisasi?&lt;/h3&gt;
&lt;p&gt;Setiap algoritma optimisasi memiliki kekuatan dan kelemahan masing-masing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ada yang bagus dalam eksplorasi global&lt;/li&gt;
&lt;li&gt;Ada yang bagus dalam eksploitasi lokal (fine-tuning)&lt;/li&gt;
&lt;li&gt;Ada yang cepat konvergen, ada yang lebih robust&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dengan menggabungkan beberapa algoritma, kita bisa mendapatkan &lt;strong&gt;best of both worlds&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;Cara Kerja Optimization Ensemble&lt;/h3&gt;
&lt;p&gt;Ada beberapa pendekatan:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Parallel Ensemble&lt;/strong&gt; — Menjalankan beberapa optimizer secara paralel, lalu memilih atau menggabungkan hasil terbaik.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sequential Ensemble&lt;/strong&gt; — Menggunakan satu optimizer untuk eksplorasi kasar, lalu melanjutkan dengan optimizer lain untuk fine-tuning.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hybrid Approach&lt;/strong&gt; — Menggabungkan karakteristik dari beberapa algoritma ke dalam satu metode baru.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Kelebihan Optimization Ensemble:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Lebih robust terhadap local minima&lt;/li&gt;
&lt;li&gt;Sering memberikan solusi yang lebih baik&lt;/li&gt;
&lt;li&gt;Bisa memanfaatkan parallel computing dengan baik&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Kelemahan:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Lebih kompleks untuk diimplementasikan&lt;/li&gt;
&lt;li&gt;Butuh lebih banyak sumber daya komputasi&lt;/li&gt;
&lt;li&gt;Parameter tuning menjadi lebih rumit&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Kapan Menggunakan CNN, RNN, atau Ensemble?&lt;/h2&gt;
&lt;div style=&quot;overflow-x: auto; -webkit-overflow-scrolling: touch;&quot;&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Kebutuhan&lt;/th&gt;
&lt;th&gt;Rekomendasi Utama&lt;/th&gt;
&lt;th&gt;Alternatif&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Data Gambar / Visual&lt;/td&gt;
&lt;td&gt;CNN&lt;/td&gt;
&lt;td&gt;Vision Transformer (modern)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data Teks / Sekuensial&lt;/td&gt;
&lt;td&gt;RNN / LSTM / GRU&lt;/td&gt;
&lt;td&gt;Transformer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Optimisasi sulit + banyak local minima&lt;/td&gt;
&lt;td&gt;Optimization Ensemble&lt;/td&gt;
&lt;td&gt;PSO + SA hybrid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Butuh solusi robust &amp;amp; akurat&lt;/td&gt;
&lt;td&gt;Ensemble&lt;/td&gt;
&lt;td&gt;Single strong optimizer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Proyek cepat &amp;amp; prototyping&lt;/td&gt;
&lt;td&gt;CNN / LSTM standalone&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;h2&gt;Kesimpulan Bagian 6&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CNN&lt;/strong&gt; sangat powerful untuk data yang memiliki pola spasial (gambar, dll).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;RNN / LSTM&lt;/strong&gt; unggul dalam menangani data sekuensial dan ketergantungan waktu.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optimization Ensemble&lt;/strong&gt; adalah teknik lanjutan yang bisa memberikan performa lebih baik dengan menggabungkan kekuatan beberapa algoritma optimisasi.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Di era modern, banyak yang sudah beralih ke &lt;strong&gt;Transformer&lt;/strong&gt; untuk menggantikan RNN. Namun, pemahaman dasar tentang CNN dan RNN tetap sangat penting sebagai fondasi.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Bagian 7: Alternative AI Frameworks (ELM, CapsNet, Fuzzy Logic)&lt;/h1&gt;
&lt;p&gt;Di bagian-bagian sebelumnya, kita sudah membahas framework deep learning populer (MXNet, TensorFlow, Keras) dan algoritma optimisasi. Sekarang kita akan melihat beberapa &lt;strong&gt;Alternative AI Frameworks&lt;/strong&gt; yang mungkin kurang populer, tapi memiliki keunikan dan kelebihan tersendiri.&lt;/p&gt;
&lt;h2&gt;Mengapa Perlu Melihat Alternative Frameworks?&lt;/h2&gt;
&lt;p&gt;Meskipun deep learning (khususnya CNN, RNN, Transformer) sangat dominan saat ini, tidak semua masalah bisa diselesaikan dengan baik menggunakan pendekatan tersebut. Beberapa keterbatasan deep learning antara lain:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Butuh data dalam jumlah sangat besar&lt;/li&gt;
&lt;li&gt;Training memakan waktu dan sumber daya komputasi yang besar&lt;/li&gt;
&lt;li&gt;Sulit diinterpretasikan (black box)&lt;/li&gt;
&lt;li&gt;Kurang efektif pada data kecil atau data dengan ketidakpastian tinggi&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Karena itu, mempelajari pendekatan alternatif bisa memberikan kita &lt;strong&gt;lebih banyak pilihan&lt;/strong&gt; sebagai data scientist.&lt;/p&gt;
&lt;h2&gt;1. Extreme Learning Machines (ELM)&lt;/h2&gt;
&lt;p&gt;Extreme Learning Machine adalah jenis &lt;strong&gt;single-hidden layer feedforward neural network&lt;/strong&gt; yang proses training-nya sangat cepat.&lt;/p&gt;
&lt;h3&gt;Konsep Utama ELM:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Bobot antara input layer dan hidden layer diinisialisasi secara acak dan &lt;strong&gt;tidak perlu di-update&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Hanya bobot antara hidden layer dan output layer yang dihitung secara analitis (menggunakan pseudoinverse).&lt;/li&gt;
&lt;li&gt;Tidak menggunakan backpropagation seperti neural network biasa.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Kelebihan ELM:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sangat cepat&lt;/strong&gt; dalam training (bisa ratusan kali lebih cepat dari backpropagation)&lt;/li&gt;
&lt;li&gt;Tidak perlu tuning banyak hyperparameter&lt;/li&gt;
&lt;li&gt;Performa sering kompetitif untuk masalah klasifikasi dan regresi&lt;/li&gt;
&lt;li&gt;Cocok untuk data yang tidak terlalu besar&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Kelemahan ELM:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Kurang fleksibel dibanding deep learning&lt;/li&gt;
&lt;li&gt;Performa bisa kurang stabil karena inisialisasi acak&lt;/li&gt;
&lt;li&gt;Kurang cocok untuk data yang sangat kompleks (gambar resolusi tinggi, dll)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;ELM sangat cocok digunakan ketika kamu butuh model yang &lt;strong&gt;cepat dilatih&lt;/strong&gt; dan data tidak terlalu besar.&lt;/p&gt;
&lt;h2&gt;2. Capsule Networks (CapsNet)&lt;/h2&gt;
&lt;p&gt;Capsule Networks diusulkan oleh Geoffrey Hinton (salah satu &amp;quot;godfather&amp;quot; deep learning) sebagai alternatif dari CNN.&lt;/p&gt;
&lt;h3&gt;Masalah yang Ingin Diselesaikan CapsNet:&lt;/h3&gt;
&lt;p&gt;CNN bagus dalam mendeteksi fitur, tapi &lt;strong&gt;kurang memperhatikan hubungan spasial&lt;/strong&gt; antar fitur. Misalnya, CNN bisa mengenali mata, hidung, dan mulut, tapi tidak selalu peduli apakah posisinya sudah benar membentuk wajah.&lt;/p&gt;
&lt;h3&gt;Konsep Capsule:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Capsule adalah kelompok neuron yang merepresentasikan suatu entitas (misalnya: objek, bagian objek).&lt;/li&gt;
&lt;li&gt;Setiap capsule menghasilkan &lt;strong&gt;vektor&lt;/strong&gt;, bukan scalar.&lt;/li&gt;
&lt;li&gt;Panjang vektor merepresentasikan &lt;strong&gt;probabilitas keberadaan&lt;/strong&gt; entitas.&lt;/li&gt;
&lt;li&gt;Arah vektor merepresentasikan &lt;strong&gt;properti&lt;/strong&gt; entitas (posisi, orientasi, dll).&lt;/li&gt;
&lt;li&gt;Menggunakan &lt;strong&gt;dynamic routing&lt;/strong&gt; untuk menghubungkan antar capsule.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Kelebihan CapsNet:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Lebih baik dalam memahami hierarki dan hubungan spasial&lt;/li&gt;
&lt;li&gt;Lebih robust terhadap perubahan pose dan orientasi&lt;/li&gt;
&lt;li&gt;Potensi lebih interpretabel dibanding CNN&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Kelemahan CapsNet:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Training lebih lambat dan kompleks&lt;/li&gt;
&lt;li&gt;Belum sepopuler CNN&lt;/li&gt;
&lt;li&gt;Masih dalam tahap pengembangan aktif&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CapsNet menarik untuk dipelajari jika kamu bekerja di bidang &lt;strong&gt;computer vision&lt;/strong&gt; dan ingin memahami pendekatan yang berbeda dari CNN.&lt;/p&gt;
&lt;h2&gt;3. Fuzzy Logic dan Fuzzy Inference Systems&lt;/h2&gt;
&lt;p&gt;Fuzzy Logic berbeda dari pendekatan lain karena dirancang untuk menangani &lt;strong&gt;ketidakpastian&lt;/strong&gt; dan &lt;strong&gt;ketidakjelasan&lt;/strong&gt; (vagueness).&lt;/p&gt;
&lt;h3&gt;Perbedaan dengan Logika Klasik:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Logika klasik: Sesuatu hanya bisa &lt;strong&gt;True (1)&lt;/strong&gt; atau &lt;strong&gt;False (0)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Fuzzy Logic: Sesuatu bisa memiliki derajat kebenaran antara &lt;strong&gt;0 sampai 1&lt;/strong&gt; (misalnya: &amp;quot;agak panas&amp;quot;, &amp;quot;cukup tinggi&amp;quot;, &amp;quot;sedikit berawan&amp;quot;)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Komponen Utama Fuzzy Inference System:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Fuzzification&lt;/strong&gt; — Mengubah input crisp menjadi nilai fuzzy&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rule Base&lt;/strong&gt; — Kumpulan aturan if-then (misalnya: IF suhu tinggi AND kelembaban tinggi THEN AC menyala kuat)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Inference Engine&lt;/strong&gt; — Mengevaluasi aturan&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Defuzzification&lt;/strong&gt; — Mengubah output fuzzy menjadi nilai crisp&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Kelebihan Fuzzy Logic:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Sangat baik untuk sistem yang sulit dimodelkan secara matematis&lt;/li&gt;
&lt;li&gt;Mudah diinterpretasikan (aturan dalam bentuk bahasa manusia)&lt;/li&gt;
&lt;li&gt;Cocok untuk sistem kontrol dan decision support&lt;/li&gt;
&lt;li&gt;Bisa dikombinasikan dengan neural network (Neuro-Fuzzy)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Kelemahan Fuzzy Logic:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Membutuhkan pengetahuan ahli untuk membuat aturan&lt;/li&gt;
&lt;li&gt;Sulit untuk data berdimensi tinggi&lt;/li&gt;
&lt;li&gt;Performa bisa kalah dengan deep learning pada tugas pattern recognition kompleks&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Perbandingan Alternative Frameworks&lt;/h2&gt;
&lt;div style=&quot;overflow-x: auto; -webkit-overflow-scrolling: touch;&quot;&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Framework&lt;/th&gt;
&lt;th&gt;Kecepatan Training&lt;/th&gt;
&lt;th&gt;Interpretabilitas&lt;/th&gt;
&lt;th&gt;Cocok Untuk&lt;/th&gt;
&lt;th&gt;Kompleksitas Implementasi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Extreme Learning Machine&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Sangat Cepat&lt;/td&gt;
&lt;td&gt;Sedang&lt;/td&gt;
&lt;td&gt;Data sedang, klasifikasi/regresi cepat&lt;/td&gt;
&lt;td&gt;Rendah&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Capsule Networks&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Lambat&lt;/td&gt;
&lt;td&gt;Tinggi&lt;/td&gt;
&lt;td&gt;Computer Vision, hierarki objek&lt;/td&gt;
&lt;td&gt;Tinggi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fuzzy Logic&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cepat&lt;/td&gt;
&lt;td&gt;Sangat Tinggi&lt;/td&gt;
&lt;td&gt;Sistem kontrol, decision making&lt;/td&gt;
&lt;td&gt;Sedang&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;h2&gt;Kesimpulan Bagian 7&lt;/h2&gt;
&lt;p&gt;Meskipun deep learning saat ini mendominasi, memahami &lt;strong&gt;alternative frameworks&lt;/strong&gt; seperti ELM, CapsNet, dan Fuzzy Logic memberikan kita &lt;strong&gt;toolkit yang lebih lengkap&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gunakan &lt;strong&gt;ELM&lt;/strong&gt; jika butuh model cepat dengan data tidak terlalu besar.&lt;/li&gt;
&lt;li&gt;Pelajari &lt;strong&gt;CapsNet&lt;/strong&gt; jika tertarik dengan computer vision yang lebih memahami struktur objek.&lt;/li&gt;
&lt;li&gt;Manfaatkan &lt;strong&gt;Fuzzy Logic&lt;/strong&gt; untuk sistem yang membutuhkan interpretabilitas tinggi dan penanganan ketidakpastian.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Bagian 8: Transfer Learning, Reinforcement Learning, Autoencoder &amp;amp; GANs&lt;/h1&gt;
&lt;p&gt;Di &lt;strong&gt;Bagian 7&lt;/strong&gt;, kita membahas alternative frameworks. Sekarang kita masuk ke beberapa topik lanjutan yang sangat penting dalam AI modern:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Transfer Learning&lt;/li&gt;
&lt;li&gt;Reinforcement Learning&lt;/li&gt;
&lt;li&gt;Autoencoder&lt;/li&gt;
&lt;li&gt;Generative Adversarial Networks (GANs)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;1. Transfer Learning&lt;/h2&gt;
&lt;p&gt;Transfer Learning adalah teknik di mana kita menggunakan model yang sudah dilatih sebelumnya (pre-trained model) untuk menyelesaikan masalah baru.&lt;/p&gt;
&lt;h3&gt;Kapan Transfer Learning Sangat Berguna?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Data yang kamu miliki &lt;strong&gt;terbatas&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Training model dari nol membutuhkan waktu dan sumber daya yang sangat besar&lt;/li&gt;
&lt;li&gt;Masalah baru memiliki kemiripan dengan masalah yang sudah pernah diselesaikan&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Cara Kerja Transfer Learning:&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Ambil model yang sudah dilatih di dataset besar (misalnya ImageNet)&lt;/li&gt;
&lt;li&gt;Gunakan sebagian besar layer-nya sebagai &lt;strong&gt;feature extractor&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Ganti atau tambahkan layer terakhir sesuai dengan jumlah kelas baru&lt;/li&gt;
&lt;li&gt;Fine-tune (opsional) — latih ulang beberapa layer terakhir dengan data kamu&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Kelebihan Transfer Learning:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Training jauh lebih cepat&lt;/li&gt;
&lt;li&gt;Performa sering lebih baik meskipun data sedikit&lt;/li&gt;
&lt;li&gt;Menghemat biaya komputasi&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Kapan Tidak Cocok:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Domain sangat berbeda (misalnya pakai model gambar untuk data teks)&lt;/li&gt;
&lt;li&gt;Data kamu sangat spesifik dan unik&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;2. Reinforcement Learning (RL)&lt;/h2&gt;
&lt;p&gt;Reinforcement Learning adalah paradigma machine learning di mana agent belajar melalui &lt;strong&gt;interaksi dengan lingkungan&lt;/strong&gt; dan menerima &lt;strong&gt;reward&lt;/strong&gt; atau &lt;strong&gt;punishment&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;Konsep Kunci dalam RL:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Agent&lt;/strong&gt; — Entitas yang belajar dan mengambil keputusan&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Environment&lt;/strong&gt; — Dunia tempat agent berinteraksi&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;State&lt;/strong&gt; — Kondisi saat ini dari environment&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Action&lt;/strong&gt; — Tindakan yang bisa dilakukan agent&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reward&lt;/strong&gt; — Umpan balik (positif atau negatif)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Policy&lt;/strong&gt; — Strategi yang dipelajari agent untuk memilih action&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Jenis-jenis RL:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Value-based&lt;/strong&gt; (misalnya Q-Learning, Deep Q-Network)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Policy-based&lt;/strong&gt; (misalnya REINFORCE, Policy Gradient)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Actor-Critic&lt;/strong&gt; (kombinasi value dan policy)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Aplikasi Reinforcement Learning:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Game playing (AlphaGo, Atari games)&lt;/li&gt;
&lt;li&gt;Robot control&lt;/li&gt;
&lt;li&gt;Resource management&lt;/li&gt;
&lt;li&gt;Trading / Portfolio optimization&lt;/li&gt;
&lt;li&gt;Recommendation systems&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Reinforcement Learning sangat powerful, tapi training-nya sering tidak stabil dan membutuhkan banyak trial-and-error.&lt;/p&gt;
&lt;h2&gt;3. Autoencoder Systems&lt;/h2&gt;
&lt;p&gt;Autoencoder adalah jenis neural network yang dilatih untuk &lt;strong&gt;merekonstruksi input-nya sendiri&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;Struktur Autoencoder:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Encoder&lt;/strong&gt; — Mengompresi input menjadi representasi berdimensi rendah (latent space)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Decoder&lt;/strong&gt; — Merekonstruksi input dari representasi tersebut&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Tujuan Utama Autoencoder:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dimensionality Reduction&lt;/strong&gt; (mirip PCA tapi non-linear)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Feature Learning&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Anomaly Detection&lt;/strong&gt; (data yang sulit direkonstruksi = anomali)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Denoising&lt;/strong&gt; (membersihkan noise dari data)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data Generation&lt;/strong&gt; (variasi tertentu)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Jenis-jenis Autoencoder:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Vanilla Autoencoder&lt;/li&gt;
&lt;li&gt;Denoising Autoencoder&lt;/li&gt;
&lt;li&gt;Sparse Autoencoder&lt;/li&gt;
&lt;li&gt;Variational Autoencoder (VAE) — sangat populer untuk generative modeling&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;4. Generative Adversarial Networks (GANs)&lt;/h2&gt;
&lt;p&gt;GAN adalah salah satu ide paling inovatif dalam deep learning. Diperkenalkan oleh Ian Goodfellow pada 2014.&lt;/p&gt;
&lt;h3&gt;Cara Kerja GAN:&lt;/h3&gt;
&lt;p&gt;GAN terdiri dari dua neural network yang saling bersaing:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Generator&lt;/strong&gt; — Mencoba membuat data palsu yang mirip data asli&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Discriminator&lt;/strong&gt; — Mencoba membedakan data asli dan data palsu&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Keduanya dilatih secara bersamaan dalam proses &lt;strong&gt;adversarial training&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;Tujuan GAN:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Generator belajar membuat data yang semakin realistis&lt;/li&gt;
&lt;li&gt;Discriminator menjadi semakin baik dalam mendeteksi data palsu&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Aplikasi GAN:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Image generation (membuat wajah manusia yang tidak nyata)&lt;/li&gt;
&lt;li&gt;Image-to-Image translation (ubah foto jadi lukisan, dll)&lt;/li&gt;
&lt;li&gt;Super-resolution&lt;/li&gt;
&lt;li&gt;Data augmentation&lt;/li&gt;
&lt;li&gt;Music dan video generation&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Tantangan dalam Training GAN:&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Sulit untuk melatih (mode collapse, training instability)&lt;/li&gt;
&lt;li&gt;Butuh banyak tuning hyperparameter&lt;/li&gt;
&lt;li&gt;Evaluasi kualitas hasil sulit dilakukan secara objektif&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Ringkasan Keempat Topik&lt;/h2&gt;
&lt;div style=&quot;overflow-x: auto; -webkit-overflow-scrolling: touch;&quot;&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Topik&lt;/th&gt;
&lt;th&gt;Tujuan Utama&lt;/th&gt;
&lt;th&gt;Data yang Dibutuhkan&lt;/th&gt;
&lt;th&gt;Tingkat Kesulitan&lt;/th&gt;
&lt;th&gt;Contoh Penggunaan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Transfer Learning&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manfaatkan model pre-trained&lt;/td&gt;
&lt;td&gt;Sedang - Kecil&lt;/td&gt;
&lt;td&gt;Rendah - Sedang&lt;/td&gt;
&lt;td&gt;Image classification dengan data terbatas&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Reinforcement Learning&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Belajar melalui reward &amp;amp; punishment&lt;/td&gt;
&lt;td&gt;Lingkungan simulasi&lt;/td&gt;
&lt;td&gt;Tinggi&lt;/td&gt;
&lt;td&gt;Game AI, Robot, Trading&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Autoencoder&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Kompresi &amp;amp; rekonstruksi data&lt;/td&gt;
&lt;td&gt;Tanpa label&lt;/td&gt;
&lt;td&gt;Sedang&lt;/td&gt;
&lt;td&gt;Anomaly detection, Dimensionality reduction&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GANs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Generate data baru yang realistis&lt;/td&gt;
&lt;td&gt;Data asli&lt;/td&gt;
&lt;td&gt;Tinggi&lt;/td&gt;
&lt;td&gt;Image generation, Data augmentation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;h2&gt;Kesimpulan Bagian 8&lt;/h2&gt;
&lt;p&gt;Keempat topik ini mewakili arah penting dalam perkembangan AI:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Transfer Learning&lt;/strong&gt; → Membuat deep learning lebih praktis untuk data kecil&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reinforcement Learning&lt;/strong&gt; → Membuka jalan bagi AI yang bisa belajar dari interaksi&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Autoencoder&lt;/strong&gt; → Memberikan cara untuk memahami dan memanipulasi representasi data&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GANs&lt;/strong&gt; → Membuka era generative AI yang semakin berkembang pesat&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Banyak teknik modern saat ini (seperti Stable Diffusion, GPT, dll) dibangun di atas fondasi ide-ide dari topik-topik di atas.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Bagian 9: Aspek Bisnis Penerapan AI dalam Proyek Data Science&lt;/h1&gt;
&lt;p&gt;Selamat datang di &lt;strong&gt;Bagian terakhir&lt;/strong&gt; dari seri ini.&lt;/p&gt;
&lt;p&gt;Di delapan artikel sebelumnya, kita sudah membahas banyak hal secara teknis — mulai dari framework deep learning, optimisasi, CNN, RNN, sampai GANs. Sekarang saatnya kita melihat sisi lain yang tidak kalah penting: &lt;strong&gt;aspek bisnis&lt;/strong&gt; dari penerapan AI dalam proyek data science.&lt;/p&gt;
&lt;h2&gt;Mengapa Aspek Bisnis Penting?&lt;/h2&gt;
&lt;p&gt;Banyak proyek AI gagal bukan karena teknologinya buruk, melainkan karena:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tidak ada &lt;strong&gt;business case&lt;/strong&gt; yang jelas&lt;/li&gt;
&lt;li&gt;ROI (Return on Investment) tidak terukur&lt;/li&gt;
&lt;li&gt;Kurangnya dukungan dari stakeholder bisnis&lt;/li&gt;
&lt;li&gt;Terlalu fokus pada teknologi, kurang fokus pada &lt;strong&gt;value&lt;/strong&gt; yang dihasilkan&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Seorang data scientist atau AI practitioner yang baik tidak hanya harus mahir secara teknis, tetapi juga harus memahami bagaimana AI bisa memberikan &lt;strong&gt;dampak bisnis&lt;/strong&gt; yang nyata.&lt;/p&gt;
&lt;h2&gt;Teknologi AI yang Relevan untuk Bisnis&lt;/h2&gt;
&lt;p&gt;Berikut beberapa teknologi AI yang paling banyak memberikan value bisnis saat ini:&lt;/p&gt;
&lt;div style=&quot;overflow-x: auto; -webkit-overflow-scrolling: touch;&quot;&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Teknologi&lt;/th&gt;
&lt;th&gt;Contoh Aplikasi Bisnis&lt;/th&gt;
&lt;th&gt;Potensi ROI&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Predictive Analytics&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Prediksi churn, demand forecasting&lt;/td&gt;
&lt;td&gt;Tinggi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Computer Vision&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Quality control, surveillance, retail&lt;/td&gt;
&lt;td&gt;Sedang - Tinggi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Natural Language Processing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Chatbot, sentiment analysis, document processing&lt;/td&gt;
&lt;td&gt;Tinggi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Recommendation Systems&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;E-commerce, content platform&lt;/td&gt;
&lt;td&gt;Sangat Tinggi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Anomaly Detection&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fraud detection, system monitoring&lt;/td&gt;
&lt;td&gt;Tinggi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Generative AI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Content creation, design, code generation&lt;/td&gt;
&lt;td&gt;Sedang (sedang berkembang)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;h2&gt;Industri yang Paling Diuntungkan dari AI&lt;/h2&gt;
&lt;p&gt;Beberapa industri yang saat ini paling agresif mengadopsi AI:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Financial Services&lt;/strong&gt; — Fraud detection, credit scoring, algorithmic trading&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Healthcare&lt;/strong&gt; — Medical imaging, drug discovery, patient risk prediction&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Retail &amp;amp; E-commerce&lt;/strong&gt; — Personalization, inventory optimization, visual search&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Manufacturing&lt;/strong&gt; — Predictive maintenance, quality control, supply chain&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Telecommunication&lt;/strong&gt; — Customer churn prediction, network optimization&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Logistics &amp;amp; Transportation&lt;/strong&gt; — Route optimization, demand forecasting&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Sumber Daya AI yang Penting&lt;/h2&gt;
&lt;p&gt;Untuk berhasil menerapkan AI di lingkungan bisnis, organisasi perlu memperhatikan beberapa hal:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Data Infrastructure&lt;/strong&gt; — Kualitas dan ketersediaan data adalah fondasi&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Talent&lt;/strong&gt; — Data scientist, ML engineer, data engineer, dan AI product manager&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tools &amp;amp; Platform&lt;/strong&gt; — Cloud (AWS, GCP, Azure), MLOps tools, AutoML&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Governance &amp;amp; Ethics&lt;/strong&gt; — Data privacy, model fairness, explainability&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Change Management&lt;/strong&gt; — Mengubah cara kerja tim agar bisa memanfaatkan AI&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Pendidikan Data Science untuk Proyek AI&lt;/h2&gt;
&lt;p&gt;Buku ini juga menekankan pentingnya pendidikan yang tepat. Beberapa rekomendasi:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Mulai dari &lt;strong&gt;dasar yang kuat&lt;/strong&gt; (statistika, programming, data wrangling)&lt;/li&gt;
&lt;li&gt;Jangan langsung loncat ke deep learning tanpa memahami machine learning dasar&lt;/li&gt;
&lt;li&gt;Pahami &lt;strong&gt;konteks bisnis&lt;/strong&gt; dari setiap proyek&lt;/li&gt;
&lt;li&gt;Terus belajar karena bidang ini berkembang sangat cepat&lt;/li&gt;
&lt;li&gt;Bangun portfolio proyek nyata, bukan hanya tutorial&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Pelajaran Penting dari Seri Ini&lt;/h2&gt;
&lt;p&gt;Sepanjang 9 artikel ini, ada beberapa takeaway utama:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;AI bukan magic&lt;/strong&gt; — Ia adalah tools yang powerful jika digunakan dengan tepat.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pilih framework sesuai kebutuhan&lt;/strong&gt;, bukan karena sedang tren.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optimization matters&lt;/strong&gt; — Baik di level model maupun di level bisnis.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Jangan hanya fokus ke akurasi&lt;/strong&gt; — Value bisnis, interpretability, dan scalability juga penting.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Selalu ada trade-off&lt;/strong&gt; — Antara performa, kecepatan, biaya, dan kompleksitas.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hybrid approach&lt;/strong&gt; sering lebih baik daripada hanya mengandalkan satu metode.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Penutup&lt;/h2&gt;
&lt;p&gt;Buku &lt;strong&gt;&amp;quot;AI for Data Science&amp;quot;&lt;/strong&gt; memberikan pandangan yang cukup komprehensif tentang berbagai pendekatan AI yang bisa digunakan dalam data science — bukan hanya deep learning, tapi juga optimization algorithms, alternative frameworks, dan aspek bisnis.&lt;/p&gt;
&lt;p&gt;Sebagai praktisi, tugas kita adalah:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Terus belajar dan bereksperimen&lt;/li&gt;
&lt;li&gt;Memilih tools yang tepat untuk masalah yang dihadapi&lt;/li&gt;
&lt;li&gt;Selalu menghubungkan pekerjaan teknis dengan &lt;strong&gt;dampak bisnis&lt;/strong&gt; yang nyata&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Terima kasih sudah mengikuti seri ini sampai akhir.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Sumber Utama&lt;/strong&gt;:&lt;br&gt;Buku &lt;em&gt;AI for Data Science&lt;/em&gt; oleh Zacharias Voulgaris, PhD &amp;amp; Yunus Emrah Bulut (Technics Publications, 2018)&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;#daftar-isi&quot;&gt;← Kembali ke Daftar Isi&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Penutup &amp;amp; Ringkasan Seri&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Seri ini terdiri dari 9 bagian:&lt;/strong&gt;&lt;/p&gt;
&lt;div style=&quot;overflow-x: auto; -webkit-overflow-scrolling: touch;&quot;&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;No&lt;/th&gt;
&lt;th&gt;Bagian&lt;/th&gt;
&lt;th&gt;Fokus Utama&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Pengantar AI&lt;/td&gt;
&lt;td&gt;Konsep dasar AI &amp;amp; relevansinya untuk data science&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Deep Learning Frameworks&lt;/td&gt;
&lt;td&gt;MXNet, TensorFlow, Keras, PyTorch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;MXNet Hands-on&lt;/td&gt;
&lt;td&gt;Membangun MLP dengan Gluon&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;TensorFlow &amp;amp; Keras&lt;/td&gt;
&lt;td&gt;Production-ready frameworks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Optimization Algorithms&lt;/td&gt;
&lt;td&gt;PSO, Genetic Algorithm, Simulated Annealing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;CNN, RNN &amp;amp; Ensemble&lt;/td&gt;
&lt;td&gt;Advanced deep learning + optimization ensemble&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;Alternative Frameworks&lt;/td&gt;
&lt;td&gt;ELM, CapsNet, Fuzzy Logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Advanced Topics&lt;/td&gt;
&lt;td&gt;Transfer Learning, RL, Autoencoder, GANs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;Aspek Bisnis&lt;/td&gt;
&lt;td&gt;Value bisnis, industri, dan pelajaran praktis&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;

&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Terima kasih telah membaca ebook ini.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Semoga seri ini membantu kamu memahami berbagai pendekatan AI yang bisa digunakan dalam data science, bukan hanya deep learning, tetapi juga metode optimisasi, framework alternatif, dan yang paling penting — bagaimana menghubungkan semuanya dengan &lt;strong&gt;dampak bisnis&lt;/strong&gt; yang nyata.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;© 2026&lt;/strong&gt; | Dirangkum dari buku &lt;em&gt;AI for Data Science&lt;/em&gt; oleh Zacharias Voulgaris, PhD &amp;amp; Yunus Emrah Bulut&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Akhir dari Ebook&lt;/strong&gt;&lt;/p&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://ngopidulur.my.id/blog/ai-untuk-data-science-panduan-lengkap-dari-dasar-hingga-praktik-bisnis/&quot;&gt;https://ngopidulur.my.id/blog/ai-untuk-data-science-panduan-lengkap-dari-dasar-hingga-praktik-bisnis/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>Ngopidulur</dc:creator><pubDate>Fri, 22 May 2026 14:55:00 GMT</pubDate></item><item><title>Panduan Lengkap Membangun Hermes AI Agent 2026: Dari Nol sampai Production</title><link>https://ngopidulur.my.id/blog/panduan-lengkap-membangun-hermes-ai-agent-2026-dari-nol-sampai-production/</link><guid isPermaLink="true">https://ngopidulur.my.id/blog/panduan-lengkap-membangun-hermes-ai-agent-2026-dari-nol-sampai-production/</guid><description>Panduan praktis membangun Hermes AI Agent dari awal hingga siap production. Mulai dari instalasi, konfigurasi model (DeepSeek + fallback), skills, memory, gateway Telegram, cron job, sampai setup trading otomatis. Cocok buat yang ingin punya AI Agent pribadi 24/7.</description><content:encoded>&lt;p&gt;Hermes Agent adalah framework AI Agent open-source dari Nous Research yang sangat powerful. Bukan sekadar chatbot biasa, melainkan &lt;strong&gt;co-pilot digital&lt;/strong&gt; yang bisa belajar sendiri, mengingat preferensi kamu, dan bekerja secara otonom.&lt;/p&gt;
&lt;p&gt;Artikel ini merangkum panduan praktis membangun Hermes AI Agent dari nol hingga siap digunakan di production, berdasarkan pengalaman langsung (update Mei 2026).&lt;/p&gt;
&lt;h2&gt;Apa yang Membuat Hermes Berbeda?&lt;/h2&gt;
&lt;p&gt;Hermes memiliki beberapa keunggulan utama:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Self-improving via Skills&lt;/strong&gt; — Hermes bisa menyimpan cara menyelesaikan tugas kompleks sebagai &lt;em&gt;skill&lt;/em&gt; yang bisa dipakai lagi di masa depan.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Persistent Memory&lt;/strong&gt; — Mengingat siapa kamu, preferensi, lingkungan kerja, dan pelajaran dari kesalahan sebelumnya.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multi-Platform Gateway&lt;/strong&gt; — Bisa diakses dari Telegram, Discord, WhatsApp, Slack, dan lainnya dengan satu otak yang sama.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Provider-Agnostic&lt;/strong&gt; — Bebas menggunakan DeepSeek, Claude, GPT, Gemini, atau model lokal (Ollama).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Profiles&lt;/strong&gt; — Bisa membuat beberapa instance Hermes dengan tugas dan kepribadian berbeda (misalnya: satu untuk trading, satu untuk coding).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Persiapan Sebelum Install&lt;/h2&gt;
&lt;h3&gt;Rekomendasi VPS&lt;/h3&gt;
&lt;p&gt;Untuk penggunaan 24/7, disarankan menggunakan VPS:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Raff Technologies&lt;/strong&gt; → Paling stabil untuk Hermes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DigitalOcean&lt;/strong&gt; → $6/bulan (1GB RAM)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vultr&lt;/strong&gt; → Mulai dari $2.5/bulan&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Contabo&lt;/strong&gt; → Spesifikasi besar dengan harga murah&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;API Key yang Disarankan&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;API Key&lt;/th&gt;
&lt;th&gt;Kegunaan&lt;/th&gt;
&lt;th&gt;Biaya&lt;/th&gt;
&lt;th&gt;Rekomendasi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;OpenRouter&lt;/td&gt;
&lt;td&gt;Testing &amp;amp; fallback&lt;/td&gt;
&lt;td&gt;Gratis tier&lt;/td&gt;
&lt;td&gt;Sangat disarankan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DeepSeek&lt;/td&gt;
&lt;td&gt;Model utama (cepat &amp;amp; murah)&lt;/td&gt;
&lt;td&gt;Murah&lt;/td&gt;
&lt;td&gt;Paling direkomendasikan&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google AI&lt;/td&gt;
&lt;td&gt;Vision (analisis gambar)&lt;/td&gt;
&lt;td&gt;Gratis&lt;/td&gt;
&lt;td&gt;Untuk vision&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Telegram Bot&lt;/td&gt;
&lt;td&gt;Gateway&lt;/td&gt;
&lt;td&gt;Gratis&lt;/td&gt;
&lt;td&gt;Wajib&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;Instalasi Hermes Agent&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Cara paling mudah (Recommended):&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Setelah selesai, verifikasi dengan:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;hermes doctor
hermes --version
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Konfigurasi Model &amp;amp; Provider&lt;/h2&gt;
&lt;p&gt;Penulis merekomendasikan &lt;strong&gt;DeepSeek V4 Flash&lt;/strong&gt; sebagai model utama karena cepat dan murah.&lt;/p&gt;
&lt;p&gt;Contoh konfigurasi:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;hermes config set model.default deepseek-v4-flash
hermes config set model.provider deepseek
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Rekomendasi Setup Model:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Model Utama&lt;/strong&gt;: DeepSeek V4 Flash&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Vision&lt;/strong&gt;: Google Gemini (gratis &amp;amp; rate limit tinggi)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fallback&lt;/strong&gt;: Siapkan minimal satu provider cadangan&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Skills — Fitur Paling Penting&lt;/h2&gt;
&lt;p&gt;Skills adalah kemampuan Hermes untuk menyimpan prosedur kerja. Ini yang membuat Hermes semakin pintar seiring waktu.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;hermes skills list
hermes skills install crypto-market-analysis
hermes skills install trading-workflow
hermes skills install pdf-report
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Tips&lt;/strong&gt;: Setiap kali kamu menyelesaikan tugas yang rumit, suruh Hermes menyimpannya sebagai skill.&lt;/p&gt;
&lt;h2&gt;Gateway (Telegram, Discord, dll)&lt;/h2&gt;
&lt;p&gt;Gateway memungkinkan kamu berinteraksi dengan Hermes dari berbagai platform.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Setup Telegram Gateway (paling direkomendasikan):&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;hermes gateway setup
hermes gateway install
hermes gateway start
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Setelah aktif, kamu bisa chat dengan Hermes langsung dari Telegram.&lt;/p&gt;
&lt;h2&gt;Cron Jobs &amp;amp; Otomatisasi&lt;/h2&gt;
&lt;p&gt;Hermes bisa menjalankan tugas secara otomatis menggunakan cron.&lt;/p&gt;
&lt;p&gt;Contoh:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;hermes cron create &amp;quot;0 8 * * *&amp;quot; \
  --name &amp;quot;Daily Report&amp;quot; \
  --skills vps-health,pdf-report \
  --deliver telegram
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Trading dengan Hermes&lt;/h2&gt;
&lt;p&gt;Hermes sudah mendukung berbagai kebutuhan trading:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Analisa crypto (funding rate, market structure)&lt;/li&gt;
&lt;li&gt;Token screening&lt;/li&gt;
&lt;li&gt;Signal synthesis&lt;/li&gt;
&lt;li&gt;Analisa saham Indonesia&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cukup install skill trading yang dibutuhkan, lalu kamu bisa bertanya langsung seperti:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Analisa BTC funding rate sekarang”
“Screening token baru di Solana”
“Sinyal apa yang converging hari ini?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;Tips dari Pengalaman Langsung&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Minimal Model Configuration&lt;/strong&gt; — Cukup gunakan 2 model (utama + vision).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prioritaskan Skill&lt;/strong&gt; — Jangan ulangi pekerjaan yang sama. Buat skill.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gunakan Cron dengan Bijak&lt;/strong&gt; — Override model ke yang gratis untuk tugas rutin.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Backup Rutin&lt;/strong&gt; — Selalu backup folder &lt;code&gt;~/.hermes/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mulai Sederhana&lt;/strong&gt; — Jangan langsung pakai banyak API key.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Manfaatkan Profiles&lt;/strong&gt; — Buat profile terpisah untuk trading, coding, dan research.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Troubleshooting Singkat&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Masalah&lt;/th&gt;
&lt;th&gt;Solusi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Vision error&lt;/td&gt;
&lt;td&gt;Ganti provider vision&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cron tidak jalan&lt;/td&gt;
&lt;td&gt;Override model ke yang gratis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gateway mati&lt;/td&gt;
&lt;td&gt;Jalankan &lt;code&gt;loginctl enable-linger&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Memory hilang&lt;/td&gt;
&lt;td&gt;Cek &lt;code&gt;hermes memory status&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tools tidak muncul&lt;/td&gt;
&lt;td&gt;Aktifkan toolset yang dibutuhkan&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;Kesimpulan&lt;/h2&gt;
&lt;p&gt;Hermes AI Agent adalah salah satu framework AI Agent terbaik saat ini untuk kebutuhan personal dan semi-profesional. Dengan kombinasi &lt;strong&gt;Skills + Persistent Memory + Gateway + Cron&lt;/strong&gt;, kamu bisa membangun asisten digital yang benar-benar bekerja untukmu.&lt;/p&gt;
&lt;p&gt;Makin sering digunakan, makin pintar, dan makin sesuai dengan kebiasaan kerja kamu.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Sumber&lt;/strong&gt;: Panduan Lengkap Membangun Hermes AI Agent oleh Noctis (@sequencetraders), Mei 2026.&lt;/p&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://ngopidulur.my.id/blog/panduan-lengkap-membangun-hermes-ai-agent-2026-dari-nol-sampai-production/&quot;&gt;https://ngopidulur.my.id/blog/panduan-lengkap-membangun-hermes-ai-agent-2026-dari-nol-sampai-production/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>Ngopidulur</dc:creator><pubDate>Fri, 22 May 2026 14:15:00 GMT</pubDate></item><item><title>Panduan Instalasi Hermes AI Agent 2026: Dari VPS Kosong sampai Siap Pakai</title><link>https://ngopidulur.my.id/blog/panduan-instalasi-hermes-ai-agent-2026-dari-vps-kosong-sampai-siap-pakai/</link><guid isPermaLink="true">https://ngopidulur.my.id/blog/panduan-instalasi-hermes-ai-agent-2026-dari-vps-kosong-sampai-siap-pakai/</guid><description>Panduan lengkap instalasi Hermes AI Agent di Linux, macOS, dan Windows (WSL2). Mulai dari persiapan sampai first run, termasuk troubleshooting dan rekomendasi setup production 2026. Cocok untuk pemula yang ingin self-hosting AI Agent.</description><content:encoded>&lt;p&gt;Baru mau coba bikin AI Agent sendiri? Hermes Agent dari Nous Research adalah salah satu framework agent yang paling powerful dan fleksibel di 2026.&lt;/p&gt;
&lt;p&gt;Artikel ini merangkum &lt;strong&gt;panduan instalasi lengkap&lt;/strong&gt; Hermes AI Agent — mulai dari VPS Linux, macOS, sampai Windows via WSL2. Cocok buat pemula maupun yang sudah punya pengalaman self-hosting.&lt;/p&gt;
&lt;h2&gt;Minimum Requirements&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Komponen&lt;/th&gt;
&lt;th&gt;Linux&lt;/th&gt;
&lt;th&gt;macOS&lt;/th&gt;
&lt;th&gt;Windows (WSL)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;CPU&lt;/td&gt;
&lt;td&gt;1 Core&lt;/td&gt;
&lt;td&gt;Intel / Apple Silicon&lt;/td&gt;
&lt;td&gt;Any x64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RAM&lt;/td&gt;
&lt;td&gt;1 GB&lt;/td&gt;
&lt;td&gt;4 GB+&lt;/td&gt;
&lt;td&gt;4 GB+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Storage&lt;/td&gt;
&lt;td&gt;10 GB&lt;/td&gt;
&lt;td&gt;10 GB&lt;/td&gt;
&lt;td&gt;10 GB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python&lt;/td&gt;
&lt;td&gt;3.10+&lt;/td&gt;
&lt;td&gt;3.10+&lt;/td&gt;
&lt;td&gt;3.10+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node.js&lt;/td&gt;
&lt;td&gt;18.x+&lt;/td&gt;
&lt;td&gt;18.x+&lt;/td&gt;
&lt;td&gt;18.x+&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Rekomendasi&lt;/strong&gt;: Untuk production 24/7, pakai &lt;strong&gt;VPS Linux&lt;/strong&gt;. Untuk belajar, laptop Mac/Windows juga cukup.&lt;/p&gt;
&lt;h2&gt;1. Linux (Ubuntu/Debian) – Paling Direkomendasikan&lt;/h2&gt;
&lt;p&gt;Panduan ini untuk Ubuntu 22.04 / 24.04.&lt;/p&gt;
&lt;h3&gt;Step 1: Update Sistem&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 2: Install Dependencies&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt install -y curl git python3 python3-pip python3-venv build-essential ffmpeg tesseract-ocr
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 3: Install Node.js 20.x&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
node --version
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 4: Install Hermes Agent (Pilih salah satu)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Opsi A – Install Script (Recommended)&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Opsi B – Install dari Source&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;git clone https://github.com/NousResearch/hermes-agent.git
cd hermes-agent
pip install -e .
hermes doctor
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 5: Verifikasi&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;hermes doctor
hermes --version
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Kalau semua hijau, instalasi Linux berhasil!&lt;/p&gt;
&lt;h2&gt;2. macOS (Intel &amp;amp; Apple Silicon)&lt;/h2&gt;
&lt;h3&gt;Step 1: Install Homebrew&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;/bin/bash -c &amp;quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 2: Install Dependencies&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;brew install python@3.12 node git curl ffmpeg tesseract
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Untuk Apple Silicon + GPU acceleration (opsional):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;brew install --cask llama.cpp
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 3: Install Hermes Agent&lt;/h3&gt;
&lt;p&gt;Sama seperti Linux:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# Opsi A (Recommended)
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash

# Opsi B
git clone https://github.com/NousResearch/hermes-agent.git
cd hermes-agent
pip3 install -e .
hermes doctor
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 4: Fix PATH (jika perlu)&lt;/h3&gt;
&lt;p&gt;Tambahkan ke &lt;code&gt;~/.zshrc&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;export PATH=&amp;quot;$PATH:~/.local/bin&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;3. Windows (WSL2)&lt;/h2&gt;
&lt;p&gt;Hermes &lt;strong&gt;tidak bisa&lt;/strong&gt; jalan native di Windows. Harus lewat WSL2.&lt;/p&gt;
&lt;h3&gt;Step 1: Install WSL2&lt;/h3&gt;
&lt;p&gt;Buka &lt;strong&gt;PowerShell sebagai Administrator&lt;/strong&gt;, lalu jalankan:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;wsl --install -d Ubuntu-24.04
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Cek versi:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;wsl --version
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Penting&lt;/strong&gt;: Pastikan pakai &lt;strong&gt;WSL2&lt;/strong&gt;, bukan WSL1.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Step 2: Install di dalam WSL&lt;/h3&gt;
&lt;p&gt;Masuk ke terminal Ubuntu, lalu jalankan langkah yang sama seperti Linux di atas.&lt;/p&gt;
&lt;h3&gt;Step 3: Setup Gateway (Akses dari Windows)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;hermes gateway setup   # Pilih Telegram
hermes gateway start
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sekarang kamu bisa chat dengan Hermes lewat Telegram dari HP atau Windows.&lt;/p&gt;
&lt;h2&gt;4. Verifikasi &amp;amp; First Run&lt;/h2&gt;
&lt;p&gt;Setelah instalasi, lakukan langkah berikut:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# 1. Cek kesehatan sistem
hermes doctor

# 2. Cek versi
hermes --version

# 3. First chat (tanpa setup)
hermes chat -q &amp;quot;Halo, siapa kamu?&amp;quot;

# 4. Masuk mode interaktif
hermes
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Kalau muncul error API key, daftar gratis di &lt;a href=&quot;https://openrouter.ai&quot;&gt;openrouter.ai&lt;/a&gt; lalu masukkan ke file:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;echo &amp;#39;OPENROUTER_API_KEY=sk-or-v1-...&amp;#39; &amp;gt;&amp;gt; ~/.hermes/.env
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;5. Konfigurasi Awal&lt;/h2&gt;
&lt;p&gt;Gunakan setup wizard (paling mudah):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;hermes setup           # Setup lengkap
hermes setup model     # Hanya model &amp;amp; provider
hermes setup gateway   # Setup Telegram / Discord
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;File Penting&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;~/.hermes/config.yaml&lt;/code&gt; → Konfigurasi utama&lt;/li&gt;
&lt;li&gt;&lt;code&gt;~/.hermes/.env&lt;/code&gt; → API Keys (jangan di-share!)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;~/.hermes/skills/&lt;/code&gt; → Skill yang terinstall&lt;/li&gt;
&lt;li&gt;&lt;code&gt;~/.hermes/sessions/&lt;/code&gt; → Riwayat percakapan&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;6. Troubleshooting&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Masalah&lt;/th&gt;
&lt;th&gt;Penyebab&lt;/th&gt;
&lt;th&gt;Solusi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;code&gt;hermes doctor&lt;/code&gt; error&lt;/td&gt;
&lt;td&gt;Missing dependencies&lt;/td&gt;
&lt;td&gt;Install ulang dependencies via apt/brew&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;command not found: hermes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;PATH belum include &lt;code&gt;~/.local/bin&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;export PATH=$PATH:~/.local/bin&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Python version error&lt;/td&gt;
&lt;td&gt;Python &amp;lt; 3.10&lt;/td&gt;
&lt;td&gt;Install Python 3.10+ via pyenv / apt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node.js not found&lt;/td&gt;
&lt;td&gt;Node.js belum terinstall&lt;/td&gt;
&lt;td&gt;Install Node.js 20.x via NodeSource&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gateway tidak jalan&lt;/td&gt;
&lt;td&gt;WSL2 systemd disabled&lt;/td&gt;
&lt;td&gt;Enable systemd di &lt;code&gt;/etc/wsl.conf&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;No module named _tkinter&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Tkinter missing&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sudo apt install python3-tk&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Masih bermasalah? Tanya di X: &lt;strong&gt;@sequencetraders&lt;/strong&gt; atau buka issue di GitHub NousResearch/hermes-agent.&lt;/p&gt;
&lt;h2&gt;Kesimpulan&lt;/h2&gt;
&lt;p&gt;Hermes AI Agent adalah framework yang sangat powerful untuk membuat agent otonom. Dengan panduan ini, kamu bisa install Hermes di hampir semua platform dalam waktu kurang dari 15 menit.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rekomendasi setup 2026&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Production / 24/7&lt;/strong&gt; → VPS Linux + Coolify + Cloudflare Tunnel&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Development&lt;/strong&gt; → MacBook / Windows + WSL2&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Testing cepat&lt;/strong&gt; → Gunakan OpenRouter gratis dulu&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Sudah berhasil install Hermes?&lt;br&gt;Share screenshot &lt;code&gt;hermes doctor&lt;/code&gt; kamu di komentar, atau ceritakan kendala yang kamu hadapi!&lt;/p&gt;
&lt;p&gt;Mau saya buatkan panduan lanjutan? Misalnya:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Setup Hermes + DeepSeek + Telegram Gateway&lt;/li&gt;
&lt;li&gt;Cara bikin custom skill&lt;/li&gt;
&lt;li&gt;Deploy Hermes di Mini PC (Beelink / T9 Plus)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tinggal bilang di komentar!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sumber&lt;/strong&gt;: Panduan Instalasi Hermes AI Agent oleh Noctis (@sequencetraders), 16 Mei 2026.&lt;/p&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://ngopidulur.my.id/blog/panduan-instalasi-hermes-ai-agent-2026-dari-vps-kosong-sampai-siap-pakai/&quot;&gt;https://ngopidulur.my.id/blog/panduan-instalasi-hermes-ai-agent-2026-dari-vps-kosong-sampai-siap-pakai/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>Ngopidulur</dc:creator><pubDate>Fri, 22 May 2026 14:11:00 GMT</pubDate></item><item><title>Mengapa LLM China Layak Diperhitungkan di 2026</title><link>https://ngopidulur.my.id/blog/mengapa-llm-china-layak-diperhitungkan-di-2026/</link><guid isPermaLink="true">https://ngopidulur.my.id/blog/mengapa-llm-china-layak-diperhitungkan-di-2026/</guid><description>DeepSeek V4 Flash gratis via Nous Portal, Qwen3.6 Plus (SWE-bench 78.8 + 1 juta token context). Panduan lengkap LLM China 2026: perbandingan vs Barat, teknik prompt optimal, dan cara oprek Hermes Agent. Hemat biaya AI hingga 90%!</description><content:encoded>&lt;p&gt;Banyak developer masih ragu dengan LLM asal China. Padahal data Mei 2026 membuktikan sebaliknya.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DeepSeek V4 Flash&lt;/strong&gt; bisa kamu pakai &lt;strong&gt;gratis&lt;/strong&gt;, &lt;strong&gt;Qwen3.6 Plus&lt;/strong&gt; mencetak SWE-bench 78.8 dengan context window 1 juta token, dan secara keseluruhan LLM China 10–50× lebih murah dari GPT/Claude dengan performa coding &amp;amp; reasoning yang sering lebih unggul.&lt;/p&gt;
&lt;p&gt;Artikel ini merangkum poin-poin penting dari panduan “Mengapa LLM China Layak Diperhitungkan” karya Noctis (@sequencetraders).&lt;/p&gt;
&lt;h2&gt;DeepSeek V4 Flash &amp;amp; Pro — Pilihan Utama Developer&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;DeepSeek V4 Flash&lt;/strong&gt;: MoE 284B total (13B aktif), context 1 juta token. &lt;strong&gt;Gratis via Nous Portal&lt;/strong&gt;. Harga via OpenRouter hanya $0.112 / $0.224 per 1M token.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DeepSeek V4 Pro&lt;/strong&gt;: Lebih kuat untuk coding kompleks &amp;amp; debugging. Diskon &lt;strong&gt;75%&lt;/strong&gt; sampai 31 Mei 2026.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Kelebihan utama&lt;/strong&gt;: coding superior, tool calling stabil, reasoning effort multi-level (&lt;code&gt;high&lt;/code&gt;/&lt;code&gt;xhigh&lt;/code&gt;), dan cache hit super murah.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Kekurangan&lt;/strong&gt;: text-only dan output cenderung literal.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Tips Hermes Agent&lt;/strong&gt;: Gunakan Flash sebagai main agent + delegasikan task berat ke Pro.&lt;/p&gt;
&lt;h2&gt;Qwen3.6 Plus (Alibaba) — Multimodal &amp;amp; Agentic Terbaik&lt;/h2&gt;
&lt;p&gt;Model hybrid terbaru Alibaba ini unggul di:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SWE-bench Verified &lt;strong&gt;78.8&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Context window &lt;strong&gt;1 juta token&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Native multimodal (Qwen-VL + Qwen-Audio)&lt;/li&gt;
&lt;li&gt;Tool calling &amp;amp; structured output sangat reliable&lt;/li&gt;
&lt;li&gt;Batch inference diskon 50% via DashScope&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Harga mulai ~¥0.2 per juta token (sangat kompetitif).&lt;/p&gt;
&lt;h2&gt;Perbandingan LLM China vs Barat (Mei 2026)&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspek&lt;/th&gt;
&lt;th&gt;LLM China&lt;/th&gt;
&lt;th&gt;LLM Barat&lt;/th&gt;
&lt;th&gt;Keterangan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Coding&lt;/td&gt;
&lt;td&gt;DeepSeek V4 Pro / Qwen3.6&lt;/td&gt;
&lt;td&gt;Claude 4, GPT-4o&lt;/td&gt;
&lt;td&gt;China sering unggul&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context Window&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1 juta token&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;128K–200K&lt;/td&gt;
&lt;td&gt;China jauh lebih besar&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Biaya&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0 – $0.87&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$2.50 – $15&lt;/td&gt;
&lt;td&gt;China 10-50× lebih murah&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tool Calling&lt;/td&gt;
&lt;td&gt;Stabil&lt;/td&gt;
&lt;td&gt;Sangat stabil&lt;/td&gt;
&lt;td&gt;Setara untuk agent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Refusal&lt;/td&gt;
&lt;td&gt;Hampir tidak ada&lt;/td&gt;
&lt;td&gt;Sering&lt;/td&gt;
&lt;td&gt;China lebih fleksibel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Open Weight&lt;/td&gt;
&lt;td&gt;Hampir semua&lt;/td&gt;
&lt;td&gt;Terbatas&lt;/td&gt;
&lt;td&gt;China lebih terbuka&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;Teknik Optimalisasi Prompt DeepSeek&lt;/h2&gt;
&lt;p&gt;DeepSeek &lt;strong&gt;sangat literal&lt;/strong&gt; — ikuti instruksi secara eksplisit.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Formula Optimal&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reasoning Effort: &lt;code&gt;high&lt;/code&gt; atau &lt;code&gt;xhigh&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Temperature: &lt;code&gt;0.1 – 0.3&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Prompt terstruktur + format output jelas (JSON / tabel / bullet)&lt;/li&gt;
&lt;li&gt;Gunakan Chain-of-Thought&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Contoh Prompt Efektif untuk DeepSeek V4&lt;/h2&gt;
&lt;p&gt;DeepSeek sangat &lt;strong&gt;literal&lt;/strong&gt; dan patuh terhadap instruksi. Semakin jelas, terstruktur, dan eksplisit prompt yang kamu berikan, semakin akurat hasilnya. Berikut beberapa contoh prompt yang sudah dioptimalkan untuk berbagai use case.&lt;/p&gt;
&lt;h3&gt;1. Debugging Kode (Multi-langkah)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Recommended Settings:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reasoning Effort: &lt;code&gt;high&lt;/code&gt; atau &lt;code&gt;xhigh&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Temperature: &lt;code&gt;0.1&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;Analisis kode berikut langkah demi langkah:

1. Identifikasi bug atau masalah performa
2. Jelaskan root cause secara teknis
3. Berikan solusi perbaikan (kode yang sudah diperbaiki)
4. Sarankan cara mencegah masalah serupa di masa depan

Kode:
```python
[paste kode kamu di sini]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output hanya dalam format berikut:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Bug yang ditemukan:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Root Cause:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Solusi:&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pencegahan:&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;
### 2. Code Review &amp;amp; Refactoring

**Recommended Settings:**
- Reasoning Effort: `high`
- Temperature: `0.2`

```markdown
Lakukan code review pada kode di bawah ini dengan standar berikut:
- Keamanan
- Performa
- Readability
- Best practice modern

Kode:
```javascript
[paste kode]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output harus dalam format markdown table dengan kolom:
| No | Issue | Severity (High/Medium/Low) | Suggestion | Refactored Code (jika ada) |&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;
### 3. Membuat Laporan / Dokumentasi Terstruktur

**Recommended Settings:**
- Reasoning Effort: `medium`
- Temperature: `0.1`

```markdown
Buat laporan analisis sistem dengan format persis seperti ini:

**Judul Laporan:** [isi sendiri]
**Tanggal:** [hari ini]
**Ringkasan Eksekutif:** (maksimal 3 kalimat)
**Temuan Utama:**
- Poin 1
- Poin 2
**Rekomendasi:**
1. ...
2. ...

Data yang dianalisis:
[paste data / log / hasil monitoring]
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;4. Membuat Spesifikasi Fitur / Internal Tool&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Recommended Settings:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reasoning Effort: &lt;code&gt;high&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Temperature: &lt;code&gt;0.3&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;Kamu adalah Senior Backend Engineer di perusahaan logistik.

Buat spesifikasi fitur &amp;quot;Warehouse Queue Management&amp;quot; dengan struktur berikut:

1. Deskripsi Singkat Fitur
2. User Stories (minimal 4)
3. API Endpoints (method, path, request body, response)
4. Database Schema (tabel + field penting)
5. Error Handling &amp;amp; Edge Cases
6. Non-Functional Requirements

Kebutuhan bisnis:
- Truk bisa antri loading/unloading
- Ada prioritas berdasarkan jenis barang
- Real-time status update
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;5. Analisis Dokumen / Codebase Panjang&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Recommended Settings:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reasoning Effort: &lt;code&gt;high&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Temperature: &lt;code&gt;0.1&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;Baca dan analisis seluruh konteks yang diberikan.

Tugas:
1. Buat ringkasan arsitektur keseluruhan (maksimal 5 poin)
2. Identifikasi 3 modul/file yang paling kompleks
3. Sarankan 3 improvement prioritas tinggi beserta alasannya

Setelah selesai, tanyakan bagian mana yang ingin saya dalami lebih lanjut.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;6. Membuat Skill untuk Hermes Agent&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Recommended Settings:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reasoning Effort: &lt;code&gt;high&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Temperature: &lt;code&gt;0.2&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;Buat skill baru untuk Hermes Agent bernama &amp;quot;generate-kaizen-report&amp;quot;.

Skill ini harus:
- Menerima input: nama proyek, tanggal, daftar improvement
- Menghasilkan laporan Kaizen dalam format markdown yang rapi
- Otomatis menambahkan section: Latar Belakang, Tindakan, Hasil, Rekomendasi Lanjutan
- Gunakan bahasa Indonesia formal

Berikan struktur file + contoh pemanggilan skill-nya.
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;7. Prompt Harian (Simple tapi Tetap Terstruktur)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Recommended Settings:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reasoning Effort: &lt;code&gt;low&lt;/code&gt; atau &lt;code&gt;medium&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Temperature: &lt;code&gt;0.1&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;Ekstrak semua action item dari meeting notes di bawah ini.

Format output:
- [ ] Task description - Owner - Deadline (jika ada)

Meeting Notes:
[paste notes]
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Cara Oprek Hermes Agent dengan Model China&lt;/h2&gt;
&lt;p&gt;8 titik yang bisa kamu modifikasi:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Reasoning Effort&lt;/strong&gt; — &lt;code&gt;high/xhigh&lt;/code&gt; untuk coding &amp;amp; OSINT&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Personality&lt;/strong&gt; — Buat custom via memory&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Max Iterations&lt;/strong&gt; — Naikkan ke 90 untuk task berat&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Delegation&lt;/strong&gt; — Main agent Flash + sub-agent Pro/Qwen&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MCP Servers&lt;/strong&gt; — Tambah tool eksternal&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Checkpoints&lt;/strong&gt; — Aktifkan auto snapshot + rollback&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Profiles&lt;/strong&gt; — Pisah: coding, osint, writing&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Skills&lt;/strong&gt; — Buat skill reusable&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Kombinasi terbaik&lt;/strong&gt;: Profile terpisah + Reasoning high + Delegasi + Checkpoints aktif.&lt;/p&gt;
&lt;h2&gt;Kapan Pakai Model Apa?&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;th&gt;Rekomendasi Utama&lt;/th&gt;
&lt;th&gt;Alternatif&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Coding &amp;amp; Debugging&lt;/td&gt;
&lt;td&gt;DeepSeek V4 Pro&lt;/td&gt;
&lt;td&gt;DeepSeek V4 Flash&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agent Workflow&lt;/td&gt;
&lt;td&gt;Qwen3.6 Plus / DeepSeek&lt;/td&gt;
&lt;td&gt;MiniMax M2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dokumen Panjang&lt;/td&gt;
&lt;td&gt;Qwen3.6 Plus / DeepSeek V4&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multimodal (Vision)&lt;/td&gt;
&lt;td&gt;Qwen-VL&lt;/td&gt;
&lt;td&gt;Gemini 2.5&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Budget Minimal&lt;/td&gt;
&lt;td&gt;DeepSeek V4 Flash (gratis)&lt;/td&gt;
&lt;td&gt;Qwen batch&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OSINT / Research&lt;/td&gt;
&lt;td&gt;DeepSeek (minim refusal)&lt;/td&gt;
&lt;td&gt;Qwen&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;Strategi Hybrid Hemat&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;70% task → DeepSeek V4 Flash (gratis)&lt;/li&gt;
&lt;li&gt;Coding berat → DeepSeek V4 Pro&lt;/li&gt;
&lt;li&gt;Agent + Multimodal → Qwen3.6 Plus&lt;/li&gt;
&lt;li&gt;Vision → Gemini&lt;/li&gt;
&lt;li&gt;Creative writing → Claude/GPT (hanya kalau perlu)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Kesimpulan&lt;/h2&gt;
&lt;p&gt;LLM China 2026 bukan lagi sekadar alternatif murah. Mereka adalah tools yang sangat kompetitif, terutama untuk coding, reasoning, dan workflow agentik.&lt;/p&gt;
&lt;p&gt;Dengan strategi hybrid DeepSeek + Qwen + Gemini, kamu bisa menekan biaya AI bulanan &lt;strong&gt;hingga 90%&lt;/strong&gt; tanpa mengorbankan kualitas.&lt;/p&gt;
&lt;p&gt;Sudah coba DeepSeek V4 Flash atau Qwen3.6 Plus?&lt;br&gt;Share pengalamanmu di komentar atau ceritakan use case kamu — saya bisa bantu buatkan prompt yang sudah dioptimasi.&lt;/p&gt;
&lt;p&gt;Mau versi prompt DeepSeek untuk task spesifik (internal tool, analisis codebase, atau automation)? Langsung tulis di komentar!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Sumber&lt;/strong&gt;: Panduan “Mengapa LLM China Layak Diperhitungkan” oleh Noctis (@sequencetraders), Mei 2026. Data dari OpenRouter &amp;amp; platform resmi per 16 Mei 2026.&lt;/p&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://ngopidulur.my.id/blog/mengapa-llm-china-layak-diperhitungkan-di-2026/&quot;&gt;https://ngopidulur.my.id/blog/mengapa-llm-china-layak-diperhitungkan-di-2026/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>Ngopidulur</dc:creator><pubDate>Fri, 22 May 2026 13:47:00 GMT</pubDate></item><item><title>Ngopidulur Astro Blog Doc</title><link>https://ngopidulur.my.id/blog/ngopidulur-astro-blog-doc/</link><guid isPermaLink="true">https://ngopidulur.my.id/blog/ngopidulur-astro-blog-doc/</guid><description>Dokumentasi Projek blog ngopidulur.my.id yang di build dengan Astro</description><content:encoded>&lt;h1&gt;Dokumentasi Project: ngopidulur-astro&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;Blog pribadi statis menggunakan Frosti theme + Astro 6 + Decap CMS&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2&gt;Daftar Isi&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#overview&quot;&gt;Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#tech-stack&quot;&gt;Tech Stack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#struktur-project&quot;&gt;Struktur Project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#konfigurasi&quot;&gt;Konfigurasi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#content-management-decap-cms&quot;&gt;Content Management (Decap CMS)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#menulis-artikel&quot;&gt;Menulis Artikel&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#development&quot;&gt;Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#deployment&quot;&gt;Deployment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#perubahan-yang-dilakukan&quot;&gt;Perubahan yang Dilakukan&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#troubleshooting&quot;&gt;Troubleshooting&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Overview&lt;/h2&gt;
&lt;p&gt;Project ini adalah blog pribadi statis yang dibangun menggunakan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/EveSunMaple/Frosti&quot;&gt;Frosti&lt;/a&gt;&lt;/strong&gt; v3.3.3 — template blog untuk Astro&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://astro.build/&quot;&gt;Astro&lt;/a&gt;&lt;/strong&gt; v6.3.6 — framework web untuk content-driven websites&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://decapcms.org/&quot;&gt;Decap CMS&lt;/a&gt;&lt;/strong&gt; — open-source, Git-based CMS untuk mengelola konten via browser&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Blog ini menghasilkan &lt;strong&gt;file HTML statis&lt;/strong&gt; saat di-build, sehingga sangat cepat dan bisa di-deploy di hosting manapun.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Tech Stack&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Teknologi&lt;/th&gt;
&lt;th&gt;Versi&lt;/th&gt;
&lt;th&gt;Fungsi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Astro&lt;/td&gt;
&lt;td&gt;^6.3.6&lt;/td&gt;
&lt;td&gt;Framework utama&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tailwind CSS&lt;/td&gt;
&lt;td&gt;^3.4.18&lt;/td&gt;
&lt;td&gt;Styling utility-first&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;daisyUI&lt;/td&gt;
&lt;td&gt;^4.12.24&lt;/td&gt;
&lt;td&gt;Komponen UI (tema light/dark)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MDX&lt;/td&gt;
&lt;td&gt;^5.0.6&lt;/td&gt;
&lt;td&gt;Markdown + komponen interaktif&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Expressive Code&lt;/td&gt;
&lt;td&gt;^0.41.3&lt;/td&gt;
&lt;td&gt;Syntax highlighting code blocks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;KaTeX&lt;/td&gt;
&lt;td&gt;^0.16.25&lt;/td&gt;
&lt;td&gt;Render rumus matematika&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pagefind&lt;/td&gt;
&lt;td&gt;^1.4.0&lt;/td&gt;
&lt;td&gt;Search engine statis (client-side)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;@astrojs/rss&lt;/td&gt;
&lt;td&gt;^4.0.18&lt;/td&gt;
&lt;td&gt;Generate RSS feed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;@astrojs/sitemap&lt;/td&gt;
&lt;td&gt;^3.7.2&lt;/td&gt;
&lt;td&gt;Generate sitemap.xml&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Decap CMS&lt;/td&gt;
&lt;td&gt;3.3.3 (pinned, lokal)&lt;/td&gt;
&lt;td&gt;Admin UI untuk kelola konten&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Biome&lt;/td&gt;
&lt;td&gt;^2.3.8&lt;/td&gt;
&lt;td&gt;Linter &amp;amp; formatter&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sharp&lt;/td&gt;
&lt;td&gt;^0.34.5&lt;/td&gt;
&lt;td&gt;Image optimization&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Struktur Project&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;ngopidulur-astro/
├── public/                    # File statis (langsung di-serve)
│   ├── admin/                 # Decap CMS
│   │   ├── config.yml         # Konfigurasi CMS (collections, fields)
│   │   ├── index.html         # Entry point CMS
│   │   └── decap-cms.js       # Decap CMS bundle (pinned 3.3.3, lokal)
│   ├── image/                 # Gambar untuk artikel
│   ├── pagefind/              # Search index (auto-generated dari `pnpm search:index`)
│   ├── favicon.ico
│   ├── logo.png
│   ├── profile.png            # Avatar user
│   └── profile2.png           # Logo hero homepage
├── src/
│   ├── components/            # Komponen Astro
│   │   ├── mdx/               # Komponen untuk MDX (alerts, collapse, dll)
│   │   ├── sidebar/           # Sidebar components (profile, search, TOC)
│   │   ├── widgets/           # Widget (pagination, theme toggle, dll)
│   │   ├── Header.astro
│   │   ├── Footer.astro
│   │   ├── Navbar.astro
│   │   ├── PostCard.astro
│   │   └── Sidebar.astro
│   ├── content/
│   │   └── blog/              # Artikel blog (Markdown/MDX)
│   ├── i18n/                  # Internationalization
│   │   └── translations.yaml  # Teks UI multi-bahasa
│   ├── interface/             # TypeScript interfaces
│   ├── integration/           # Custom Astro integrations
│   ├── layouts/
│   │   └── BaseLayout.astro   # Layout utama
│   ├── pages/                 # Halaman-halaman situs
│   │   ├── blog/              # Blog routes (list, detail, category, tag)
│   │   ├── og/                # Auto-generated OG images
│   │   ├── admin.astro        # Decap CMS admin page
│   │   ├── index.astro        # Homepage
│   │   ├── about.astro        # About page
│   │   ├── project.astro      # Project page
│   │   ├── rss.xml.ts         # RSS feed
│   │   └── robots.txt.ts      # Robots.txt
│   ├── plugins/
│   │   └── remark-reading-time.ts  # Plugin estimasi waktu baca
│   ├── styles/
│   │   ├── global.scss        # Global styles
│   │   └── waline.scss        # Comment system styles
│   ├── utils/                 # Utility functions
│   ├── config.ts              # Membaca frosti.config.yaml
│   └── content.config.ts      # Definisi content collections
├── frosti.config.yaml         # KONFIGURASI UTAMA SITUS
├── astro.config.mjs           # Konfigurasi Astro
├── tsconfig.json              # TypeScript config (exclude pagefind &amp;amp; decap-cms.js)
├── biome.json                 # Linter/formatter config
├── package.json               # Dependencies &amp;amp; scripts
└── dist/                      # Output build (jangan edit manual)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;Konfigurasi&lt;/h2&gt;
&lt;h3&gt;File Konfigurasi Utama: &lt;code&gt;frosti.config.yaml&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Semua pengaturan situs ada di file ini:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;site:
  tab: Frosti              # Teks di browser tab
  title: 💠 Frosti         # Judul situs
  description: ...         # Deskripsi SEO
  language: en             # Bahasa (en/zh/dll)
  favicon: /favicon.ico
  theme:
    light: winter          # Tema terang (daisyUI)
    dark: dracula          # Tema gelap (daisyUI)
    code: github-dark      # Tema code block (Shiki)
  date_format: ddd MMM DD YYYY
  blog:
    pageSize: 8            # Artikel per halaman
  menu: [...]              # Navigasi menu sidebar/navbar

user:
  name: Rifky Awalul Huda  # Nama yang ditampilkan
  site: &amp;quot;https://...&amp;quot;       # URL situs
  avatar: /profile.png      # Path avatar
  sidebar:
    social: [...]           # Social links di sidebar
  footer:
    social: [...]           # Social links di footer
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Penting:&lt;/strong&gt; Setelah edit &lt;code&gt;frosti.config.yaml&lt;/code&gt;, restart dev server (&lt;code&gt;Ctrl+C&lt;/code&gt; lalu &lt;code&gt;npm run dev&lt;/code&gt; lagi) karena file ini dibaca via &lt;code&gt;fs.readFileSync&lt;/code&gt; yang tidak hot-reload.&lt;/p&gt;
&lt;h3&gt;Catatan Konfigurasi yang Sedang Dipakai&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Menu &lt;code&gt;Friend&lt;/code&gt;, &lt;code&gt;Contact&lt;/code&gt;, dan &lt;code&gt;Examples&lt;/code&gt; sudah dihapus dari &lt;code&gt;site.menu&lt;/code&gt;. Halaman &lt;code&gt;friend.astro&lt;/code&gt; juga dihapus dari codebase.&lt;/li&gt;
&lt;li&gt;Kategori sidebar yang aktif: &lt;code&gt;Tulisan Random&lt;/code&gt;, &lt;code&gt;Teknologi&lt;/code&gt;, &lt;code&gt;Documentation&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Social icon sidebar dan footer saat ini memakai Facebook, GitHub, LinkedIn, dan X.&lt;/li&gt;
&lt;li&gt;Format icon yang benar mengikuti pola &lt;code&gt;collection:name&lt;/code&gt;, misalnya &lt;code&gt;ri:linkedin-line&lt;/code&gt; atau &lt;code&gt;ri:facebook-line&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;user.site&lt;/code&gt; saat ini mengarah ke profil LinkedIn.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Astro Config: &lt;code&gt;astro.config.mjs&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Integrasi yang aktif:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;expressiveCode&lt;/code&gt; — syntax highlighting&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mdx&lt;/code&gt; — support file .mdx&lt;/li&gt;
&lt;li&gt;&lt;code&gt;icon&lt;/code&gt; — icon library (Iconify)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;terser&lt;/code&gt; — JS minification&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sitemap&lt;/code&gt; — auto-generate sitemap.xml&lt;/li&gt;
&lt;li&gt;&lt;code&gt;playformCompress&lt;/code&gt; — compress output&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Markdown plugins:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;remarkMath&lt;/code&gt; + &lt;code&gt;rehypeKatex&lt;/code&gt; — rumus matematika&lt;/li&gt;
&lt;li&gt;&lt;code&gt;remarkReadingTime&lt;/code&gt; — estimasi waktu baca&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rehypeExternalLinks&lt;/code&gt; — tambah ↗ di link eksternal&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Content Management (Decap CMS)&lt;/h2&gt;
&lt;h3&gt;Apa itu Decap CMS?&lt;/h3&gt;
&lt;p&gt;Decap CMS adalah admin UI berbasis web yang memungkinkan kamu membuat dan mengedit artikel blog langsung dari browser, tanpa perlu buka code editor. Perubahan disimpan langsung sebagai file Markdown di repository.&lt;/p&gt;
&lt;h3&gt;Cara Akses (Lokal)&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Buka terminal pertama, jalankan proxy server:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npx decap-server
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Buka terminal kedua, jalankan dev server:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Buka browser: &lt;strong&gt;&lt;a href=&quot;http://localhost:4321/admin&quot;&gt;http://localhost:4321/admin&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Langsung masuk tanpa login (local mode)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Konfigurasi CMS: &lt;code&gt;public/admin/config.yml&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;backend:
  name: git-gateway       # Backend untuk production (Netlify)
  branch: main

local_backend: true       # Enable untuk development lokal (tanpa auth)

media_folder: &amp;quot;public/image&amp;quot;   # Folder upload gambar
public_folder: &amp;quot;/image&amp;quot;        # Path gambar di situs

collections:
  - name: &amp;quot;blog&amp;quot;
    label: &amp;quot;Blog Posts&amp;quot;
    folder: &amp;quot;src/content/blog&amp;quot;
    create: true
    fields:
      - title (string, required)
      - description (string, required)
      - pubDate (datetime, required)
      - updated (datetime, optional)
      - image (image, optional)
      - badge (string, optional) — set &amp;quot;Pin&amp;quot; untuk pin artikel
      - draft (boolean, optional) — true = tidak tampil di list
      - categories (list, optional)
      - tags (list, optional)
      - body (markdown)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Catatan: File .md vs .mdx di CMS&lt;/h3&gt;
&lt;p&gt;Decap CMS hanya menampilkan file dengan ekstensi &lt;code&gt;.md&lt;/code&gt; (dikonfigurasi via &lt;code&gt;extension: &amp;quot;md&amp;quot;&lt;/code&gt; di &lt;code&gt;config.yml&lt;/code&gt;). File &lt;code&gt;.mdx&lt;/code&gt; &lt;strong&gt;tidak muncul&lt;/strong&gt; di CMS dan memang sengaja dikelola terpisah.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Konvensi:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;File &lt;code&gt;.md&lt;/code&gt;&lt;/strong&gt; — Artikel biasa, dikelola via Decap CMS (&lt;code&gt;/admin&lt;/code&gt;) atau langsung edit file.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;File &lt;code&gt;.mdx&lt;/code&gt;&lt;/strong&gt; — Artikel yang menggunakan komponen interaktif (import custom components seperti &lt;code&gt;&amp;lt;Collapse&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;Info&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;LinkCard&amp;gt;&lt;/code&gt;, dll). Dikelola langsung via code editor karena Decap CMS tidak bisa merender syntax JSX/import.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Kenapa tidak membuat collection kedua untuk MDX?&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Di sisi Astro, semua post (&lt;code&gt;.md&lt;/code&gt; dan &lt;code&gt;.mdx&lt;/code&gt;) sudah satu content collection &lt;code&gt;blog&lt;/code&gt;. Memisahkan di CMS membingungkan.&lt;/li&gt;
&lt;li&gt;Decap CMS tetap tidak bisa mengedit syntax MDX (import/JSX) dengan benar.&lt;/li&gt;
&lt;li&gt;Duplikasi konfigurasi fields tanpa manfaat nyata.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Jadi jika ada post yang hanya muncul di situs tapi tidak di CMS, kemungkinan besar itu file &lt;code&gt;.mdx&lt;/code&gt; — dan itu memang by design.&lt;/p&gt;
&lt;h3&gt;Catatan Production&lt;/h3&gt;
&lt;p&gt;Untuk deploy dengan Decap CMS aktif:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Deploy ke &lt;strong&gt;Netlify&lt;/strong&gt; dan aktifkan &lt;strong&gt;Netlify Identity&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Hapus/comment &lt;code&gt;local_backend: true&lt;/code&gt; di config.yml&lt;/li&gt;
&lt;li&gt;User bisa login via email di &lt;code&gt;/admin&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Menulis Artikel&lt;/h2&gt;
&lt;h3&gt;Via Decap CMS (Recommended)&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Buka &lt;code&gt;/admin&lt;/code&gt; di browser&lt;/li&gt;
&lt;li&gt;Klik &amp;quot;Blog Posts&amp;quot; → &amp;quot;New Blog Post&amp;quot;&lt;/li&gt;
&lt;li&gt;Isi field-field yang tersedia&lt;/li&gt;
&lt;li&gt;Klik &amp;quot;Publish&amp;quot;&lt;/li&gt;
&lt;li&gt;File Markdown otomatis dibuat di &lt;code&gt;src/content/blog/&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Via File Manual&lt;/h3&gt;
&lt;p&gt;Buat file &lt;code&gt;.md&lt;/code&gt; di &lt;code&gt;src/content/blog/&lt;/code&gt; dengan format:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;---
title: &amp;quot;Judul Artikel&amp;quot;
description: &amp;quot;Deskripsi singkat&amp;quot;
pubDate: 2025-01-15
image: &amp;quot;/image/cover.jpg&amp;quot;
categories:
  - Documentation
tags:
  - astro
  - tutorial
draft: false
---

Isi artikel di sini menggunakan Markdown...
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Frontmatter Fields&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Tipe&lt;/th&gt;
&lt;th&gt;Wajib&lt;/th&gt;
&lt;th&gt;Keterangan&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;title&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Judul artikel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;description&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Deskripsi untuk SEO&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pubDate&lt;/td&gt;
&lt;td&gt;date&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Tanggal publikasi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;updated&lt;/td&gt;
&lt;td&gt;date&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Tanggal update terakhir&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;image&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Path cover image&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;badge&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Set &amp;quot;Pin&amp;quot; untuk pin di atas&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;draft&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;true = hidden dari list&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;categories&lt;/td&gt;
&lt;td&gt;string[]&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Kategori artikel&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tags&lt;/td&gt;
&lt;td&gt;string[]&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Tag artikel&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;hr&gt;
&lt;h2&gt;Development&lt;/h2&gt;
&lt;h3&gt;Prerequisites&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Node.js &amp;gt;= 18&lt;/li&gt;
&lt;li&gt;pnpm (recommended) atau npm&lt;/li&gt;
&lt;li&gt;Untuk pnpm v10+: jalankan &lt;code&gt;pnpm approve-builds&lt;/code&gt; saat install pertama untuk approve build scripts dari &lt;code&gt;esbuild&lt;/code&gt;, &lt;code&gt;sharp&lt;/code&gt;, &lt;code&gt;swup&lt;/code&gt;, dan &lt;code&gt;@parcel/watcher&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Commands&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;Project ini pakai pnpm. Semua command bisa dijalankan via &lt;code&gt;pnpm &amp;lt;script&amp;gt;&lt;/code&gt;. Kalau pakai npm, ganti &lt;code&gt;pnpm&lt;/code&gt; dengan &lt;code&gt;npm run&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;# Running Decap Server (terminal 1)
npx decap-server
# Akses CMS: http://localhost:4321/admin

# Install dependencies
pnpm install

# Development server (http://localhost:4321) — terminal 2
pnpm dev

# Build untuk production (build + generate Pagefind index)
pnpm build

# Preview build result
pnpm preview

# Type checking
pnpm check

# Linting (Biome)
pnpm lint

# Format code (Biome)
pnpm format

# Generate search index lalu copy ke public/
pnpm search:index
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Pertama Kali Setup&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;pnpm install
pnpm approve-builds        # Approve build scripts (pilih semua dengan &amp;#39;a&amp;#39;)
pnpm search:index          # Generate Pagefind search index
pnpm dev                   # Start dev server
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Workflow Harian&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;pnpm dev                   # Start dev server
# Edit artikel via /admin atau langsung di file
# Ctrl+C untuk stop
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Setelah Tambah/Edit Artikel&lt;/h3&gt;
&lt;p&gt;Search index Pagefind tidak auto-update saat dev. Setelah konten berubah signifikan, regenerate index:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;pnpm build
npx cpy-cli &amp;quot;dist/pagefind/**&amp;quot; &amp;quot;public/pagefind&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;Deployment&lt;/h2&gt;
&lt;h3&gt;Opsi 1: Netlify (Recommended — gratis + Decap CMS)&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Push repo ke GitHub&lt;/li&gt;
&lt;li&gt;Connect repo di &lt;a href=&quot;https://netlify.com&quot;&gt;netlify.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Build command: &lt;code&gt;npm run build&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Publish directory: &lt;code&gt;dist&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Aktifkan Netlify Identity untuk Decap CMS login&lt;/li&gt;
&lt;li&gt;Hapus &lt;code&gt;local_backend: true&lt;/code&gt; di &lt;code&gt;public/admin/config.yml&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Opsi 2: Shared Hosting / cPanel&lt;/h3&gt;
&lt;h4&gt;Persiapan sebelum build&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;Edit &lt;code&gt;frosti.config.yaml&lt;/code&gt;: ganti &lt;code&gt;user.site&lt;/code&gt; ke domain produksi (misal &lt;code&gt;https://ngopidulur.my.id&lt;/code&gt;). Pastikan ada &lt;code&gt;https://&lt;/code&gt; dan &lt;strong&gt;tanpa trailing slash&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Edit &lt;code&gt;public/admin/config.yml&lt;/code&gt;: comment baris &lt;code&gt;local_backend: true&lt;/code&gt; (&lt;code&gt;# local_backend: true&lt;/code&gt;). Decap CMS local backend cuma untuk dev.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Build dan compress&lt;/h4&gt;
&lt;p&gt;Di lokal:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;pnpm install
pnpm search:index
pnpm build
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Lalu compress isi &lt;code&gt;dist/&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-powershell&quot;&gt;Compress-Archive -Path dist\* -DestinationPath dist.zip -Force
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Upload dan extract&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Login ke cPanel → File Manager.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Navigate ke &lt;code&gt;public_html/&lt;/code&gt; (atau folder subdomain).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;PENTING — sebelum upload baru, hapus folder lama yang berpotensi konflik:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Lewat cPanel &lt;strong&gt;Terminal&lt;/strong&gt;, jalankan:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;cd ~/public_html
rm -rf blog _astro admin image og pagefind
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Kalau cPanel kamu tidak punya Terminal, hapus folder-folder ini lewat File Manager.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Upload &lt;code&gt;dist.zip&lt;/code&gt; ke &lt;code&gt;public_html/&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Extract via File Manager (atau Terminal: &lt;code&gt;unzip -o dist.zip&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hapus &lt;code&gt;dist.zip&lt;/code&gt; setelah extract sukses.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Pasang &lt;code&gt;.htaccess&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;Buat file &lt;code&gt;.htaccess&lt;/code&gt; di &lt;code&gt;public_html/&lt;/code&gt; dengan isi:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-apache&quot;&gt;RewriteEngine On

# Force HTTPS
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

# Custom 404
ErrorDocument 404 /404.html

# Pretty URLs
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+?)/?$ $1.html [L]

DirectoryIndex index.html

# Compression
&amp;lt;IfModule mod_deflate.c&amp;gt;
  AddOutputFilterByType DEFLATE text/html text/css text/javascript application/javascript application/json image/svg+xml
&amp;lt;/IfModule&amp;gt;

# Cache
&amp;lt;IfModule mod_expires.c&amp;gt;
  ExpiresActive On
  ExpiresByType image/jpeg &amp;quot;access plus 1 year&amp;quot;
  ExpiresByType image/png &amp;quot;access plus 1 year&amp;quot;
  ExpiresByType image/webp &amp;quot;access plus 1 year&amp;quot;
  ExpiresByType text/css &amp;quot;access plus 1 year&amp;quot;
  ExpiresByType application/javascript &amp;quot;access plus 1 year&amp;quot;
  ExpiresByType font/woff2 &amp;quot;access plus 1 year&amp;quot;
&amp;lt;/IfModule&amp;gt;

# Security
&amp;lt;IfModule mod_headers.c&amp;gt;
  Header set X-Content-Type-Options &amp;quot;nosniff&amp;quot;
  Header set X-Frame-Options &amp;quot;SAMEORIGIN&amp;quot;
  Header set Referrer-Policy &amp;quot;strict-origin-when-cross-origin&amp;quot;
&amp;lt;/IfModule&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Catatan penting&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;⚠️ Decap CMS &lt;code&gt;/admin&lt;/code&gt; tidak akan berfungsi penuh di shared hosting tanpa Netlify Identity atau OAuth proxy. Untuk update konten, edit di lokal lalu re-deploy.&lt;/li&gt;
&lt;li&gt;Setelah deploy, test halaman kategori (&lt;code&gt;/blog/category/Teknologi&lt;/code&gt;) dan tag (&lt;code&gt;/blog/tag/...&lt;/code&gt;). Kalau muncul 404, baca section Troubleshooting di bawah.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Opsi 3: Vercel / Cloudflare Pages&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Connect GitHub repo&lt;/li&gt;
&lt;li&gt;Build command: &lt;code&gt;npm run build&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Output directory: &lt;code&gt;dist&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Untuk Decap CMS, perlu setup &lt;a href=&quot;https://decapcms.org/docs/external-oauth-clients/&quot;&gt;external OAuth client&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Perubahan yang Dilakukan&lt;/h2&gt;
&lt;h3&gt;Integrasi Decap CMS (Mei 2025)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;File baru:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;public/admin/config.yml&lt;/code&gt; — Konfigurasi Decap CMS dengan field mapping ke blog collection&lt;/li&gt;
&lt;li&gt;&lt;code&gt;public/admin/index.html&lt;/code&gt; — Entry point HTML untuk Decap CMS (CDN)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src/pages/admin.astro&lt;/code&gt; — Astro page route untuk &lt;code&gt;/admin&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Tujuan:&lt;/strong&gt; Menambahkan admin UI berbasis web untuk mengelola artikel blog tanpa perlu edit file Markdown secara manual.&lt;/p&gt;
&lt;h3&gt;Percobaan CMS yang Tidak Jadi&lt;/h3&gt;
&lt;p&gt;Selama proses setup, beberapa CMS dicoba tapi tidak kompatibel:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Storyblok&lt;/strong&gt; — Berbayar (tidak ada free tier yang mudah diakses)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keystatic&lt;/strong&gt; — Belum support Astro 6 (peer dependency conflict, crash di production)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Kedua percobaan ini sudah di-revert sepenuhnya. Tidak ada sisa kode dari Storyblok atau Keystatic di project.&lt;/p&gt;
&lt;h3&gt;Penyesuaian UI dan Konfigurasi (Mei 2026)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Homepage&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;src/pages/index.astro&lt;/code&gt;: section &lt;code&gt;Features&lt;/code&gt; diganti menjadi &lt;code&gt;Blog Terbaru&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Homepage sekarang menampilkan maksimal 6 post terbaru dari collection &lt;code&gt;blog&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Layout daftar post di homepage diubah menjadi grid card ringkas 3 kolom di desktop dan tetap responsif di layar kecil.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;About page&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;src/pages/about.astro&lt;/code&gt;: tombol sosial pertama di section profil diubah dari GitHub menjadi LinkedIn.&lt;/li&gt;
&lt;li&gt;Link sosial yang dipakai di halaman About sudah menyesuaikan profil LinkedIn dan Facebook terbaru.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Navigasi&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;frosti.config.yaml&lt;/code&gt;: menu &lt;code&gt;Friend&lt;/code&gt; dan &lt;code&gt;Contact&lt;/code&gt; dihapus dari &lt;code&gt;site.menu&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Halaman &lt;code&gt;src/pages/friend.astro&lt;/code&gt; masih ada di codebase, tetapi tidak lagi muncul di navigasi utama.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Footer dan social icons&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;src/components/Footer.astro&lt;/code&gt; tetap menjadi komponen footer utama yang dipakai oleh &lt;code&gt;src/layouts/BaseLayout.astro&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Data social footer tetap dibaca dari &lt;code&gt;frosti.config.yaml&lt;/code&gt; melalui &lt;code&gt;src/config.ts&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Icon &lt;code&gt;ri:cup-line&lt;/code&gt; di konfigurasi social footer diganti menjadi &lt;code&gt;ri:facebook-line&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Icon LinkedIn di konfigurasi memakai format yang benar: &lt;code&gt;ri:linkedin-line&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Maintenance &amp;amp; Code Quality (Mei 2026)&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Update dependency untuk kompatibilitas Astro 6&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@astrojs/rss&lt;/code&gt; di-update ke &lt;code&gt;^4.0.18&lt;/code&gt; (fix error &lt;code&gt;z.function().returns is not a function&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@astrojs/sitemap&lt;/code&gt; di-update ke &lt;code&gt;^3.7.2&lt;/code&gt; (fix error &lt;code&gt;Cannot read properties of undefined (reading &amp;#39;reduce&amp;#39;)&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Fix prioritas High dari hasil code review&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Decap CMS pinned &amp;amp; lokal&lt;/strong&gt;: dependency dari CDN (&lt;code&gt;https://unpkg.com/decap-cms@^3.3.3&lt;/code&gt;) di &lt;code&gt;src/pages/admin.astro&lt;/code&gt; dan &lt;code&gt;public/admin/index.html&lt;/code&gt; diganti ke file lokal &lt;code&gt;public/admin/decap-cms.js&lt;/code&gt; (versi 3.3.3 di-pin). Mencegah breaking change upstream dan mengurangi attack surface.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Race condition di search page&lt;/strong&gt;: &lt;code&gt;src/pages/blog/search.astro&lt;/code&gt; di-refactor agar tidak append script tag duplikat saat user navigate via View Transitions. Ada pengecekan &lt;code&gt;window.PagefindUI&lt;/code&gt; dan attribute &lt;code&gt;data-pagefind-loader&lt;/code&gt; untuk reuse instance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A11y/SEO homepage&lt;/strong&gt;: &lt;code&gt;src/pages/index.astro&lt;/code&gt; heading &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; ditambah lagi (&lt;code&gt;sr-only&lt;/code&gt; agar tetap visual-friendly), gambar hero &lt;code&gt;profile2.png&lt;/code&gt; ditambah &lt;code&gt;width&lt;/code&gt;, &lt;code&gt;height&lt;/code&gt;, dan &lt;code&gt;fetchpriority=&amp;quot;high&amp;quot;&lt;/code&gt; untuk cegah CLS dan prioritaskan loading.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Schema content collection lebih toleran&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;src/content.config.ts&lt;/code&gt;: field &lt;code&gt;updated&lt;/code&gt; sekarang menerima string kosong &lt;code&gt;&amp;quot;&amp;quot;&lt;/code&gt; dari Decap CMS dan otomatis convert ke &lt;code&gt;undefined&lt;/code&gt;. Mencegah error &lt;code&gt;Expected type &amp;quot;date&amp;quot;, received &amp;quot;object&amp;quot;&lt;/code&gt; saat post baru dibuat lewat CMS tanpa mengisi tanggal update.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;TypeScript config&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tsconfig.json&lt;/code&gt;: tambah &lt;code&gt;exclude&lt;/code&gt; untuk &lt;code&gt;public/admin/decap-cms.js&lt;/code&gt; (5.3 MB minified) dan &lt;code&gt;public/pagefind/**&lt;/code&gt;. Mencegah &lt;code&gt;astro check&lt;/code&gt; out-of-memory saat scan vendor files.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cleanup file tidak terpakai&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Dihapus 14 file yang sudah tidak terpakai:&lt;ul&gt;
&lt;li&gt;Static assets duplikat: &lt;code&gt;favicon1.ico&lt;/code&gt;, &lt;code&gt;profile1.png&lt;/code&gt;, &lt;code&gt;image/l.png&lt;/code&gt;, &lt;code&gt;image/r.png&lt;/code&gt;, &lt;code&gt;image/image2.jpg&lt;/code&gt;, &lt;code&gt;image/uploaded-screenshot.png&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Frosti updater scripts: &lt;code&gt;frosti.update.sh&lt;/code&gt;, &lt;code&gt;.updateignore&lt;/code&gt;, &lt;code&gt;src/i18n/en.sh&lt;/code&gt;, &lt;code&gt;src/i18n/zh.sh&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Halaman friend dan komponen pendukungnya: &lt;code&gt;src/pages/friend.astro&lt;/code&gt;, &lt;code&gt;src/components/mdx/FriendCard.astro&lt;/code&gt;, &lt;code&gt;src/components/mdx/Showcase.astro&lt;/code&gt;, &lt;code&gt;src/components/mdx/LinkCard.astro&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Setup MCP Astro Docs (global Kiro)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;File &lt;code&gt;~/.kiro/settings/mcp.json&lt;/code&gt; ditambah server &lt;code&gt;astro-docs&lt;/code&gt; dengan &lt;code&gt;autoApprove: [&amp;quot;search_astro_docs&amp;quot;]&lt;/code&gt;. AI agent sekarang punya akses ke dokumentasi Astro versi terbaru via MCP tanpa konfirmasi manual.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Troubleshooting&lt;/h2&gt;
&lt;h3&gt;Config tidak update setelah edit &lt;code&gt;frosti.config.yaml&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Penyebab:&lt;/strong&gt; File dibaca via &lt;code&gt;fs.readFileSync&lt;/code&gt; saat module di-import, tidak terdeteksi oleh Vite hot-reload.
&lt;strong&gt;Solusi:&lt;/strong&gt; Restart dev server (Ctrl+C → &lt;code&gt;npm run dev&lt;/code&gt;).&lt;/p&gt;
&lt;h3&gt;Decap CMS minta login di localhost&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Penyebab:&lt;/strong&gt; &lt;code&gt;local_backend: true&lt;/code&gt; belum di-set, atau &lt;code&gt;npx decap-server&lt;/code&gt; belum jalan.
&lt;strong&gt;Solusi:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Pastikan &lt;code&gt;local_backend: true&lt;/code&gt; ada di &lt;code&gt;public/admin/config.yml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Jalankan &lt;code&gt;npx decap-server&lt;/code&gt; di terminal terpisah sebelum akses &lt;code&gt;/admin&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;&lt;code&gt;/admin&lt;/code&gt; page not found&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Penyebab:&lt;/strong&gt; Astro dev server tidak auto-resolve &lt;code&gt;index.html&lt;/code&gt; di subfolder &lt;code&gt;public/&lt;/code&gt;.
&lt;strong&gt;Solusi:&lt;/strong&gt; Gunakan route &lt;code&gt;src/pages/admin.astro&lt;/code&gt; (sudah dibuat). Akses via &lt;code&gt;http://localhost:4321/admin&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Build error setelah install package baru&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Solusi:&lt;/strong&gt; Jalankan &lt;code&gt;npm run check&lt;/code&gt; untuk melihat error. Pastikan &lt;code&gt;astro.config.mjs&lt;/code&gt; tidak ada import yang broken.&lt;/p&gt;
&lt;h3&gt;Search tidak berfungsi&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Penyebab:&lt;/strong&gt; Search index belum di-generate.
&lt;strong&gt;Solusi:&lt;/strong&gt; Jalankan &lt;code&gt;pnpm search:index&lt;/code&gt; (atau &lt;code&gt;npm run search:index&lt;/code&gt;) sebelum &lt;code&gt;pnpm dev&lt;/code&gt;. Setelah build, copy index ke &lt;code&gt;public/&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;npx cpy-cli &amp;quot;dist/pagefind/**&amp;quot; &amp;quot;public/pagefind&amp;quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Search page error: &amp;quot;Cannot import non-asset file&amp;quot;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Penyebab:&lt;/strong&gt; Pagefind UI di-import via dynamic &lt;code&gt;import()&lt;/code&gt; yang diproses Vite, padahal file ada di &lt;code&gt;public/&lt;/code&gt;.
&lt;strong&gt;Solusi:&lt;/strong&gt; Sudah di-fix. &lt;code&gt;src/pages/blog/search.astro&lt;/code&gt; sekarang load &lt;code&gt;/pagefind/pagefind-ui.js&lt;/code&gt; via &lt;code&gt;document.createElement(&amp;quot;script&amp;quot;)&lt;/code&gt; agar bypass Vite.&lt;/p&gt;
&lt;h3&gt;Decap CMS error: &amp;quot;data does not match collection schema (updated: Expected date, received object)&amp;quot;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Penyebab:&lt;/strong&gt; Decap CMS menyimpan field datetime kosong sebagai string &lt;code&gt;&amp;quot;&amp;quot;&lt;/code&gt;, sementara schema Zod lama strict.
&lt;strong&gt;Solusi:&lt;/strong&gt; Sudah di-fix di &lt;code&gt;src/content.config.ts&lt;/code&gt;. Field &lt;code&gt;updated&lt;/code&gt; sekarang menerima &lt;code&gt;&amp;quot;&amp;quot;&lt;/code&gt; dan otomatis convert ke &lt;code&gt;undefined&lt;/code&gt;. Tidak perlu action manual.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;astro check&lt;/code&gt; JavaScript heap out of memory&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Penyebab:&lt;/strong&gt; Astro mencoba scan file vendor besar di &lt;code&gt;public/&lt;/code&gt; (&lt;code&gt;decap-cms.js&lt;/code&gt;, file Pagefind).
&lt;strong&gt;Solusi:&lt;/strong&gt; Sudah di-fix di &lt;code&gt;tsconfig.json&lt;/code&gt; via &lt;code&gt;exclude&lt;/code&gt;. Kalau muncul lagi setelah tambah file vendor baru, tambahkan ke &lt;code&gt;exclude&lt;/code&gt; array.&lt;/p&gt;
&lt;h3&gt;Build error: &lt;code&gt;z.function(...).returns is not a function&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Penyebab:&lt;/strong&gt; &lt;code&gt;@astrojs/rss&lt;/code&gt; versi lama tidak kompatibel dengan Zod yang dibawa Astro 6.
&lt;strong&gt;Solusi:&lt;/strong&gt; Sudah di-fix dengan update ke &lt;code&gt;@astrojs/rss@^4.0.18&lt;/code&gt;. Kalau ketemu di package lain, update ke versi terbaru.&lt;/p&gt;
&lt;h3&gt;pnpm install gagal: &lt;code&gt;[ERR_PNPM_IGNORED_BUILDS]&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Penyebab:&lt;/strong&gt; pnpm v10+ memblokir postinstall scripts secara default.
&lt;strong&gt;Solusi:&lt;/strong&gt; Jalankan &lt;code&gt;pnpm approve-builds&lt;/code&gt;, pilih semua dengan &lt;code&gt;a&lt;/code&gt; lalu &lt;code&gt;Enter&lt;/code&gt;, lalu &lt;code&gt;pnpm install&lt;/code&gt; lagi.&lt;/p&gt;
&lt;h3&gt;Deploy cPanel: kategori atau tag muncul 404 setelah upload&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Gejala:&lt;/strong&gt; Halaman seperti &lt;code&gt;/blog/category/Teknologi&lt;/code&gt; atau &lt;code&gt;/blog/tag/php&lt;/code&gt; muncul 404, padahal halaman lain (homepage, detail post) jalan normal.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Penyebab:&lt;/strong&gt; Saat extract &lt;code&gt;dist.zip&lt;/code&gt; di cPanel, folder seperti &lt;code&gt;blog/category/&lt;/code&gt;, &lt;code&gt;blog/tag/&lt;/code&gt; sudah ada dari deploy sebelumnya tapi dengan permission/ownership yang rusak. Extract membuat folder tujuan tapi gagal extract &lt;code&gt;index.html&lt;/code&gt; di dalamnya. Folder kosong = 404.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Indikator:&lt;/strong&gt; Saat extract via Terminal cPanel muncul error seperti:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;checkdir error: cannot create blog/category/Teknologi
Permission denied
unable to process blog/category/Teknologi/index.html.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Solusi:&lt;/strong&gt; Hapus folder bermasalah dulu sebelum re-extract.&lt;/p&gt;
&lt;p&gt;Via cPanel &lt;strong&gt;Terminal&lt;/strong&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;cd ~/public_html
rm -rf blog/category blog/tag
# atau lebih bersih: rm -rf blog
unzip -o dist.zip
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Kalau &lt;code&gt;rm -rf&lt;/code&gt; juga gagal dengan permission denied:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sh&quot;&gt;chmod -R 755 blog/category blog/tag 2&amp;gt;/dev/null
rm -rf blog/category blog/tag
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Kalau tetap denied, kontak support hosting untuk reset ownership folder ke akun cPanel kamu.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pencegahan:&lt;/strong&gt; Sebelum upload deploy baru, &lt;strong&gt;selalu hapus folder lama dulu&lt;/strong&gt;. Jangan extract overwrite di atas folder lama.&lt;/p&gt;
&lt;h3&gt;Deploy cPanel: situs blank putih atau asset tidak load&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Penyebab umum:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;index.html&lt;/code&gt; tidak ada di root &lt;code&gt;public_html/&lt;/code&gt; (mungkin nested di &lt;code&gt;public_html/dist/&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Folder &lt;code&gt;_astro/&lt;/code&gt; tidak lengkap (file CSS/JS hilang)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;USER_SITE&lt;/code&gt; di &lt;code&gt;frosti.config.yaml&lt;/code&gt; salah saat build&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Solusi:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Pastikan &lt;code&gt;index.html&lt;/code&gt; ada langsung di &lt;code&gt;public_html/&lt;/code&gt;, bukan di subfolder&lt;/li&gt;
&lt;li&gt;Cek Console browser (F12) untuk error 404 spesifik&lt;/li&gt;
&lt;li&gt;Build ulang dengan &lt;code&gt;USER_SITE&lt;/code&gt; yang benar di &lt;code&gt;frosti.config.yaml&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2&gt;Referensi&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.astro.build/&quot;&gt;Astro Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/EveSunMaple/Frosti&quot;&gt;Frosti Theme&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://decapcms.org/docs/&quot;&gt;Decap CMS Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://daisyui.com/docs/themes/&quot;&gt;daisyUI Themes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://icon-sets.iconify.design/&quot;&gt;Iconify Icons&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://tailwindcss.com/docs&quot;&gt;Tailwind CSS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://ngopidulur.my.id/blog/ngopidulur-astro-blog-doc/&quot;&gt;https://ngopidulur.my.id/blog/ngopidulur-astro-blog-doc/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>Ngopidulur</dc:creator><pubDate>Thu, 21 May 2026 23:20:00 GMT</pubDate></item><item><title>Harness Engineering: OpenAI Bangun 1 Juta Baris Kode Tanpa Menulis Satu Baris Kode Manual</title><link>https://ngopidulur.my.id/blog/harness-engineering-openai-bangun-1-juta-baris-kode-tanpa-menulis-satu-baris-kode-manual/</link><guid isPermaLink="true">https://ngopidulur.my.id/blog/harness-engineering-openai-bangun-1-juta-baris-kode-tanpa-menulis-satu-baris-kode-manual/</guid><description>Bagaimana tim OpenAI mengubah peran engineer menjadi “pengarah agen” dan membangun produk besar hanya dengan Codex dalam waktu 1/10 normal.</description><content:encoded>&lt;h3&gt;Era Baru Rekayasa Perangkat Lunak Telah Tiba&lt;/h3&gt;
&lt;p&gt;Bayangkan ini: sebuah tim kecil hanya &lt;strong&gt;7 orang&lt;/strong&gt; berhasil membangun produk software berukuran &lt;strong&gt;1 juta baris kode&lt;/strong&gt; dalam waktu lima bulan — &lt;strong&gt;tanpa menulis satu baris kode pun secara manual&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Semua kode, mulai dari logika aplikasi, tes otomatis, konfigurasi CI/CD, dokumentasi, hingga tooling internal, ditulis sepenuhnya oleh &lt;strong&gt;Codex&lt;/strong&gt;, agen coding AI dari OpenAI.&lt;/p&gt;
&lt;p&gt;Ini bukan sekadar eksperimen kecil. Produk tersebut sudah digunakan ratusan pengguna internal setiap hari dan telah melewati tahap alpha testing eksternal. Ia dirilis, di-deploy, rusak, diperbaiki, dan terus berkembang.&lt;/p&gt;
&lt;p&gt;OpenAI menyebut pendekatan ini sebagai &lt;strong&gt;“Harness Engineering”&lt;/strong&gt; — seni merancang sistem, aturan, dan infrastruktur agar agen AI bisa bekerja secara mandiri dan andal dalam skala besar.&lt;/p&gt;
&lt;p&gt;Artikel ini akan membahas secara lengkap apa yang mereka pelajari, tantangan yang dihadapi, dan pelajaran penting bagi developer Indonesia yang ingin mengikuti jejak ini.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;1. Dimulai dari Repositori Git yang Benar-Benar Kosong&lt;/h3&gt;
&lt;p&gt;Pada akhir Agustus 2025, tim memulai dengan repositori kosong.&lt;/p&gt;
&lt;p&gt;Scaffold awal (struktur folder, konfigurasi CI, aturan formatting, package manager, dan framework aplikasi) dibuat oleh Codex CLI menggunakan GPT-5. Bahkan file AGENTS.md yang menjadi “panduan kerja” bagi agen juga ditulis oleh Codex sendiri.&lt;/p&gt;
&lt;p&gt;Tidak ada kode manusia sama sekali sejak commit pertama.&lt;/p&gt;
&lt;p&gt;Lima bulan kemudian, repositori telah berisi sekitar &lt;strong&gt;1 juta baris kode&lt;/strong&gt; dan lebih dari &lt;strong&gt;1.500 pull request&lt;/strong&gt; berhasil digabungkan. Rata-rata throughput mencapai &lt;strong&gt;3,5 PR per engineer per hari&lt;/strong&gt; — dan angka ini justru meningkat seiring bertambahnya tim.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Filosofi inti tim:&lt;/strong&gt; &lt;strong&gt;“No manually-written code.”&lt;/strong&gt; Manusia tidak boleh menulis kode. Titik.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;2. Peran Engineer Berubah Total&lt;/h3&gt;
&lt;p&gt;Dengan tidak adanya coding manual, peran engineer berubah drastis.&lt;/p&gt;
&lt;p&gt;Tugas utama bukan lagi menulis kode, melainkan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Merancang lingkungan kerja yang memungkinkan agen bekerja efektif&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Menentukan tujuan tingkat tinggi (intent)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Membangun sistem umpan balik (feedback loop)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Membuat segala sesuatu &lt;strong&gt;terbaca dan dapat ditegakkan&lt;/strong&gt; oleh agen&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ketika ada masalah, engineer tidak langsung “memperbaiki kode”. Mereka bertanya: &lt;strong&gt;“Kapabilitas apa yang kurang? Bagaimana kita membuatnya jelas bagi agen?”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Manusia bekerja hampir 100% melalui &lt;strong&gt;prompt&lt;/strong&gt;. Mereka mendeskripsikan tugas, menjalankan agen, lalu membiarkan agen membuka pull request, mereview sendiri, dan mengulang hingga selesai.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;3. Meningkatkan “Keterbacaan” Aplikasi untuk Agen&lt;/h3&gt;
&lt;p&gt;Salah satu bottleneck terbesar adalah kapasitas QA manusia. Karena waktu manusia terbatas, tim OpenAI membuat aplikasi, log, dan metrik &lt;strong&gt;langsung bisa dibaca dan dipahami oleh Codex&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Beberapa langkah yang dilakukan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Aplikasi bisa dijalankan per git worktree (isolasi sempurna)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Integrasi Chrome DevTools Protocol → agen bisa mengambil screenshot, snapshot DOM, dan menavigasi UI&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Observabilitas penuh (log + metrik) diekspos ke agen melalui LogQL dan PromQL&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Agen bisa bekerja sendirian hingga &lt;strong&gt;6 jam&lt;/strong&gt; tanpa intervensi manusia&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Hasilnya: agen tidak hanya menulis kode, tetapi juga bisa &lt;strong&gt;mereproduksi bug, memvalidasi perbaikan, dan bahkan merekam video demonstrasi&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;4. Pengetahuan Repositori Jadi “Sistem Catatan Utama”&lt;/h3&gt;
&lt;p&gt;Salah satu pelajaran paling penting:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;“Berikan Codex peta, bukan buku panduan 1.000 halaman.”&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Mereka pernah mencoba file AGENTS.md yang sangat besar. Gagal total. File itu justru membingungkan agen, cepat usang, dan sulit diverifikasi.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solusi yang mereka terapkan:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;AGENTS.md hanya berisi ~100 baris sebagai &lt;strong&gt;daftar isi&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Semua pengetahuan mendalam disimpan di folder docs/ yang terstruktur rapi&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ada dokumen arsitektur, core beliefs, quality score, reliability, security, dan execution plans&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Semua rencana (plans) diperlakukan sebagai artefak resmi yang versi-controlled&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Mereka juga menjalankan agen “doc-gardening” secara rutin untuk membersihkan dokumentasi usang.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;5. Arsitektur yang Ketat = Kecepatan Tanpa Kekacauan&lt;/h3&gt;
&lt;p&gt;Karena codebase 100% dihasilkan agen, mereka membangun &lt;strong&gt;arsitektur yang sangat ketat&lt;/strong&gt; sejak awal:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Setiap domain bisnis dibagi menjadi lapisan tetap (Types → Config → Repo → Service → Runtime → UI)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dependensi hanya boleh mengalir ke satu arah&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cross-cutting concerns (auth, telemetry, feature flags) masuk melalui interface tunggal&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Semua aturan ditegakkan oleh &lt;strong&gt;linter custom&lt;/strong&gt; yang dibuat Codex sendiri&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Mereka menyebutnya &lt;strong&gt;“taste invariants”&lt;/strong&gt; — aturan rasa dan kualitas yang ditegakkan secara otomatis.&lt;/p&gt;
&lt;p&gt;Dengan agen, aturan ketat justru menjadi &lt;strong&gt;pengganda kekuatan&lt;/strong&gt;, bukan penghambat.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;6. Otonomi Agen yang Semakin Tinggi&lt;/h3&gt;
&lt;p&gt;Baru-baru ini, Codex di repositori ini mencapai level otonomi yang mengesankan. Hanya dengan &lt;strong&gt;satu prompt&lt;/strong&gt;, agen sekarang bisa:&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;p&gt;Memvalidasi kondisi codebase&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Mereproduksi bug + merekam video&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Menulis perbaikan&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Memvalidasi perbaikan dengan menjalankan aplikasi&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Merekam video hasil perbaikan&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Membuka pull request&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Merespons feedback&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Memperbaiki build failure&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Menggabungkan perubahan sendiri&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Hanya ketika butuh judgment manusia, agen akan mengeskalasi.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;7. Masalah Baru: “AI Slop” dan Garbage Collection&lt;/h3&gt;
&lt;p&gt;Otonomi tinggi membawa masalah baru: agen cenderung mereplikasi pola yang sudah ada — termasuk pola buruk.&lt;/p&gt;
&lt;p&gt;Awalnya tim menghabiskan setiap Jumat untuk membersihkan “AI slop”. Tidak sustainable.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solusi:&lt;/strong&gt; Mereka membuat &lt;strong&gt;“Golden Principles”&lt;/strong&gt; dan proses garbage collection otomatis. Agen latar belakang secara rutin memindai penyimpangan, memperbarui kualitas kode, dan membuka PR refactoring yang ditargetkan.&lt;/p&gt;
&lt;p&gt;Technical debt dibayar secara terus-menerus dalam jumlah kecil, bukan ditumpuk lalu dibersihkan sekaligus.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Kesimpulan &amp;amp; Pelajaran Utama&lt;/h3&gt;
&lt;p&gt;OpenAI sudah membuktikan bahwa &lt;strong&gt;masa depan software engineering bukan tentang menulis kode lebih cepat&lt;/strong&gt;, melainkan tentang &lt;strong&gt;merancang sistem yang membuat agen AI bisa bekerja secara mandiri dan berkualitas tinggi&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Beberapa takeaways penting:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Manusia bukan lagi penulis kode&lt;/strong&gt;, melainkan &lt;strong&gt;perancang lingkungan dan aturan&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Keterbacaan untuk agen&lt;/strong&gt; sama pentingnya dengan keterbacaan untuk manusia.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Arsitektur ketat + dokumentasi terstruktur&lt;/strong&gt; adalah prasyarat kecepatan, bukan penghalang.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Garbage collection otomatis&lt;/strong&gt; untuk AI-generated code menjadi kebutuhan wajib.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Disiplin tetap diperlukan — hanya saja sekarang disiplin itu diterapkan di &lt;strong&gt;scaffolding&lt;/strong&gt;, bukan di setiap baris kode.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;Apa Artinya Ini untuk Developer Indonesia?&lt;/h3&gt;
&lt;p&gt;Bagi developer, startup, dan perusahaan teknologi di Indonesia, pesan ini sangat relevan:&lt;/p&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mulai sekarang&lt;/strong&gt;, biasakan menulis kode yang “agent-friendly” (terstruktur, terdokumentasi, dan memiliki batas yang jelas).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Investasikan waktu&lt;/strong&gt; untuk membangun harness (tools, linter, dokumentasi, dan feedback loop) — ini akan memberikan leverage jauh lebih besar di masa depan.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Jangan takut&lt;/strong&gt; dengan aturan ketat. Justru aturan yang jelas memungkinkan agen (dan tim) bergerak lebih cepat.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Siapa tahu, dalam 1–2 tahun ke depan, banyak produk Indonesia juga akan dibangun dengan pendekatan serupa.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Sumber Asli:&lt;/strong&gt; &lt;a href=&quot;https://openai.com/index/harness-engineering/&quot;&gt;Harness engineering: leveraging Codex in an agent-first world&lt;/a&gt; Oleh Ryan Lopopolo (OpenAI) – 11 Februari 2026&lt;/p&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://ngopidulur.my.id/blog/harness-engineering-openai-bangun-1-juta-baris-kode-tanpa-menulis-satu-baris-kode-manual/&quot;&gt;https://ngopidulur.my.id/blog/harness-engineering-openai-bangun-1-juta-baris-kode-tanpa-menulis-satu-baris-kode-manual/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>Ngopidulur</dc:creator><pubDate>Thu, 21 May 2026 22:17:00 GMT</pubDate></item><item><title>Prompt AI Code Reviewer Terbaik 2026</title><link>https://ngopidulur.my.id/blog/prompt-ai-code-reviewer-terbaik-2026/</link><guid isPermaLink="true">https://ngopidulur.my.id/blog/prompt-ai-code-reviewer-terbaik-2026/</guid><description>Review Kode Jadi Lebih Tajam, Actionable &amp; Profesional</description><content:encoded>&lt;p&gt;Pernahkah Anda meminta AI untuk mereview kode, tapi hasilnya hanya “kode ini bagus” atau “ada sedikit masalah”?&lt;/p&gt;
&lt;p&gt;Atau justru terlalu panjang, tidak terstruktur, dan sulit ditindaklanjuti?&lt;/p&gt;
&lt;p&gt;Saya juga sering mengalami hal yang sama. Makanya saya memutuskan untuk &lt;strong&gt;menyempurnakan prompt Code Review AI&lt;/strong&gt; secara menyeluruh. Hasilnya? Review yang jauh lebih tajam, terstruktur, dan benar-benar membantu developer memperbaiki kodenya.&lt;/p&gt;
&lt;p&gt;Di artikel ini, saya akan membagikan &lt;strong&gt;prompt versi upgrade&lt;/strong&gt; yang sudah saya sempurnakan, beserta alasan mengapa prompt ini jauh lebih efektif dibandingkan prompt biasa.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Mengapa Kebanyakan Prompt Code Review Kurang Efektif?&lt;/h2&gt;
&lt;p&gt;Banyak orang masih menggunakan prompt sederhana seperti:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“You are an expert code reviewer. Review this code and give suggestions.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Hasilnya biasanya:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Terlalu umum&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tidak ada prioritas (mana yang harus diperbaiki dulu?)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tidak memberikan contoh kode perbaikan&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tidak seimbang (hanya kritik, jarang memuji)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tidak terstruktur, sehingga sulit dibaca&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Padahal code review yang baik harus &lt;strong&gt;jelas, actionable, dan seimbang&lt;/strong&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Prompt AI Code Reviewer yang Sudah Saya Sempurnakan&lt;/h2&gt;
&lt;p&gt;Setelah melakukan beberapa iterasi dan pengujian, berikut adalah &lt;strong&gt;prompt terbaik&lt;/strong&gt; yang saya gunakan saat ini:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;You are an expert AI Code Reviewer with deep expertise across multiple programming languages (Python, JavaScript/TypeScript, Java, C#, Go, Rust, PHP, etc.), modern frameworks, clean code principles, security, and performance engineering.**Your Mission**  Provide thorough, constructive, balanced, and highly actionable code reviews that genuinely help developers improve code quality, security, performance, maintainability, and reliability. Always be professional, encouraging, and specific. Never be condescending.**Analysis Process (Follow Strictly)**When the user shares code:1. **Detect Context** — Automatically identify the programming language, framework/library (if obvious), and infer the purpose of the code. Note any assumptions you make. If the goal or full context is unclear, state your assumptions and ask clarifying questions at the end.2. **Comprehensive Multi-Dimensional Review** — Analyze the code across the following categories, **prioritizing by severity** (Critical → High → Medium → Low).### Review Categories**1. Code Quality &amp;amp; Maintainability**- Code smells, anti-patterns, and design issues (duplication, god classes, tight coupling, long methods, etc.)- Naming conventions, consistency, and descriptiveness- Code organization, modularity, and separation of concerns- Readability and cognitive complexity- Opportunities for refactoring with clear before/after examples**2. Bug Detection &amp;amp; Correctness**- Logical errors, incorrect assumptions, and potential runtime failures- Unhandled edge cases, boundary conditions, and off-by-one errors- Null/undefined handling, exception handling, and error propagation- Concurrency issues (race conditions, deadlocks, thread safety) when applicable- Data flow and state management problems**3. Security Analysis**- Common vulnerabilities (OWASP Top 10, injection, XSS, CSRF, insecure deserialization, etc.)- Input validation, sanitization, and output encoding- Authentication, authorization, and access control logic- Hardcoded secrets, weak cryptography, insecure configurations, and dependency risks- Language- and framework-specific security issues**4. Performance &amp;amp; Scalability**- Time and space complexity analysis (Big O where relevant)- Performance bottlenecks, inefficient algorithms, or suboptimal data structures- Resource leaks (memory, file handles, database connections, etc.)- Optimization opportunities (caching, batching, lazy loading, vectorization, etc.)- Scalability considerations for high-load or large-scale scenarios**5. Best Practices &amp;amp; Standards**- Adherence to language-specific style guides and idioms (PEP 8, Google Style Guide, Airbnb, etc.)- Error handling, logging, and observability best practices- Testability and suggestions for unit/integration tests (including edge cases)- Documentation quality (docstrings, comments, type hints, README notes)- Dependency management and potential outdated/vulnerable packages (if manifest is visible)**Output Format (Use This Exact Structure)**## Overall Assessment- One-paragraph summary of what the code does well + overall impression- Overall rating: Excellent / Good / Needs Improvement / Requires Significant Refactoring## Key Findings(Organized by category, sorted by severity descending)For **every issue** use this format:- **Severity**: Critical / High / Medium / Low- **Category**: Code Quality | Bug | Security | Performance | Best Practices- **Location**: Line X–Y or function `functionName()`- **Issue**: Clear, concise description- **Impact**: Why this matters (risk, maintainability cost, performance penalty, etc.)- **Recommendation**: Specific actionable fix + code example (use ```diff or before/after blocks)## Positive Aspects- Highlight well-written sections, good patterns, and strengths## Prioritized Recommendations- Top 3–5 most important actions the developer should take next (with clear priority)## Questions &amp;amp; Clarifications (if needed)- Any assumptions made or additional context required**Additional Strict Rules**- Always provide **concrete code examples** for suggestions (diff blocks are preferred).- Be balanced: criticize constructively and explicitly praise good practices.- If the code is only a snippet, review what is provided but clearly state limitations.- Tailor every recommendation to the detected language and apparent use case.- Never invent issues that do not exist. Base all findings on actual code.- If no major issues are found, still offer meaningful improvements for excellence.- Keep the tone supportive and developer-friendly.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Apa yang Membuat Prompt Ini Jauh Lebih Baik?&lt;/h2&gt;
&lt;p&gt;Berikut beberapa peningkatan utama yang saya tambahkan:&lt;/p&gt;
&lt;p&gt;Aspek&lt;/p&gt;
&lt;p&gt;Prompt Biasa&lt;/p&gt;
&lt;p&gt;Prompt Upgrade (Versi Saya)&lt;/p&gt;
&lt;p&gt;Keuntungan&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Struktur Output&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Acak&lt;/p&gt;
&lt;p&gt;Sangat terstruktur &amp;amp; konsisten&lt;/p&gt;
&lt;p&gt;Mudah dibaca&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Prioritas&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Tidak ada&lt;/p&gt;
&lt;p&gt;Ada tingkat keparahan (Critical–Low)&lt;/p&gt;
&lt;p&gt;Developer tahu mana yang urgent&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Contoh Kode&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Jarang&lt;/p&gt;
&lt;p&gt;Selalu ada diff/before-after&lt;/p&gt;
&lt;p&gt;Lebih actionable&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Keseimbangan&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Sering hanya kritik&lt;/p&gt;
&lt;p&gt;Ada bagian &amp;quot;Positive Aspects&amp;quot;&lt;/p&gt;
&lt;p&gt;Lebih memotivasi&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Kedalaman Analisis&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Superficial&lt;/p&gt;
&lt;p&gt;5 kategori mendalam + security &amp;amp; performance&lt;/p&gt;
&lt;p&gt;Review lebih komprehensif&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Rekomendasi&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Umum&lt;/p&gt;
&lt;p&gt;Top 3–5 Prioritized Recommendations&lt;/p&gt;
&lt;p&gt;Fokus pada hal terpenting&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Cara Menggunakan Prompt Ini&lt;/h2&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;p&gt;Copy seluruh prompt di atas&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Paste ke ChatGPT, Claude, Grok, atau AI lain&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Langsung paste kode yang ingin direview&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AI akan otomatis mengikuti format yang sudah saya tetapkan&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Tips Pro:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Jika kode cukup panjang, tambahkan konteks di awal (misalnya: “Ini adalah bagian dari aplikasi Next.js yang menangani autentikasi”)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Minta AI untuk fokus pada aspek tertentu jika diperlukan (contoh: “Fokus pada security dan performance”)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://ngopidulur.my.id/blog/prompt-ai-code-reviewer-terbaik-2026/&quot;&gt;https://ngopidulur.my.id/blog/prompt-ai-code-reviewer-terbaik-2026/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>Ngopidulur</dc:creator><pubDate>Thu, 21 May 2026 22:10:00 GMT</pubDate></item><item><title>Filament PHP: Cara Tercepat Membangun Admin Panel &amp; Aplikasi Laravel di 2026</title><link>https://ngopidulur.my.id/blog/filament-php-cara-tercepat-membangun-admin-panel-aplikasi-laravel-di-2026/</link><guid isPermaLink="true">https://ngopidulur.my.id/blog/filament-php-cara-tercepat-membangun-admin-panel-aplikasi-laravel-di-2026/</guid><description>Filament PHP sedang mengubah cara developer Laravel membangun admin panel. Dari yang biasanya butuh berbulan-bulan, sekarang bisa selesai dalam hitungan hari — dengan tampilan cantik dan kode yang bersih.Di artikel ini saya bahas kenapa Filament menjadi pilihan utama di 2026, fitur-fiturnya, dan bagaimana cara kerjanya.</description><content:encoded>&lt;p&gt;Pernahkah kamu merasa lelah menghabiskan berbulan-bulan hanya untuk membuat admin panel yang cantik dan fungsional? Atau mungkin kamu sudah mencoba beberapa solusi admin panel Laravel, tapi hasilnya tetap kurang memuaskan — baik dari segi tampilan, kecepatan development, maupun maintainability?&lt;/p&gt;
&lt;p&gt;Jika iya, maka &lt;strong&gt;Filament PHP&lt;/strong&gt; mungkin adalah jawaban yang selama ini kamu cari.&lt;/p&gt;
&lt;p&gt;Filament adalah &lt;strong&gt;open-source UI framework&lt;/strong&gt; yang dibangun di atas Laravel dan Livewire, yang memungkinkan developer membangun admin panel dan aplikasi full-stack dengan kecepatan luar biasa tanpa mengorbankan kualitas dan fleksibilitas.&lt;/p&gt;
&lt;h3&gt;Apa Itu Filament PHP?&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Filament&lt;/strong&gt; adalah framework modern untuk membangun &lt;strong&gt;admin panel&lt;/strong&gt; dan aplikasi Laravel dengan sangat cepat. Ia menggunakan pendekatan deklaratif dalam PHP, sehingga kamu bisa membuat antarmuka yang kompleks hanya dengan menulis sedikit kode.&lt;/p&gt;
&lt;p&gt;Filament bukan sekadar admin panel biasa. Ia adalah &lt;strong&gt;full-stack solution&lt;/strong&gt; yang memungkinkan kamu membangun aplikasi web yang utuh — mulai dari dashboard, manajemen data, form kompleks, hingga fitur real-time — dalam waktu yang jauh lebih singkat dibandingkan cara tradisional.&lt;/p&gt;
&lt;p&gt;Tagline resminya sangat jelas: &lt;strong&gt;“Build Laravel apps &amp;amp; admin panels fast”&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;Mengapa Filament Sangat Populer di Kalangan Developer Laravel?&lt;/h3&gt;
&lt;p&gt;Berikut alasan mengapa Filament menjadi salah satu pilihan utama developer Laravel di tahun 2026:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Developer Experience (DX) yang Sangat Baik&lt;/strong&gt; Banyak developer menyebut Filament sebagai “game changer”. Kamu bisa membuat resource admin (List, Create, Edit, View) hanya dalam hitungan menit.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tampilan Modern &amp;amp; Profesional&lt;/strong&gt; Filament menggunakan Tailwind CSS, sehingga tampilannya sudah sangat cantik dan responsif sejak awal. Tidak perlu repot desain dari nol.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performa yang Terus Meningkat&lt;/strong&gt; Di versi terbaru (Filament 4 &amp;amp; 5), performa tabel meningkat signifikan — hingga &lt;strong&gt;2–3x lebih cepat&lt;/strong&gt; dibandingkan versi sebelumnya.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sangat Fleksibel &amp;amp; Extensible&lt;/strong&gt; Kamu bisa dengan mudah menyesuaikan hampir semua bagian, membuat custom page, widget, atau bahkan plugin sendiri.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Komunitas yang Sangat Aktif&lt;/strong&gt; Didukung oleh komunitas Laravel yang besar, banyak plugin siap pakai, dan dokumentasi yang sangat lengkap.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Fitur Unggulan Filament&lt;/h3&gt;
&lt;p&gt;Filament dilengkapi dengan berbagai fitur powerful yang siap pakai:&lt;/p&gt;
&lt;p&gt;FiturDeskripsi&lt;strong&gt;Tables&lt;/strong&gt;Tabel interaktif dengan filter, sorting, bulk action, dan pagination yang sangat powerful&lt;strong&gt;Forms&lt;/strong&gt;Form reaktif yang kompleks dengan validasi, dependency antar field, dan layout fleksibel&lt;strong&gt;Infolists&lt;/strong&gt;Menampilkan detail record secara rapi dan terstruktur&lt;strong&gt;Notifications&lt;/strong&gt;Notifikasi real-time untuk feedback pengguna&lt;strong&gt;Dashboard Widgets&lt;/strong&gt;Widget dinamis untuk menampilkan metrik dan statistik&lt;strong&gt;Action Modals&lt;/strong&gt;Modal interaktif untuk konfirmasi dan input data&lt;strong&gt;Authorization&lt;/strong&gt;Integrasi penuh dengan Laravel Policies &amp;amp; Gates  &lt;/p&gt;
&lt;p&gt;Semua fitur ini bisa dikonfigurasi langsung di dalam file PHP — tanpa perlu menulis JavaScript atau CSS berlebihan.&lt;/p&gt;
&lt;h3&gt;Technology Stack: Powered by TALL Stack&lt;/h3&gt;
&lt;p&gt;Filament dibangun di atas &lt;strong&gt;TALL Stack&lt;/strong&gt; yang sangat populer di ekosistem Laravel:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;T&lt;/strong&gt;ailwind CSS → Styling modern &amp;amp; responsif&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A&lt;/strong&gt;lpine.js → Interaksi ringan di frontend&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;L&lt;/strong&gt;ivewire → Reactivity tanpa JavaScript berat&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;L&lt;/strong&gt;aravel → Fondasi backend yang kuat&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Kombinasi ini membuat Filament sangat ringan, cepat, dan mudah di-maintain.&lt;/p&gt;
&lt;h3&gt;Filament vs Alternatif Lain&lt;/h3&gt;
&lt;p&gt;AspekFilamentLaravel NovaBackpackOrchid&lt;strong&gt;Harga&lt;/strong&gt;Gratis (Open Source)BerbayarGratisGratis&lt;strong&gt;Kecepatan Development&lt;/strong&gt;Sangat CepatCepatSedangSedang&lt;strong&gt;Kustomisasi&lt;/strong&gt;Sangat TinggiTerbatasTinggiTinggi&lt;strong&gt;Performa&lt;/strong&gt;Sangat BaikBaikSedangBaik&lt;strong&gt;Komunitas&lt;/strong&gt;Sangat BesarBesarSedangKecil  &lt;/p&gt;
&lt;p&gt;Banyak developer yang sebelumnya menggunakan Nova atau Backpack akhirnya beralih ke Filament karena fleksibilitas dan kecepatan development yang jauh lebih baik.&lt;/p&gt;
&lt;h3&gt;Siapa yang Cocok Menggunakan Filament?&lt;/h3&gt;
&lt;p&gt;Filament sangat cocok untuk:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Developer Laravel yang ingin membangun &lt;strong&gt;admin panel&lt;/strong&gt; dengan cepat&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Startup dan agensi yang ingin &lt;strong&gt;menghemat waktu development&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tim yang membutuhkan &lt;strong&gt;dashboard kompleks&lt;/strong&gt; dan manajemen data&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Developer yang ingin membangun &lt;strong&gt;aplikasi full-stack&lt;/strong&gt; tanpa frontend framework terpisah&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Proyek internal perusahaan (ERP, CRM, sistem manajemen, dll)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Kesimpulan&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Filament PHP&lt;/strong&gt; bukan hanya sekadar admin panel. Ia adalah &lt;strong&gt;ekosistem lengkap&lt;/strong&gt; yang membantu developer Laravel membangun aplikasi dengan lebih cepat, lebih cantik, dan lebih mudah di-maintain.&lt;/p&gt;
&lt;p&gt;Di tahun 2026, ketika kecepatan pengiriman produk menjadi semakin penting, Filament menawarkan keunggulan kompetitif yang sangat signifikan.&lt;/p&gt;
&lt;p&gt;Jika kamu sedang membangun proyek baru dengan Laravel, sangat disarankan untuk mencoba Filament. Kamu mungkin tidak akan pernah kembali ke cara lama lagi.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ingin mencoba langsung?&lt;/strong&gt; Kunjungi situs resminya di &lt;a href=&quot;https://filamentphp.com&quot;&gt;https://filamentphp.com&lt;/a&gt; dan coba &lt;strong&gt;live demo&lt;/strong&gt; yang sudah mereka sediakan.&lt;/p&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://ngopidulur.my.id/blog/filament-php-cara-tercepat-membangun-admin-panel-aplikasi-laravel-di-2026/&quot;&gt;https://ngopidulur.my.id/blog/filament-php-cara-tercepat-membangun-admin-panel-aplikasi-laravel-di-2026/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>Ngopidulur</dc:creator><pubDate>Thu, 21 May 2026 13:41:00 GMT</pubDate></item><item><title>Testing Mathematical Formulas in Markdown</title><link>https://ngopidulur.my.id/blog/mathematics-examples/</link><guid isPermaLink="true">https://ngopidulur.my.id/blog/mathematics-examples/</guid><description>A demonstration of various mathematical formulas rendered using LaTeX within Markdown.</description><content:encoded>&lt;p&gt;This document serves as a test for rendering mathematical formulas in Markdown using &lt;code&gt;$$&lt;/code&gt; delimiters.&lt;/p&gt;
&lt;h2&gt;Basic Algebra&lt;/h2&gt;
&lt;p&gt;Let&amp;#39;s start with some fundamental algebraic expressions.&lt;/p&gt;
&lt;p&gt;The quadratic formula is given by:
$$x = \frac{-b \pm \sqrt{b^2-4ac}}{2a}$$&lt;/p&gt;
&lt;p&gt;A simple linear equation:
$$y = mx + c$$&lt;/p&gt;
&lt;p&gt;Expansion of a binomial square:
$$(a+b)^2 = a^2 + 2ab + b^2$$&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Calculus&lt;/h2&gt;
&lt;p&gt;Here are some common expressions from calculus.&lt;/p&gt;
&lt;p&gt;The limit definition of a derivative:
$$f&amp;#39;(x) = \lim_{h \to 0} \frac{f(x+h) - f(x)}{h}$$&lt;/p&gt;
&lt;p&gt;A definite integral:
$$\int_{a}^{b} f(x) dx$$&lt;/p&gt;
&lt;p&gt;The Taylor series expansion of $e^x$ around $x=0$:
$$e^x = \sum_{n=0}^{\infty} \frac{x^n}{n!} = 1 + x + \frac{x^2}{2!} + \frac{x^3}{3!} + \cdots$$&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Trigonometry&lt;/h2&gt;
&lt;p&gt;Some basic trigonometric identities.&lt;/p&gt;
&lt;p&gt;Pythagorean identity:
$$\sin^2\theta + \cos^2\theta = 1$$&lt;/p&gt;
&lt;p&gt;Angle addition formula for sine:
$$\sin(\alpha + \beta) = \sin\alpha\cos\beta + \cos\alpha\sin\beta$$&lt;/p&gt;
&lt;p&gt;Euler&amp;#39;s formula:
$$e^{i\theta} = \cos\theta + i\sin\theta$$&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Statistics and Probability&lt;/h2&gt;
&lt;p&gt;Formulas commonly used in statistics and probability.&lt;/p&gt;
&lt;p&gt;The formula for the mean ($\mu$) of a set of $n$ numbers $x_1, x_2, \ldots, x_n$:
$$\mu = \frac{1}{n} \sum_{i=1}^{n} x_i$$&lt;/p&gt;
&lt;p&gt;The probability density function of a normal distribution:
$$f(x | \mu, \sigma^2) = \frac{1}{\sqrt{2\pi\sigma^2}} e^{-\frac{(x-\mu)^2}{2\sigma^2}}$$&lt;/p&gt;
&lt;p&gt;Bayes&amp;#39; theorem:
$$P(A|B) = \frac{P(B|A)P(A)}{P(B)}$$&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Linear Algebra&lt;/h2&gt;
&lt;p&gt;Examples from linear algebra.&lt;/p&gt;
&lt;p&gt;A 2x2 matrix:
$$A = \begin{pmatrix} a &amp;amp; b \ c &amp;amp; d \end{pmatrix}$$&lt;/p&gt;
&lt;p&gt;The determinant of a 2x2 matrix:
$$\det(A) = ad - bc$$&lt;/p&gt;
&lt;p&gt;Matrix multiplication of two matrices A and B:
$$C = AB$$&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Physics&lt;/h2&gt;
&lt;p&gt;A couple of well-known physics equations.&lt;/p&gt;
&lt;p&gt;Einstein&amp;#39;s mass-energy equivalence:
$$E = mc^2$$&lt;/p&gt;
&lt;p&gt;Newton&amp;#39;s second law of motion:
$$F = ma$$&lt;/p&gt;
&lt;p&gt;This should provide a good test of how various mathematical formulas are rendered.&lt;/p&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://ngopidulur.my.id/blog/mathematics-examples/&quot;&gt;https://ngopidulur.my.id/blog/mathematics-examples/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>Ngopidulur</dc:creator><pubDate>Fri, 30 May 2025 17:00:00 GMT</pubDate></item><item><title>Adding Comment Systems to Frosti</title><link>https://ngopidulur.my.id/blog/adding-comment-systems/</link><guid isPermaLink="true">https://ngopidulur.my.id/blog/adding-comment-systems/</guid><description>A comprehensive guide on how to integrate the Waline comment system into your Frosti blog</description><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;One of the essential features of any blog is the ability for readers to engage with your content through comments. While Frosti provides an excellent foundation for your Astro-based blog, adding a comment system requires a few additional steps. This guide will walk you through integrating the Waline comment system into your Frosti blog.&lt;/p&gt;
&lt;p&gt;Static sites like those built with Astro don&amp;#39;t have built-in comment systems since they lack server-side processing. However, we can use third-party comment services that handle the backend for us, while we integrate their frontend components into our site.&lt;/p&gt;
&lt;h2&gt;Creating Comment Components in Astro&lt;/h2&gt;
&lt;p&gt;Before diving into a specific comment system, let&amp;#39;s understand how to create and use components in Astro. We&amp;#39;ll create a reusable component that can be easily added to any page.&lt;/p&gt;
&lt;h3&gt;Component Structure&lt;/h3&gt;
&lt;p&gt;We&amp;#39;ll create our comment component in the &lt;code&gt;src/components/comments&lt;/code&gt; directory. First, let&amp;#39;s ensure this directory exists:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mkdir -p src/components/comments
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Integrating Waline&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://waline.js.org/&quot;&gt;Waline&lt;/a&gt; is a simple, safe, and feature-rich comment system with backend and frontend separation. It is highly customizable and easy to set up.&lt;/p&gt;
&lt;h3&gt;Step 1: Set Up Waline Backend&lt;/h3&gt;
&lt;p&gt;Before adding Waline to your site, you need to set up the backend:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a LeanCloud application to store your comments.&lt;/li&gt;
&lt;li&gt;Deploy the Waline server to Vercel or another hosting platform.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Follow the &lt;a href=&quot;https://waline.js.org/guide/get-started/&quot;&gt;official Waline guide&lt;/a&gt; to set up your backend service. After deploying, you&amp;#39;ll get a server URL that you will need for the frontend component.&lt;/p&gt;
&lt;h3&gt;Step 2: Create the Waline Component&lt;/h3&gt;
&lt;p&gt;Let&amp;#39;s create a reusable Waline component:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;touch src/components/comments/Waline.astro
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add the following code to this component:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-astro&quot;&gt;---
interface Props {
  serverURL: string;
  lang?: string;
  dark?: string;
  emoji?: string[];
  meta?: string[];
  requiredMeta?: string[];
  reaction?: boolean;
  pageview?: boolean;
}

const {
  serverURL,
  lang = &amp;quot;en&amp;quot;,
  dark = &amp;quot;html[data-theme-type=&amp;#39;dark&amp;#39;]&amp;quot;,
  emoji = [&amp;quot;https://unpkg.com/@waline/emojis@1.1.0/weibo&amp;quot;, &amp;quot;https://unpkg.com/@waline/emojis@1.1.0/bilibili&amp;quot;],
  meta = [&amp;quot;nick&amp;quot;, &amp;quot;mail&amp;quot;, &amp;quot;link&amp;quot;],
  requiredMeta = [],
  reaction = false,
  pageview = false,
} = Astro.props;
---

&amp;lt;div id=&amp;quot;waline-container&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;

&amp;lt;link rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;https://unpkg.com/@waline/client@v3/dist/waline.css&amp;quot; /&amp;gt;

&amp;lt;script
  type=&amp;quot;module&amp;quot;
  define:vars={{
    serverURL,
    lang,
    dark,
    emoji,
    meta,
    requiredMeta,
    reaction,
    pageview,
  }}
&amp;gt;
  import { init } from &amp;quot;https://unpkg.com/@waline/client@v3/dist/waline.js&amp;quot;;

  async function initWaline() {
    const container = document.querySelector(&amp;quot;#waline-container&amp;quot;);
    if (!container) return;

    init({
      el: &amp;quot;#waline-container&amp;quot;,
      serverURL,
      path: location.pathname,
      lang,
      dark,
      emoji,
      meta,
      requiredMeta,
      reaction,
      pageview,
    });
  }

  document.addEventListener(&amp;quot;astro:page-load&amp;quot;, () =&amp;gt; {
    initWaline();
  });

  if (document.readyState !== &amp;quot;loading&amp;quot;) {
    initWaline();
  } else {
    document.addEventListener(&amp;quot;DOMContentLoaded&amp;quot;, initWaline);
  }
&amp;lt;/script&amp;gt;

&amp;lt;style&amp;gt;
  #waline-container {
    margin-top: 2rem;
    margin-bottom: 2rem;
  }
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 3: Using the Waline Component&lt;/h3&gt;
&lt;p&gt;You can now use the Waline component in your Astro pages or layouts. Here&amp;#39;s how to add it to your blog post template:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-astro&quot;&gt;---
// In your blog post layout file
import Waline from &amp;quot;../../components/comments/Waline.astro&amp;quot;;
// Other imports and frontmatter...
---

&amp;lt;!-- Your blog post content --&amp;gt;
&amp;lt;article&amp;gt;
  &amp;lt;slot /&amp;gt;
&amp;lt;/article&amp;gt;

&amp;lt;!-- Add the comment section --&amp;gt;
&amp;lt;section class=&amp;quot;comments&amp;quot;&amp;gt;
  &amp;lt;h2&amp;gt;Comments&amp;lt;/h2&amp;gt;
  &amp;lt;Waline serverURL=&amp;quot;https://your-waline-server.vercel.app&amp;quot; /&amp;gt;
&amp;lt;/section&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Replace &lt;code&gt;&amp;quot;https://your-waline-server.vercel.app&amp;quot;&lt;/code&gt; with your actual Waline server URL.&lt;/p&gt;
&lt;h2&gt;Troubleshooting&lt;/h2&gt;
&lt;h3&gt;Common Issues&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Comments not displaying:&lt;/strong&gt; Make sure your &lt;code&gt;serverURL&lt;/code&gt; is correctly set and accessible.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CSS issues:&lt;/strong&gt; Ensure that the Waline stylesheet is properly loaded.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deployment issues:&lt;/strong&gt; If your server is on Vercel, check the environment variables and deployment logs.&lt;/li&gt;
&lt;/ul&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://ngopidulur.my.id/blog/adding-comment-systems/&quot;&gt;https://ngopidulur.my.id/blog/adding-comment-systems/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>Ngopidulur</dc:creator><pubDate>Mon, 14 Apr 2025 17:00:00 GMT</pubDate></item><item><title>Markdown Style Guide</title><link>https://ngopidulur.my.id/blog/markdown-style-guide/</link><guid isPermaLink="true">https://ngopidulur.my.id/blog/markdown-style-guide/</guid><description>Here is a sample of some basic Markdown syntax that can be used when writing Markdown content in Astro.</description><content:encoded>&lt;p&gt;Here is a sample of some basic Markdown syntax that can be used when writing Markdown content in Astro.&lt;/p&gt;
&lt;h2&gt;Headings&lt;/h2&gt;
&lt;p&gt;The following HTML &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;—&lt;code&gt;&amp;lt;h6&amp;gt;&lt;/code&gt; elements represent six levels of section headings. &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; is the highest section level while &lt;code&gt;&amp;lt;h6&amp;gt;&lt;/code&gt; is the lowest.&lt;/p&gt;
&lt;h1&gt;H1&lt;/h1&gt;
&lt;h2&gt;H2&lt;/h2&gt;
&lt;h3&gt;H3&lt;/h3&gt;
&lt;h4&gt;H4&lt;/h4&gt;
&lt;h5&gt;H5&lt;/h5&gt;
&lt;h6&gt;H6&lt;/h6&gt;
&lt;h2&gt;Paragraph&lt;/h2&gt;
&lt;p&gt;Xerum, quo qui aut unt expliquam qui dolut labo. Aque venitatiusda cum, voluptionse latur sitiae dolessi aut parist aut dollo enim qui voluptate ma dolestendit peritin re plis aut quas inctum laceat est volestemque commosa as cus endigna tectur, offic to cor sequas etum rerum idem sintibus eiur? Quianimin porecus evelectur, cum que nis nust voloribus ratem aut omnimi, sitatur? Quiatem. Nam, omnis sum am facea corem alique molestrunt et eos evelece arcillit ut aut eos eos nus, sin conecerem erum fuga. Ri oditatquam, ad quibus unda veliamenimin cusam et facea ipsamus es exerum sitate dolores editium rerore eost, temped molorro ratiae volorro te reribus dolorer sperchicium faceata tiustia prat.&lt;/p&gt;
&lt;p&gt;Itatur? Quiatae cullecum rem ent aut odis in re eossequodi nonsequ idebis ne sapicia is sinveli squiatum, core et que aut hariosam ex eat.&lt;/p&gt;
&lt;h2&gt;Images&lt;/h2&gt;
&lt;h4&gt;Syntax&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;![Alt text](./full/or/relative/path/of/image)
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Output&lt;/h4&gt;
&lt;p&gt;&lt;img src=&quot;https://ngopidulur.my.id/logo.png&quot; alt=&quot;blog placeholder&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Blockquotes&lt;/h2&gt;
&lt;p&gt;The blockquote element represents content that is quoted from another source, optionally with a citation which must be within a &lt;code&gt;footer&lt;/code&gt; or &lt;code&gt;cite&lt;/code&gt; element, and optionally with in-line changes such as annotations and abbreviations.&lt;/p&gt;
&lt;h3&gt;Blockquote without attribution&lt;/h3&gt;
&lt;h4&gt;Syntax&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;&amp;gt; Tiam, ad mint andaepu dandae nostion secatur sequo quae.
&amp;gt; **Note** that you can use _Markdown syntax_ within a blockquote.
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Output&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;Tiam, ad mint andaepu dandae nostion secatur sequo quae.
&lt;strong&gt;Note&lt;/strong&gt; that you can use &lt;em&gt;Markdown syntax&lt;/em&gt; within a blockquote.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Blockquote with attribution&lt;/h3&gt;
&lt;h4&gt;Syntax&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;&amp;gt; Don&amp;#39;t communicate by sharing memory, share memory by communicating.&amp;lt;br&amp;gt;
&amp;gt; — &amp;lt;cite&amp;gt;Rob Pike[^1]&amp;lt;/cite&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Output&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;Don&amp;#39;t communicate by sharing memory, share memory by communicating.&lt;br&gt;
— &lt;cite&gt;Rob Pike[^1]&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;[^1]: The above quote is excerpted from Rob Pike&amp;#39;s &lt;a href=&quot;https://www.youtube.com/watch?v=PAAkCSZUG1c&quot;&gt;talk&lt;/a&gt; during Gopherfest, November 18, 2015.&lt;/p&gt;
&lt;h2&gt;Tables&lt;/h2&gt;
&lt;h4&gt;Syntax&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;| Italics   | Bold     | Code   |
| --------- | -------- | ------ |
| _italics_ | **bold** | `code` |
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Output&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Italics&lt;/th&gt;
&lt;th&gt;Bold&lt;/th&gt;
&lt;th&gt;Code&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;&lt;em&gt;italics&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;bold&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;code&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;Code Blocks&lt;/h2&gt;
&lt;h4&gt;Syntax&lt;/h4&gt;
&lt;p&gt;we can use 3 backticks ``` in new line and write snippet and close with 3 backticks on new line and to highlight language specific syntac, write one word of language name after first 3 backticks, for eg. html, javascript, css, markdown, typescript, txt, bash&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;```cpp
#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;
const int N = 1e5 + 5;
int n, k, a[N];
long long ans;
vector&amp;lt;int&amp;gt; v[N];
int main()
{
    scanf(&amp;quot;%d%d&amp;quot;, &amp;amp;n, &amp;amp;k);
    for (int i = 1; i &amp;lt;= n; i++)
    {
        scanf(&amp;quot;%d&amp;quot;, &amp;amp;a[i]);
        v[i % k].push_back(a[i]);
    }
    for (int i = 0; i &amp;lt; k; i++)
        sort(v[i].rbegin(), v[i].rend());
    for (int i = 0; i &amp;lt; k; i++)
    {
        for (int j = 0; j + 1 &amp;lt; v[i].size(); j += 2)
        {
            ans += v[i][j] + v[i][j + 1];
        }
    }
    printf(&amp;quot;%lld\n&amp;quot;, ans);
    return 0;
}
```
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Output&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;#include &amp;lt;bits/stdc++.h&amp;gt;
using namespace std;
const int N = 1e5 + 5;
int n, k, a[N];
long long ans;
vector&amp;lt;int&amp;gt; v[N];
int main()
{
    scanf(&amp;quot;%d%d&amp;quot;, &amp;amp;n, &amp;amp;k);
    for (int i = 1; i &amp;lt;= n; i++)
    {
        scanf(&amp;quot;%d&amp;quot;, &amp;amp;a[i]);
        v[i % k].push_back(a[i]);
    }
    for (int i = 0; i &amp;lt; k; i++)
        sort(v[i].rbegin(), v[i].rend());
    for (int i = 0; i &amp;lt; k; i++)
    {
        for (int j = 0; j + 1 &amp;lt; v[i].size(); j += 2)
        {
            ans += v[i][j] + v[i][j + 1];
        }
    }
    printf(&amp;quot;%lld\n&amp;quot;, ans);
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;List Types&lt;/h2&gt;
&lt;h3&gt;Ordered List&lt;/h3&gt;
&lt;h4&gt;Syntax&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;1. First item
2. Second item
3. Third item
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Output&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;First item&lt;/li&gt;
&lt;li&gt;Second item&lt;/li&gt;
&lt;li&gt;Third item&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Unordered List&lt;/h3&gt;
&lt;h4&gt;Syntax&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;- List item
- Another item
- And another item
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Output&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;List item&lt;/li&gt;
&lt;li&gt;Another item&lt;/li&gt;
&lt;li&gt;And another item&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Nested list&lt;/h3&gt;
&lt;h4&gt;Syntax&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;- Fruit
  - Apple
  - Orange
  - Banana
- Dairy
  - Milk
  - Cheese
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Output&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Fruit&lt;ul&gt;
&lt;li&gt;Apple&lt;/li&gt;
&lt;li&gt;Orange&lt;/li&gt;
&lt;li&gt;Banana&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Dairy&lt;ul&gt;
&lt;li&gt;Milk&lt;/li&gt;
&lt;li&gt;Cheese&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Other Elements&lt;/h2&gt;
&lt;h4&gt;Syntax&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;&amp;lt;abbr title=&amp;quot;Graphics Interchange Format&amp;quot;&amp;gt;GIF&amp;lt;/abbr&amp;gt; is a bitmap image format.

H&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;O

X&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; + Y&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; = Z&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt;

Press &amp;lt;kbd&amp;gt;CTRL&amp;lt;/kbd&amp;gt;+&amp;lt;kbd&amp;gt;ALT&amp;lt;/kbd&amp;gt;+&amp;lt;kbd&amp;gt;Delete&amp;lt;/kbd&amp;gt; to end the session.

Most &amp;lt;mark&amp;gt;salamanders&amp;lt;/mark&amp;gt; are nocturnal, and hunt for insects, worms, and other small creatures.
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Output&lt;/h4&gt;
&lt;p&gt;&lt;abbr title=&quot;Graphics Interchange Format&quot;&gt;GIF&lt;/abbr&gt; is a bitmap image format.&lt;/p&gt;
&lt;p&gt;H&lt;sub&gt;2&lt;/sub&gt;O&lt;/p&gt;
&lt;p&gt;X&lt;sup&gt;n&lt;/sup&gt; + Y&lt;sup&gt;n&lt;/sup&gt; = Z&lt;sup&gt;n&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Press &lt;kbd&gt;CTRL&lt;/kbd&gt;+&lt;kbd&gt;ALT&lt;/kbd&gt;+&lt;kbd&gt;Delete&lt;/kbd&gt; to end the session.&lt;/p&gt;
&lt;p&gt;Most &lt;mark&gt;salamanders&lt;/mark&gt; are nocturnal, and hunt for insects, worms, and other small creatures.&lt;/p&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://ngopidulur.my.id/blog/markdown-style-guide/&quot;&gt;https://ngopidulur.my.id/blog/markdown-style-guide/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>Ngopidulur</dc:creator><pubDate>Sun, 30 Jun 2024 17:00:00 GMT</pubDate></item><item><title>Using MDX</title><link>https://ngopidulur.my.id/blog/using-mdx/</link><guid isPermaLink="true">https://ngopidulur.my.id/blog/using-mdx/</guid><description>Lorem ipsum dolor sit amet</description><content:encoded>&lt;p&gt;This theme comes with the &lt;a href=&quot;https://docs.astro.build/en/guides/integrations-guide/mdx/&quot;&gt;@astrojs/mdx&lt;/a&gt; integration installed and configured in your &lt;code&gt;astro.config.mjs&lt;/code&gt; config file. If you prefer not to use MDX, you can disable support by removing the integration from your config file.&lt;/p&gt;
&lt;h2&gt;Why MDX?&lt;/h2&gt;
&lt;p&gt;MDX is a special flavor of Markdown that supports embedded JavaScript &amp;amp; JSX syntax. This unlocks the ability to &lt;a href=&quot;https://docs.astro.build/en/guides/markdown-content/#mdx-features&quot;&gt;mix JavaScript and UI Components into your Markdown content&lt;/a&gt; for things like interactive charts or alerts.&lt;/p&gt;
&lt;p&gt;If you have existing content authored in MDX, this integration will hopefully make migrating to Astro a breeze.&lt;/p&gt;
&lt;h2&gt;Example&lt;/h2&gt;
&lt;p&gt;Here is how you import and use a UI component inside of MDX.&lt;br&gt;When you open this page in the browser, you should see the clickable button below.&lt;/p&gt;
&lt;h2&gt;More Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://mdxjs.com/docs/what-is-mdx&quot;&gt;MDX Syntax Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.astro.build/en/guides/markdown-content/#markdown-and-mdx-pages&quot;&gt;Astro Usage Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;a href=&quot;https://docs.astro.build/en/reference/directives-reference/#client-directives&quot;&gt;Client Directives&lt;/a&gt; are still required to create interactive components. Otherwise, all components in your MDX will render as static HTML (no JavaScript) by default.&lt;/li&gt;
&lt;/ul&gt;
 &lt;blockquote&gt;This rendering was automatically generated by Frosti Feed and may have formatting issues. For the best experience, please visit: &lt;a href=&quot;https://ngopidulur.my.id/blog/using-mdx/&quot;&gt;https://ngopidulur.my.id/blog/using-mdx/&lt;/a&gt;&lt;/blockquote&gt;</content:encoded><dc:creator>Ngopidulur</dc:creator><pubDate>Fri, 01 Jul 2022 17:00:00 GMT</pubDate></item></channel></rss>