<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Blogging on kenji.blog</title><link>http://kenji.blog/id/categories/blogging/</link><description>Recent content in Blogging on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>id</language><copyright>kenjinote</copyright><lastBuildDate>Sun, 13 Sep 2026 02:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/id/categories/blogging/index.xml" rel="self" type="application/rss+xml"/><item><title>Pengenalan Generator Situs Statis Menggunakan Hugo (Prosedur Migrasi dari WordPress)</title><link>http://kenji.blog/id/p/hugo-static-site-generator-wordpress-migration/</link><pubDate>Sun, 13 Sep 2026 02:00:00 +0900</pubDate><guid>http://kenji.blog/id/p/hugo-static-site-generator-wordpress-migration/</guid><description>&lt;img src="http://kenji.blog/p/hugo-static-site-generator-wordpress-migration/img/eyecatch.jpg" alt="Featured image of post Pengenalan Generator Situs Statis Menggunakan Hugo (Prosedur Migrasi dari WordPress)" />&lt;p>Dalam pengembangan web modern dan manajemen blog, kecepatan memuat situs, keamanan, dan pemeliharaan merupakan faktor yang sangat penting. &amp;ldquo;WordPress&amp;rdquo;, yang telah lama mendominasi sebagai fondasi untuk blog dan situs perusahaan, banyak digunakan oleh pengguna karena ekosistem plugin yang fleksibel dan dasbor manajemen yang intuitif. Namun, karena ini melibatkan komunikasi dengan database dan pembuatan halaman dinamis di sisi server (pemrosesan oleh PHP), ia juga memiliki masalah seperti kerentanan terhadap lonjakan lalu lintas yang tiba-tiba dan penundaan tampilan (latensi).&lt;/p>
&lt;p>Oleh karena itu, dalam beberapa tahun terakhir, &amp;ldquo;Generator Situs Statis (SSG: Static Site Generator)&amp;rdquo; dengan cepat menjadi populer. Dalam artikel ini, di antara sekian banyak SSG, kita akan menggali lebih dalam tentang &amp;ldquo;&lt;strong>Hugo&lt;/strong>&amp;rdquo;, yang dikembangkan dengan bahasa Go dan dikenal dengan kecepatan build-nya yang luar biasa. Kita akan membahas semuanya secara menyeluruh, mulai dari perbandingan arsitektur teknis dengan CMS dinamis (Content Management System) seperti WordPress, prosedur migrasi yang konkret, evaluasi kinerja menggunakan model matematis, hingga struktur direktori spesifik Hugo dan urutan pencarian template (lookup order).&lt;/p>
&lt;hr>
&lt;h2 id="1-perbedaan-teknis-antara-cms-dinamis-wordpress-dan-generator-situs-statis-hugo">1. Perbedaan Teknis antara CMS Dinamis (WordPress) dan Generator Situs Statis (Hugo)
&lt;/h2>&lt;p>Dalam mekanisme penyampaian situs web, WordPress dan Hugo mengambil pendekatan yang pada dasarnya berbeda.&lt;/p>
&lt;h3 id="11-arsitektur-wordpress-pembuatan-dinamis">1.1 Arsitektur WordPress (Pembuatan Dinamis)
&lt;/h3>&lt;p>WordPress adalah contoh utama dari CMS dinamis yang menyusun halaman di sisi server setiap kali ada permintaan. Ketika seorang pengguna (browser) mengakses sebuah halaman, server web (Apache, Nginx, dll.) mengeksekusi skrip PHP dan menerbitkan kueri ke database relasional seperti MySQL (atau MariaDB). Konten yang diambil dari database (data artikel, kategori, tag, pengaturan situs, dll.) digabungkan dengan file template, dan HTML akhir dihasilkan lalu dikembalikan ke klien.&lt;/p>
&lt;p>Mekanisme ini memiliki keuntungan mampu menghasilkan konten yang berbeda untuk setiap pengunjung secara real-time (misalnya: keranjang belanja di situs e-commerce, halaman khusus pengguna yang masuk), tetapi kecuali jika mekanisme caching (reverse proxy, plugin, dll.) dirancang dengan tepat, ini akan menghabiskan sumber daya server secara drastis.&lt;/p>
&lt;h3 id="12-arsitektur-hugo-pra-pembuatan-saat-build">1.2 Arsitektur Hugo (Pra-pembuatan saat Build)
&lt;/h3>&lt;p>Di sisi lain, seperti namanya &amp;ldquo;generator situs statis&amp;rdquo;, Hugo menghasilkan konten saat &amp;ldquo;build&amp;rdquo;, bukan saat &amp;ldquo;permintaan (request)&amp;rdquo;. Konten tidak disimpan dalam database, melainkan dikelola sebagai &amp;ldquo;file Markdown&amp;rdquo; lokal yang dikontrol versinya dengan Git atau sejenisnya.
Saat pengembang menjalankan perintah (&lt;code>hugo&lt;/code>), Hugo membaca file Markdown, menuangkan data ke dalam template HTML (file layout) yang ditentukan, dan menghasilkan sekumpulan file HTML/CSS/JS murni yang telah selesai.&lt;/p>
&lt;p>Kumpulan file yang dihasilkan (aset statis) dapat didistribusikan hanya dengan menempatkannya di &amp;ldquo;lingkungan hosting statis&amp;rdquo; seperti Amazon S3, Cloudflare Pages, Netlify, Vercel, atau server Nginx sederhana. Karena tidak ada database atau bahasa sisi server (seperti PHP) yang diperlukan, risiko keamanan (injeksi SQL, kerentanan PHP, dll.) berkurang secara drastis, dan kecepatan distribusi dimaksimalkan hingga batasnya karena di-cache pada node edge CDN (Content Delivery Network).&lt;/p>
&lt;p>Perbedaan arsitektur masing-masing ditunjukkan pada diagram Mermaid di bawah ini.&lt;/p>
&lt;pre class="mermaid">
flowchart TD
subgraph WordPress[&amp;#34;CMS Dinamis (WordPress)&amp;#34;]
direction TB
Req1[&amp;#34;Permintaan Pengguna&amp;#34;] --&amp;gt; WebServer1[&amp;#34;Server Web (Nginx/Apache)&amp;#34;]
WebServer1 --&amp;gt; PHP[&amp;#34;Pemrosesan PHP&amp;#34;]
PHP &amp;lt;--&amp;gt; DB[&amp;#34;Database (MySQL)&amp;#34;]
PHP --&amp;gt; HTML1[&amp;#34;Pembuatan HTML&amp;#34;]
HTML1 --&amp;gt; Res1[&amp;#34;Pengembalian Respons&amp;#34;]
end
subgraph Hugo[&amp;#34;Generator Situs Statis (Hugo)&amp;#34;]
direction TB
Dev[&amp;#34;Pengembang / CI・CD&amp;#34;] --&amp;gt; HugoBuild[&amp;#34;Proses Build Hugo&amp;#34;]
Markdown[&amp;#34;Kumpulan File Markdown&amp;#34;] --&amp;gt; HugoBuild
Templates[&amp;#34;Template (HTML)&amp;#34;] --&amp;gt; HugoBuild
HugoBuild --&amp;gt; StaticFiles[&amp;#34;Kumpulan File Statis (HTML/CSS/JS)&amp;#34;]
StaticFiles --&amp;gt; CDN[&amp;#34;CDN / Hosting Statis&amp;#34;]
Req2[&amp;#34;Permintaan Pengguna&amp;#34;] --&amp;gt; CDN
CDN --&amp;gt; Res2[&amp;#34;Pengembalian Respons Instan&amp;#34;]
end
&lt;/pre>
&lt;hr>
&lt;h2 id="2-evaluasi-kinerja-menggunakan-model-matematis">2. Evaluasi Kinerja Menggunakan Model Matematis
&lt;/h2>&lt;p>Salah satu keuntungan terbesar bermigrasi dari WordPress ke Hugo adalah peningkatan kinerja (kecepatan tampilan). Untuk memahami ini secara kuantitatif, mari kita nyatakan dengan model matematika sederhana.&lt;/p>
&lt;p>Waktu hingga pemuatan halaman selesai (Load Time: $T_{load}$) pada dasarnya dibagi menjadi waktu respons server (TTFB: Time To First Byte) dan waktu rendering serta pengambilan sumber daya oleh browser ($T_{render}$).&lt;/p>
$$ T_{load} = T_{ttfb} + T_{render} $$&lt;p>Dalam kasus CMS dinamis (WordPress), $T_{ttfb}$ adalah jumlah dari elemen-elemen berikut: Penundaan jaringan ($T_{network}$), waktu eksekusi skrip di sisi server ($T_{php}$), dan waktu pemrosesan kueri database ($T_{db}$).&lt;/p>
$$ T_{ttfb\_wp} = T_{network} + T_{php} + T_{db} $$&lt;p>Dalam kondisi di mana akses terkonsentrasi (beban tinggi), $T_{php}$ dan $T_{db}$ meningkat secara non-linier, dan seluruh sistem dapat menjadi leher botol (bottleneck). Dinyatakan dalam rumus, penurunan waktu respons berikut terjadi sehubungan dengan jumlah permintaan ($N$) (dengan $k$ adalah koefisien overhead pemrosesan).&lt;/p>
$$ T_{php}(N) \approx O(N^k), \quad T_{db}(N) \approx O(N^k) \quad \text{where } k > 1 $$&lt;p>Di sisi lain, dalam arsitektur yang menggabungkan generator situs statis (Hugo) dan CDN, tidak ada pemrosesan dinamis di sisi server (PHP atau kueri DB). Karena konten di-cache di server edge yang didistribusikan di seluruh dunia, $T_{ttfb}$ murni hanya bergantung pada latensi jaringan ($T_{edge}$) dari klien ke server edge terdekat.&lt;/p>
$$ T_{ttfb\_hugo} = T_{edge} $$&lt;p>Sebagai hasilnya, $T_{edge} \ll (T_{network} + T_{php} + T_{db})$ berlaku, dan TTFB dipersingkat secara dramatis dari beberapa milidetik hingga sekitar puluhan milidetik. Selain itu, bahkan jika jumlah permintaan $N$ meningkat, fungsi penyeimbangan beban dari server edge menjaga waktu respons tetap konstan ($O(1)$).&lt;/p>
$$ \lim_{N \to \infty} T_{ttfb\_hugo}(N) \approx \text{Constant} $$&lt;p>Inilah dasar matematis mengapa Hugo (situs statis) sangat kuat terhadap lonjakan lalu lintas (misalnya, ketika menjadi viral).&lt;/p>
&lt;hr>
&lt;h2 id="3-struktur-dasar-dan-prinsip-kerja-hugo">3. Struktur Dasar dan Prinsip Kerja Hugo
&lt;/h2>&lt;p>Untuk menguasai Hugo, penting untuk memahami struktur direktorinya yang unik dan konsep &amp;ldquo;Front Matter&amp;rdquo; serta &amp;ldquo;Template Lookup Order&amp;rdquo;.&lt;/p>
&lt;h3 id="31-penjelasan-rinci-tentang-struktur-direktori">3.1 Penjelasan Rinci tentang Struktur Direktori
&lt;/h3>&lt;p>Ketika Anda membuat proyek Hugo baru (&lt;code>hugo new site mysite&lt;/code>), struktur direktori berikut akan dihasilkan.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">mysite/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── archetypes/ # Template untuk pembuatan konten baru (kerangka Front Matter)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── assets/ # File yang akan diproses oleh Hugo Pipes (SCSS/Sass, JavaScript, dll.)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── content/ # Konten situs sebenarnya (kumpulan file Markdown). Ini menggantikan DB.
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── data/ # Data eksternal dan pengaturan yang digunakan di seluruh situs (JSON, TOML, YAML, CSV, dll.)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── layouts/ # Kumpulan template HTML yang menentukan tampilan situs (menggunakan Go html/template)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── public/ # Tempat output file statis yang dihasilkan setelah menjalankan perintah build
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── static/ # File statis yang dipublikasikan apa adanya (gambar, favicon, teks untuk robot, dll.)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── themes/ # Direktori tema pihak ketiga atau buatan sendiri
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└── hugo.toml # File konfigurasi seluruh situs (sebelumnya config.toml yang utama)
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Dalam WordPress, konten disimpan dalam tabel &lt;code>wp_posts&lt;/code> MySQL, tetapi di Hugo, semuanya dikelola sebagai file teks (terutama Markdown) di dalam direktori &lt;code>content/&lt;/code>. Hal ini memudahkan pengelolaan versi konten (Git).&lt;/p>
&lt;h3 id="32-manajemen-konten-markdown-dan-front-matter">3.2 Manajemen Konten: Markdown dan Front Matter
&lt;/h3>&lt;p>Setiap file artikel di Hugo memiliki blok metadata yang disebut &amp;ldquo;Front Matter&amp;rdquo; di bagian paling atas, diikuti oleh teks utama (Markdown) di bawahnya. Front Matter dapat ditulis dalam format TOML, YAML, atau JSON, tetapi YAML adalah yang paling banyak digunakan.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">title&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;Memahami Taksonomi Hugo&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">date&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="ld">2026-09-13T10:00:00&lt;/span>&lt;span class="m">+09&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="m">00&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">draft&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">false&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">categories&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;Penjelasan Teknis&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">tags&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;Hugo&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;Go&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">aliases&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;/old-category/hugo-taxonomy/&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="l">Dari sini adalah teks utamanya. Ditulis dalam **Markdown**.&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="l">Saya akan menjelaskan fitur-fitur canggih dari Hugo...&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Yang patut diperhatikan di sini adalah kunci &lt;code>aliases&lt;/code>. Saat bermigrasi dari WordPress, jika permalink (URL) berubah, itu akan menjadi kerugian besar untuk SEO. Dengan menggunakan fungsi alias Hugo, hanya dengan menentukan URL lama, Hugo secara otomatis akan menghasilkan HTML untuk pengalihan (transfer oleh meta refresh). Sangat mudah karena pengaturan pengalihan sisi server (seperti .htaccess) tidak lagi diperlukan.&lt;/p>
&lt;h3 id="33-urutan-pencarian-template-template-lookup-order">3.3 Urutan Pencarian Template (Template Lookup Order)
&lt;/h3>&lt;p>Salah satu fitur paling kuat dari Hugo adalah mekanisme pencarian template yang fleksibel (Template Lookup Order). Saat me-render halaman tertentu, Hugo mencari direktori dan nama file dalam urutan tertentu untuk menemukan template yang paling cocok.&lt;/p>
&lt;p>Sebagai contoh, ketika menggambar artikel tunggal (Single Page) seperti &lt;code>content/post/hello-world.md&lt;/code>, Hugo umumnya mencari file layout dengan urutan sebagai berikut.&lt;/p>
&lt;ol>
&lt;li>&lt;code>layouts/post/single.html&lt;/code>&lt;/li>
&lt;li>&lt;code>layouts/post/list.html&lt;/code> (Tidak salah, tetapi biasanya untuk daftar)&lt;/li>
&lt;li>&lt;code>layouts/_default/single.html&lt;/code>&lt;/li>
&lt;li>&lt;code>themes/&amp;lt;NAMA_TEMA&amp;gt;/layouts/post/single.html&lt;/code>&lt;/li>
&lt;li>&lt;code>themes/&amp;lt;NAMA_TEMA&amp;gt;/layouts/_default/single.html&lt;/code>&lt;/li>
&lt;/ol>
&lt;p>Pengembang dapat &lt;strong>menimpa (override)&lt;/strong> template tema hanya dengan membuat file dengan nama yang sama di direktori &lt;code>layouts/&lt;/code> milik proyek mereka sendiri tanpa mengubah kode sumber tema secara langsung. Hal ini memungkinkan penyesuaian (kustomisasi) unik tanpa menghalangi pembaruan tema dasar.&lt;/p>
&lt;h3 id="34-taksonomi-taxonomy">3.4 Taksonomi (Taxonomy)
&lt;/h3>&lt;p>Sistem klasifikasi yang setara dengan &amp;ldquo;Kategori&amp;rdquo; dan &amp;ldquo;Tag&amp;rdquo; di WordPress disebut &amp;ldquo;Taksonomi (Taxonomy)&amp;rdquo; di Hugo.
Secara default, Hugo mendukung taksonomi &lt;code>categories&lt;/code> dan &lt;code>tags&lt;/code>, tetapi dengan mengedit &lt;code>hugo.toml&lt;/code>, Anda dapat dengan bebas menambahkan taksonomi kustom (misalnya: &lt;code>series&lt;/code>, &lt;code>authors&lt;/code>, dll.).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-toml" data-lang="toml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Contoh hugo.toml&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="nx">taxonomies&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">category&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;categories&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">tag&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;tags&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">series&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;series&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">author&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;authors&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Ini memungkinkan Anda untuk mengatur dan membuat daftar konten dari berbagai sudut pandang.&lt;/p>
&lt;hr>
&lt;h2 id="4-proses-migrasi-dari-wordpress-ke-hugo-migration">4. Proses Migrasi dari WordPress ke Hugo (Migration)
&lt;/h2>&lt;p>Dalam migrasi dari WordPress ke Hugo, kunci suksesnya adalah bagaimana mengubah konten dinamis dalam database menjadi file statis yang bersih (Markdown + Front Matter) serta mempertahankan struktur URL yang ada.&lt;/p>
&lt;p>Berikut adalah alur pipeline migrasi secara umum.&lt;/p>
&lt;pre class="mermaid">
flowchart LR
WPDB[&amp;#34;Database WP&amp;#34;] --&amp;gt;|Plugin| Exporter[&amp;#34;Alat Ekspor&amp;#34;]
Exporter --&amp;gt;| Mengekstrak Teks, \nMeta, Gambar | ZipFile[&amp;#34;File Zip / Folder&amp;#34;]
ZipFile --&amp;gt;|Unpack| MarkdownFiles[&amp;#34;File Markdown \n(content/)&amp;#34;]
ZipFile --&amp;gt;|Unpack| ImageFiles[&amp;#34;Gambar \n(static/wp-content/)&amp;#34;]
MarkdownFiles --&amp;gt; Formatting[&amp;#34;Tinjau &amp;amp; Format \n(Perbaiki Shortcode)&amp;#34;]
Formatting --&amp;gt; Git[&amp;#34;Commit ke Git&amp;#34;]
&lt;/pre>
&lt;h3 id="41-ekstraksi-data-dan-konversi-ke-markdown">4.1 Ekstraksi Data dan Konversi ke Markdown
&lt;/h3>&lt;p>Untuk mengeluarkan data WordPress untuk Hugo, cara termudah dan paling dapat diandalkan adalah dengan menggunakan plugin khusus. Berikut ini beberapa pendekatan yang umum digunakan.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Menggunakan plugin Jekyll Exporter&lt;/strong>
Karena Hugo memiliki struktur data yang sangat mirip dengan Jekyll (yang juga merupakan SSG), merupakan metode umum untuk menggunakan plugin &amp;ldquo;Jekyll Exporter&amp;rdquo; untuk WordPress. Saat Anda menginstal dan menjalankan plugin ini, semua postingan dan halaman statis akan diubah menjadi file Markdown dengan Front Matter, dan dapat diunduh sebagai file ZIP bersama dengan kumpulan file gambar.&lt;/li>
&lt;li>&lt;strong>Skrip buatan sendiri menggunakan API WordPress&lt;/strong>
Ini adalah metode untuk membuat skrip sendiri menggunakan Python atau Node.js dll. untuk memanggil REST API WordPress (&lt;code>/wp-json/wp/v2/posts&lt;/code>), mengurai data JSON, dan membuat file Markdown sendiri. Ini efektif untuk situs yang banyak menggunakan bidang khusus kompleks (seperti ACF) yang tidak dapat ditangani oleh plugin.&lt;/li>
&lt;li>&lt;strong>Memanfaatkan alat wp2hugo&lt;/strong>
Ada juga pendekatan yang menggunakan alat CLI yang ditulis dalam bahasa Go dll. untuk mengubah secara langsung dari file XML ekspor WordPress (WXR) ke format Hugo.&lt;/li>
&lt;/ol>
&lt;h3 id="42-mempertahankan-struktur-permalink-url">4.2 Mempertahankan Struktur Permalink (URL)
&lt;/h3>&lt;p>Sangat penting untuk mempertahankan URL dari era WordPress apa adanya demi melanjutkan evaluasi SEO. Jika Anda menggunakan pengaturan permalink seperti &lt;code>https://example.com/2026/09/13/my-post/&lt;/code> di WordPress, tentukan struktur permalink di &lt;code>hugo.toml&lt;/code> Hugo.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-toml" data-lang="toml">&lt;span class="line">&lt;span class="cl">&lt;span class="p">[&lt;/span>&lt;span class="nx">permalinks&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">post&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;/:year/:month/:day/:slug/&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Atau, dimungkinkan juga untuk menetapkan URL secara paksa dengan menentukan parameter &lt;code>url&lt;/code> secara langsung di dalam Front Matter untuk setiap artikel.
Lebih lanjut, untuk halaman yang URL-nya berubah, siapkan pengalihan (redirect) menggunakan &lt;code>aliases&lt;/code> yang disebutkan sebelumnya.&lt;/p>
&lt;h3 id="43-konversi-shortcode">4.3 Konversi Shortcode
&lt;/h3>&lt;p>Shortcode khusus WordPress (contoh: &lt;code>[gallery]&lt;/code>, &lt;code>[caption]&lt;/code>, kode unik dari berbagai plugin) sering kali tertinggal dalam bentuk string aslinya saat diekspor, sehingga perlu ditangani.
Ini dapat dihapus sekaligus menggunakan skrip pengganti (sed atau Python), atau dipindahkan sehingga dirender dengan benar di sisi Hugo dengan memanfaatkan &lt;strong>fitur shortcode kustom&lt;/strong> Hugo yang kuat (membuat tata letak (layout) sendiri di dalam &lt;code>layouts/shortcodes/&lt;/code>).&lt;/p>
&lt;hr>
&lt;h2 id="5-alat-cli-hugo-serta-proses-build-dan-deploy">5. Alat CLI Hugo serta Proses Build dan Deploy
&lt;/h2>&lt;p>Setelah proses migrasi selesai, saatnya menggunakan Hugo untuk mem-build situs dan mempublikasikannya ke dunia. Tersedia sebagai biner bahasa Go, Hugo menawarkan kecepatan yang luar biasa, mampu menyelesaikan build hanya dalam beberapa detik bahkan untuk situs dengan ribuan hingga puluhan ribu halaman.&lt;/p>
&lt;h3 id="51-memulai-server-untuk-pengembangan-lokal">5.1 Memulai Server untuk Pengembangan Lokal
&lt;/h3>&lt;p>Saat menulis artikel atau menyesuaikan desain, mulai server lokal.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Perintah untuk memulai server pengembangan (gunakan -D untuk menyertakan artikel Draft)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">hugo server -D
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Saat Anda menjalankan perintah ini, situs akan dapat dipratinjau di &lt;code>http://localhost:1313/&lt;/code>. Hugo memiliki fitur &amp;ldquo;LiveReload&amp;rdquo; bawaan yang kuat; begitu Anda mengedit dan menyimpan file Markdown, template, atau CSS, layar browser akan secara otomatis diperbarui dengan sangat cepat. Oleh karena itu, pengalaman menulis dan mengembangkan jauh lebih nyaman daripada dasbor manajemen WordPress.&lt;/p>
&lt;h3 id="52-build-untuk-produksi-dan-optimasi-kinerja">5.2 Build untuk Produksi dan Optimasi Kinerja
&lt;/h3>&lt;p>Untuk menghasilkan file statis untuk di-deploy ke lingkungan produksi, cukup ketik &lt;code>hugo&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Menjalankan build produksi. Perkecil HTML/CSS/JS dengan opsi --minify&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">hugo --minify
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Perintah ini menampilkan file seluruh situs ke dalam direktori &lt;code>public/&lt;/code>. Dengan menambahkan opsi &lt;code>--minify&lt;/code>, baris baru dan spasi yang tidak perlu akan dihapus, sehingga ukuran file akan semakin dikurangi. Ini berkontribusi langsung pada pengurangan latensi jaringan ($T_{network}$) dalam model matematika yang disebutkan sebelumnya.&lt;/p>
&lt;h3 id="53-otomatisasi-deploy-cicd">5.3 Otomatisasi Deploy (CI/CD)
&lt;/h3>&lt;p>Menghasilkan file statis setiap kali di PC lokal dan mengunggahnya melalui FTP dll. tidaklah efisien. Dalam operasi SSG modern, praktik terbaik adalah membangun lingkungan CI/CD yang secara otomatis melakukan build dan deploy dengan memanfaatkan push ke repositori Git (seperti GitHub) sebagai pemicu (trigger).&lt;/p>
&lt;p>Sebagai contoh, bentuk dasar pengaturan (file YAML) untuk men-deploy ke Cloudflare Pages atau GitHub Pages menggunakan GitHub Actions adalah sebagai berikut.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Contoh .github/workflows/hugo.yml&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Deploy Hugo site to GitHub Pages&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">on&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">push&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">branches&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;main&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">workflow_dispatch&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">permissions&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">contents&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">read&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">pages&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">write&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">id-token&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">write&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">jobs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">build&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">runs-on&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ubuntu-latest&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">steps&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Checkout&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">uses&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">actions/checkout@v3&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">with&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">submodules&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">recursive&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># Jika tema dikelola sebagai submodul&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">fetch-depth&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">0&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Setup Hugo&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">uses&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">peaceiris/actions-hugo@v2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">with&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">hugo-version&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;latest&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">extended&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Build&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">run&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">hugo --minify&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Upload artifact&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">uses&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">actions/upload-pages-artifact@v2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">with&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">path&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">./public&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">deploy&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">environment&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">github-pages&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">url&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">${{ steps.deployment.outputs.page_url }}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">runs-on&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ubuntu-latest&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">needs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">build&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">steps&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Deploy to GitHub Pages&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">id&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">deployment&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">uses&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">actions/deploy-pages@v2&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Dengan mengatur seperti ini, pipeline otomatisasi telah selesai di mana situs terbaru dipublikasikan ke lingkungan produksi hanya dalam beberapa menit hanya dengan tindakan &amp;ldquo;menulis artikel di Markdown dan Push ke GitHub&amp;rdquo;.&lt;/p>
&lt;hr>
&lt;h2 id="6-keuntungan-seo-dan-operasional-setelah-migrasi">6. Keuntungan SEO dan Operasional setelah Migrasi
&lt;/h2>&lt;p>Operator situs yang telah menyelesaikan migrasi dari WordPress ke Hugo sering menyadari tiga keuntungan signifikan berikut:&lt;/p>
&lt;h3 id="61-peningkatan-drastis-pada-kecepatan-situs-dan-core-web-vitals">6.1 Peningkatan Drastis pada Kecepatan Situs dan Core Web Vitals
&lt;/h3>&lt;p>Sebagai hasil dari penghapusan kueri database dan rendering sisi server, waktu pemuatan halaman berkurang hingga hitungan milidetik. Ini secara langsung mengarah pada peningkatan skor &amp;ldquo;Core Web Vitals&amp;rdquo; (LCP, FID/INP, CLS) yang substansial yang merupakan faktor peringkat Google. Anda dapat mengharapkan penurunan rasio pentalan (bounce rate) pengguna dan peningkatan penilaian SEO.&lt;/p>
&lt;h3 id="62-bebas-dari-ancaman-keamanan">6.2 Bebas dari Ancaman Keamanan
&lt;/h3>&lt;p>Karena WordPress digunakan secara luas di seluruh dunia, ia sering menjadi target serangan. Selalu ada risiko kerusakan dengan memanfaatkan kerentanan plugin, maupun pembobolan login melalui serangan brute force.
Namun, situs statis yang dihasilkan oleh Hugo tidak memiliki database, tidak ada lingkungan PHP, bahkan tidak memiliki dasbor manajemen (formulir login). Tidak ada ruang bagi peretas (hacker) untuk menyusup ke server dan memodifikasi database, sehingga risiko keamanan diturunkan mendekati nol hingga batas maksimal.&lt;/p>
&lt;h3 id="63-operasi-bebas-pemeliharaan-maintenance-free">6.3 Operasi Bebas Pemeliharaan (Maintenance-free)
&lt;/h3>&lt;p>Dalam menjalankan WordPress, pekerjaan pemeliharaan yang konstan sangat diperlukan, seperti memutakhirkan inti WordPress, memperbarui plugin, dan mengikuti versi PHP. Anda harus selalu khawatir akan risiko situs menjadi rusak karena masalah kompatibilitas.
Dalam kasus Hugo, alat itu sendiri hanya perlu diperbarui jika perlu, dan kode situs itu sendiri adalah kumpulan file teks independen, yang memberikan rasa aman yang luar biasa bahwa situs &amp;ldquo;tidak akan rusak bahkan jika dibiarkan&amp;rdquo;.&lt;/p>
&lt;hr>
&lt;h2 id="7-kesimpulan">7. Kesimpulan
&lt;/h2>&lt;p>Dalam artikel ini, kami telah menjelaskan secara terperinci tentang migrasi dari CMS dinamis seperti WordPress ke &amp;ldquo;Hugo&amp;rdquo;, generator situs statis yang kuat berbasis bahasa Go, mulai dari perbedaan arsitektur teknis, pembuktian kinerja dengan model matematika, hingga prosedur migrasi yang spesifik.&lt;/p>
&lt;p>Migrasi ke generator situs statis memang memerlukan biaya pembelajaran awal (seperti operasi Git, sintaks Markdown, menjalankan perintah CLI dari terminal, memahami spesifikasi mesin template, dll.), tetapi akan memberikan imbal hasil (return) yang lebih dari sekadar menggantikannya, seperti &amp;ldquo;kecepatan tampilan yang luar biasa&amp;rdquo;, &amp;ldquo;keamanan yang tangguh&amp;rdquo;, dan &amp;ldquo;bebas dari pemeliharaan&amp;rdquo;.&lt;/p>
&lt;p>Jika situs web Anda tidak memerlukan perubahan desain yang sering atau proses dinamis yang kompleks (seperti fungsi khusus anggota atau fitur e-commerce lanjutan) dan utamanya bertujuan untuk mendistribusikan informasi (seperti blog, media, atau situs web perusahaan), maka migrasi ke Hugo akan menjadi salah satu investasi teknis yang paling efektif. Silakan gunakan artikel ini sebagai referensi dan ambil langkah pertama menuju operasi situs web generasi berikutnya menggunakan Hugo.&lt;/p></description></item><item><title>Blog Teknologi dengan Markdown: Pengaturan Editor untuk Menggandakan Kecepatan Menulis</title><link>http://kenji.blog/id/p/markdown-editor-setup-for-tech-blogs/</link><pubDate>Sat, 12 Sep 2026 12:00:00 +0900</pubDate><guid>http://kenji.blog/id/p/markdown-editor-setup-for-tech-blogs/</guid><description>&lt;img src="http://kenji.blog/p/markdown-editor-setup-for-tech-blogs/img/eyecatch.jpg" alt="Featured image of post Blog Teknologi dengan Markdown: Pengaturan Editor untuk Menggandakan Kecepatan Menulis" />&lt;p>Untuk terus menulis blog teknologi, pengoptimalan lingkungan penulisan sangatlah penting. Artikel ini akan membahas secara mendalam pengaturan editor tingkat lanjut yang dapat meningkatkan kecepatan penulisan blog teknologi menggunakan Markdown secara drastis. Kita akan membahas secara komprehensif mulai dari penyesuaian ekstrem Visual Studio Code (VS Code) dan Neovim, pemanfaatan snippet, pengenalan textlint sebagai alat pemeriksa tata bahasa hingga otomatisasi dalam pipeline CI/CD, dan teknik penulisan mutakhir memanfaatkan LLM seperti GitHub Copilot.&lt;/p>
&lt;h2 id="1-model-matematis-peningkatan-kecepatan-menulis">1. Model Matematis Peningkatan Kecepatan Menulis
&lt;/h2>&lt;p>Mari kita buat model dengan rumus sederhana untuk melihat seberapa besar pengaruh pengoptimalan pengaturan editor terhadap waktu penulisan. Misalkan total waktu pengetikan saat menulis satu artikel blog adalah $T_{total}$.&lt;/p>
$$
T_{total} = T_{think} + T_{type} + T_{format} + T_{review}
$$&lt;p>Di sini, $T_{think}$ adalah waktu berpikir, $T_{type}$ adalah waktu mengetik, $T_{format}$ adalah waktu penyesuaian format seperti Markdown, dan $T_{review}$ adalah waktu revisi dan koreksi.&lt;/p>
&lt;p>Waktu yang dihemat $T_{saved}$ melalui penyesuaian editor (seperti penggunaan snippet dan pengaturan Linter) dapat diekspresikan sebagai berikut, menggunakan jumlah kemunculan $N$ dari pola tertentu (misalnya, shortcode Hugo atau tabel Markdown), waktu yang dibutuhkan untuk pengetikan manual $t_{manual}$, dan waktu yang dibutuhkan jika diotomatisasi dengan snippet $t_{snippet}$.&lt;/p>
$$
T_{saved} = \sum_{i=1}^{k} N_i \times (t_{manual, i} - t_{snippet, i}) + T_{review\_saved}
$$&lt;p>Selanjutnya, dengan memperkenalkan pemformat otomatis dan alat Lint, waktu pemeriksaan visual oleh manusia $T_{review}$ berkurang secara signifikan. Memaksimalkan $T_{saved}$ inilah yang menjadi tujuan dari artikel ini.&lt;/p>
&lt;h2 id="2-pengaturan-terkuat-visual-studio-code-vs-code">2. Pengaturan Terkuat Visual Studio Code (VS Code)
&lt;/h2>&lt;p>VS Code saat ini adalah salah satu editor yang paling banyak digunakan dan memiliki ekosistem ekstensi yang kuat untuk penulisan Markdown.&lt;/p>
&lt;h3 id="ekstensi-yang-direkomendasikan">Ekstensi yang Direkomendasikan
&lt;/h3>&lt;p>Untuk mempercepat penulisan, sangat disarankan untuk menginstal ekstensi berikut:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Markdown All in One&lt;/strong>: Menyediakan semua fitur dasar yang diperlukan untuk penulisan Markdown, seperti cetak tebal/miring dengan tombol pintasan, kelanjutan daftar otomatis, dan pembuatan daftar isi (TOC) otomatis.&lt;/li>
&lt;li>&lt;strong>markdownlint&lt;/strong>: Memperingatkan kesalahan sintaks dan pelanggaran gaya Markdown secara real-time.&lt;/li>
&lt;li>&lt;strong>vscode-textlint&lt;/strong>: Menerapkan set aturan untuk dokumen teknis guna mencegah ketidakkonsistenan ejaan dan kesalahan tata bahasa.&lt;/li>
&lt;/ol>
&lt;h3 id="pengaturan-snippet-khusus-untuk-hugo-markdownjson">Pengaturan Snippet Khusus untuk Hugo (&lt;code>markdown.json&lt;/code>)
&lt;/h3>&lt;p>Jika Anda menggunakan generator situs statis seperti Hugo atau Docusaurus untuk blog teknologi, Anda akan sering memasukkan Frontmatter atau shortcode kustom. Menggunakan fitur snippet VS Code, ini dapat dikembangkan dalam sekejap.&lt;/p>
&lt;p>Pilih &lt;code>Preferences: Configure User Snippets&lt;/code> dari Command Palette dan tambahkan pengaturan berikut ke &lt;code>markdown.json&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;Hugo Frontmatter&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;prefix&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;frontmatter&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;body&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;---&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;title: \&amp;#34;${1:Judul}\&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;slug: \&amp;#34;${2:slug-name}\&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;date: \&amp;#34;$CURRENT_YEAR-$CURRENT_MONTH-$CURRENT_DATE T$CURRENT_HOUR:$CURRENT_MINUTE:$CURRENT_SECOND+09:00\&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;image: \&amp;#34;img/eyecatch.jpg\&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;math: true&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;mermaid: true&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;categories: [\&amp;#34;${3:Category}\&amp;#34;]&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;tags: [\&amp;#34;${4:Tag1}\&amp;#34;, \&amp;#34;${5:Tag2}\&amp;#34;]&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;---&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;${0}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;description&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Mengembangkan YAML Frontmatter untuk Hugo&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;Hugo Figure Shortcode&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;prefix&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;hfig&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;body&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;{{&amp;lt; figure src=\&amp;#34;${1:image.jpg}\&amp;#34; title=\&amp;#34;${2:Judul Gambar}\&amp;#34; &amp;gt;}}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;description&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Shortcode Figure Hugo&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;Markdown Table&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;prefix&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;mtable&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;body&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;| ${1:Header 1} | ${2:Header 2} | ${3:Header 3} |&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;| :--- | :---: | ---: |&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;| ${4:Row 1} | ${5:Data} | ${6:Data} |&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;| ${7:Row 2} | ${8:Data} | ${9:Data} |&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;$0&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;description&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Menghasilkan tabel Markdown 3 kolom&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Dengan pengaturan ini, hanya dengan mengetik &lt;code>frontmatter&lt;/code> dan menekan tombol Tab, YAML Frontmatter termasuk waktu saat ini akan langsung dikembangkan, dan kecepatan awal penulisan akan meningkat drastis.&lt;/p>
&lt;h3 id="bantuan-penulisan-memanfaatkan-github-copilot">Bantuan Penulisan Memanfaatkan GitHub Copilot
&lt;/h3>&lt;p>Jika GitHub Copilot diaktifkan di VS Code, penyelesaian AI berdasarkan konteks juga berfungsi dalam Markdown. Khususnya untuk blog teknologi, AI dapat mengantisipasi dan menyarankan &amp;ldquo;struktur selanjutnya yang harus dijelaskan&amp;rdquo; atau &amp;ldquo;blok kode terkait&amp;rdquo;, sehingga waktu mengetik $T_{type}$ dapat dikurangi secara signifikan.&lt;/p>
&lt;h2 id="3-penyesuaian-ekstrem-di-neovim">3. Penyesuaian Ekstrem di Neovim
&lt;/h2>&lt;p>Meskipun GUI VS Code sangat bagus, bagi penggemar terminal dan Vimmer, Neovim adalah pilihan terkuat yang memungkinkan semuanya diselesaikan tanpa melepaskan tangan dari keyboard sama sekali.&lt;/p>
&lt;h3 id="arsitektur-lsp-neovim">Arsitektur LSP Neovim
&lt;/h3>&lt;p>Arsitektur LSP (Language Server Protocol) dan Linter untuk Neovim di lingkungan Markdown adalah sebagai berikut.&lt;/p>
&lt;pre class="mermaid">
classDiagram
class Neovim {
+&amp;#34;Buffer Teks&amp;#34;
+&amp;#34;Peta Tombol&amp;#34;
}
class nvim_lspconfig {
+&amp;#34;marksman (Markdown LSP)&amp;#34;
}
class null_ls_or_none_ls {
+&amp;#34;markdownlint&amp;#34;
+&amp;#34;textlint&amp;#34;
}
class LuaSnip {
+&amp;#34;Snippet Dinamis&amp;#34;
}
class CMP {
+&amp;#34;Mesin Penyelesaian Otomatis&amp;#34;
}
Neovim --&amp;gt; nvim_lspconfig : &amp;#34;Menyediakan fitur semantik&amp;#34;
Neovim --&amp;gt; null_ls_or_none_ls : &amp;#34;Diagnostik &amp;amp; Pemformatan&amp;#34;
Neovim --&amp;gt; CMP : &amp;#34;Permintaan Penyelesaian&amp;#34;
CMP --&amp;gt; nvim_lspconfig : &amp;#34;Sumber LSP&amp;#34;
CMP --&amp;gt; LuaSnip : &amp;#34;Sumber Snippet&amp;#34;
&lt;/pre>
&lt;h3 id="ekspansi-snippet-tingkat-lanjut-menggunakan-luasnip">Ekspansi Snippet Tingkat Lanjut Menggunakan LuaSnip
&lt;/h3>&lt;p>Lebih kuat dari snippet JSON VS Code adalah plugin Neovim yaitu &lt;code>LuaSnip&lt;/code>. Menggunakan logika Lua, Anda dapat menghitung dan mengembangkan konten snippet secara dinamis.&lt;/p>
&lt;p>Berikut adalah contoh pengaturan LuaSnip yang mengambil tanggal dan waktu saat ini secara dinamis dan mengembangkan Frontmatter Hugo.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-lua" data-lang="lua">&lt;span class="line">&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="n">ls&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">require&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;luasnip&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="n">s&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ls.snippet&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="n">t&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ls.text_node&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ls.insert_node&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="n">f&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ls.function_node&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">-- Fungsi untuk mendapatkan waktu JST saat ini&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kd">local&lt;/span> &lt;span class="kr">function&lt;/span> &lt;span class="nf">get_current_date_jst&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kr">return&lt;/span> &lt;span class="n">os.date&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;!%Y-%m-%dT%H:%M:%S&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">..&lt;/span> &lt;span class="s2">&amp;#34;+09:00&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kr">end&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">ls.add_snippets&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;markdown&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">s&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;frontmatter&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">t&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;---&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;title: &lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">}),&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;Judul&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;slug: &lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">}),&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;slug-name&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;date: &lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">}),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">f&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kr">function&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="kr">return&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="n">get_current_date_jst&lt;/span>&lt;span class="p">()}&lt;/span> &lt;span class="kr">end&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{}),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">t&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;image: &lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">img/eyecatch.jpg&lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;math: true&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;mermaid: true&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;categories: [&lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">}),&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;Category&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">]&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;tags: [&lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">}),&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;Tag&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\&amp;#34;&lt;/span>&lt;span class="s2">]&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;---&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">}),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">i&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">s&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;mtable&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">t&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34;| &amp;#34;&lt;/span>&lt;span class="p">}),&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;Header 1&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34; | &amp;#34;&lt;/span>&lt;span class="p">}),&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;Header 2&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34; |&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;|---|---|&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;| &amp;#34;&lt;/span>&lt;span class="p">}),&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;Cell 1&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34; | &amp;#34;&lt;/span>&lt;span class="p">}),&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;Cell 2&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s2">&amp;#34; |&amp;#34;&lt;/span>&lt;span class="p">}),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Dengan cara ini, dengan meminjam kekuatan bahasa pemrograman (Lua), dimungkinkan untuk membuat snippet kompleks yang tidak hanya menyisipkan string tetap, tetapi juga menyematkan nilai kembalian fungsi atau mengubah jumlah kolom tabel secara dinamis sesuai dengan input.&lt;/p>
&lt;h2 id="4-analisis-statis-yang-menyeimbangkan-kualitas-dan-kecepatan-penulisan-textlint-dan-ekspresi-reguler">4. Analisis Statis yang Menyeimbangkan Kualitas dan Kecepatan Penulisan (textlint dan Ekspresi Reguler)
&lt;/h2>&lt;p>Untuk menjamin kualitas blog, perlu untuk mencegah kesalahan ketik dan ketidakkonsistenan ejaan. Melakukan ini secara manual akan menyebabkan $T_{review}$ meningkat tajam, jadi kita akan memperkenalkan analisis statis menggunakan &lt;code>textlint&lt;/code>.&lt;/p>
&lt;h3 id="pengenalan-textlint-dan-set-aturan">Pengenalan textlint dan Set Aturan
&lt;/h3>&lt;p>Instal textlint di lingkungan Node.js.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">npm install -D textlint textlint-rule-preset-ja-technical-writing textlint-rule-prh textlint-filter-rule-comments
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Buat &lt;code>.textlintrc.json&lt;/code> di root proyek dan atur seperti berikut.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-json" data-lang="json">&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;filters&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;comments&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">true&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;rules&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;preset-ja-technical-writing&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;ja-no-mixed-period&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;periodMark&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;sentence-length&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;max&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">100&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;prh&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nt">&amp;#34;rulePaths&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;./prh.yml&amp;#34;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Buat &lt;code>prh.yml&lt;/code> dan definisikan ketidakkonsistenan ejaan istilah teknis. Misalnya, menyatukan &amp;ldquo;Server&amp;rdquo; dan &amp;ldquo;Peladen&amp;rdquo;, &amp;ldquo;Javascript&amp;rdquo; dan &amp;ldquo;JavaScript&amp;rdquo;, dll.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">version&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">1&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">rules&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">expected&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;JavaScript&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">pattern&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;Javascript&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">expected&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;Server&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">pattern&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;Peladen&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">expected&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;Antarmuka&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">pattern&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;Antar muka&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Dengan ini, setiap kali Anda mengetik di editor, ketidakkonsistenan ejaan akan diperingatkan secara real-time, dan waktu koreksi akan menjadi hampir nol.&lt;/p>
&lt;h3 id="penggantian-massal-dengan-ekspresi-reguler-dan-pola-terstruktur">Penggantian Massal dengan Ekspresi Reguler dan Pola Terstruktur
&lt;/h3>&lt;p>Saat memigrasi artikel yang ada ke Markdown atau menempelkan teks dari luar, penggantian massal dengan ekspresi reguler sangat berguna.&lt;/p>
&lt;p>Misalnya, ekspresi reguler untuk mengubah tag &lt;code>&amp;lt;b&amp;gt;tebal&amp;lt;/b&amp;gt;&lt;/code> HTML menjadi &lt;code>**tebal**&lt;/code> Markdown:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Pola pencarian&lt;/strong>: &lt;code>&amp;lt;b&amp;gt;(.*?)&amp;lt;/b&amp;gt;&lt;/code>&lt;/li>
&lt;li>&lt;strong>Pola penggantian&lt;/strong>: &lt;code>**$1**&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>Saat menggabungkan baris baru berturut-turut yang tidak perlu menjadi satu:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Pola pencarian&lt;/strong>: &lt;code>\n{3,}&lt;/code>&lt;/li>
&lt;li>&lt;strong>Pola penggantian&lt;/strong>: &lt;code>\n\n&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>Dengan menjalankan ini melalui fitur cari &amp;amp; ganti (mode ekspresi reguler) VS Code atau perintah &lt;code>%s&lt;/code> Neovim (&lt;code>:%s/&amp;lt;b&amp;gt;\(.*?\)&amp;lt;\/b&amp;gt;/**\1**/g&lt;/code>), Anda dapat menyatukan format dalam sekejap.&lt;/p>
&lt;h3 id="pemeriksaan-otomatis-oleh-pipeline-cicd">Pemeriksaan Otomatis oleh Pipeline CI/CD
&lt;/h3>&lt;p>Selain itu, menggunakan GitHub Actions, kami membangun pipeline CI di mana textlint berjalan secara otomatis saat Anda melakukan push artikel blog. Hal ini dapat mencegah publikasi artikel yang memiliki pelanggaran aturan.&lt;/p>
&lt;pre class="mermaid">
flowchart TD
A[&amp;#34;Penulis&amp;#34;] --&amp;gt;|Dorong perubahan| B[&amp;#34;Repositori GitHub&amp;#34;]
B --&amp;gt; C{&amp;#34;GitHub Actions Dipicu&amp;#34;}
C --&amp;gt; D[&amp;#34;Checkout Repositori&amp;#34;]
D --&amp;gt; E[&amp;#34;Setup Node.js&amp;#34;]
E --&amp;gt; F[&amp;#34;npm install&amp;#34;]
F --&amp;gt; G[&amp;#34;Jalankan textlint&amp;#34;]
G --&amp;gt;|Lulus| H[&amp;#34;Bangun Situs Hugo&amp;#34;]
G --&amp;gt;|Gagal| I[&amp;#34;Laporkan Kesalahan ke PR/Commit&amp;#34;]
H --&amp;gt; J[&amp;#34;Terapkan ke Hosting (Vercel/Netlify)&amp;#34;]
&lt;/pre>
&lt;h2 id="5-teknik-penulisan-markdown-di-era-llm">5. Teknik Penulisan Markdown di Era LLM
&lt;/h2>&lt;p>Dalam penulisan blog teknologi modern, pemanfaatan LLM (Large Language Model) tidak bisa dihindari. Dengan memanfaatkan alat AI bawaan editor, kecepatan penulisan akan berlipat ganda.&lt;/p>
&lt;h3 id="rekayasa-prompt-di-dalam-editor">Rekayasa Prompt di Dalam Editor
&lt;/h3>&lt;p>Menggunakan GitHub Copilot Chat di VS Code atau &lt;code>ChatGPT.nvim&lt;/code> dan &lt;code>Copilot.vim&lt;/code> di Neovim, Anda dapat memberikan prompt seperti berikut tanpa meninggalkan editor.&lt;/p>
&lt;blockquote>
&lt;p>&amp;ldquo;Buatkan kerangka struktur hierarki Markdown untuk pemula tentang elemen teknologi berikut: Docker, Kubernetes, CI/CD&amp;rdquo;&lt;/p>
&lt;/blockquote>
&lt;p>Kemudian, Markdown untuk judul dan poin-poin akan dihasilkan seketika. Kita hanya perlu menambahkan detail ke dalam kerangka kerja tersebut.&lt;/p>
&lt;p>Selain itu, untuk pembuatan diagram Mermaid yang kompleks dan rumus matematika (LaTeX), memberikan instruksi kepada AI akan menghasilkan sintaks yang akurat. Misalnya, tata letak rumus matematika dan diagram yang ditampilkan dalam artikel ini juga dipercepat melalui penulisan berpasangan (pair writing) dengan LLM.&lt;/p>
&lt;h2 id="6-kesimpulan">6. Kesimpulan
&lt;/h2>&lt;p>Kami telah menjelaskan pengaturan editor yang dapat menggandakan kecepatan penulisan saat menulis blog teknologi dengan Markdown.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Kesadaran akan model matematis&lt;/strong>: Membasmi tugas berulang untuk memaksimalkan $T_{saved}$.&lt;/li>
&lt;li>&lt;strong>Pemanfaatan VS Code&lt;/strong>: Menghemat input dengan ekstensi dan snippet &lt;code>markdown.json&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Penyesuaian ekstrem Neovim&lt;/strong>: Snippet dinamis oleh &lt;code>LuaSnip&lt;/code> dan operasi keyboard penuh.&lt;/li>
&lt;li>&lt;strong>textlint dan analisis statis&lt;/strong>: Integrasi CI/CD dan Linter lokal untuk mendekati waktu koreksi ke nol.&lt;/li>
&lt;li>&lt;strong>Integrasi LLM&lt;/strong>: Membuat AI secara langsung menghasilkan struktur Markdown dan kode diagram di dalam editor.&lt;/li>
&lt;/ol>
&lt;p>Dengan memasukkan pengaturan ini ke dalam lingkungan Anda sendiri, &amp;ldquo;kerepotan&amp;rdquo; menulis akan hilang, dan kuantitas serta kualitas output teknis akan meningkat secara dramatis. Bagaimana kalau memulainya bahkan dari satu pendaftaran snippet kecil?&lt;/p></description></item><item><title>Cara Menghosting Blog Hugo Secara Gratis dan Super Cepat di Cloudflare Pages atau GitHub Pages</title><link>http://kenji.blog/id/p/hugo-hosting-cloudflare-vs-github-pages/</link><pubDate>Sat, 12 Sep 2026 12:00:00 +0900</pubDate><guid>http://kenji.blog/id/p/hugo-hosting-cloudflare-vs-github-pages/</guid><description>&lt;img src="http://kenji.blog/p/hugo-hosting-cloudflare-vs-github-pages/img/eyecatch.jpg" alt="Featured image of post Cara Menghosting Blog Hugo Secara Gratis dan Super Cepat di Cloudflare Pages atau GitHub Pages" />&lt;p>Dalam mengelola situs web atau blog, kecepatan pemuatan (kinerja), biaya operasional, dan keamanan adalah faktor yang sangat penting. Di masa lalu, kombinasi CMS (Content Management System) dinamis seperti WordPress dan server sewaan adalah yang utama, tetapi saat ini, arsitektur yang disebut &amp;ldquo;Jamstack&amp;rdquo; menarik banyak perhatian. Di antaranya, menggabungkan &amp;ldquo;Hugo&amp;rdquo;, generator situs statis (SSG) super cepat yang dibuat dalam bahasa Go, dengan layanan hosting modern seperti Cloudflare Pages atau GitHub Pages memungkinkan Anda membangun lingkungan blog yang &lt;strong>sepenuhnya gratis dan sangat cepat&lt;/strong>.&lt;/p>
&lt;p>Artikel ini akan membahas secara mendalam dari perspektif teknis langkah-langkah spesifik untuk memublikasikan situs statis berbasis Hugo di Cloudflare Pages atau GitHub Pages, perbedaan arsitektur di setiap platform, pengaturan CI/CD (Continuous Integration / Continuous Deployment) menggunakan GitHub Actions, pengoptimalan DNS, strategi cache, hingga penerapan analisis akses yang mengutamakan privasi.&lt;/p>
&lt;hr>
&lt;h2 id="1-dasar-dasar-generator-situs-statis-ssg-dan-jamstack">1. Dasar-dasar Generator Situs Statis (SSG) dan Jamstack
&lt;/h2>&lt;h3 id="11-mengapa-situs-statis">1.1 Mengapa Situs Statis?
&lt;/h3>&lt;p>CMS dinamis konvensional (misalnya WordPress) menjalankan kueri ke basis data (seperti MySQL) setiap kali ada permintaan dari pengguna, kemudian secara dinamis menghasilkan HTML di sisi server (seperti PHP) dan mengembalikannya. Metode ini menawarkan fleksibilitas tinggi, namun kurang tahan terhadap lonjakan lalu lintas yang tiba-tiba (seperti saat viral atau serangan DDoS), dan arsitektur infrastrukturnya cenderung menjadi rumit karena memerlukan server cache (seperti Redis atau Varnish) di bagian depan.&lt;/p>
&lt;p>Sebaliknya, Generator Situs Statis (SSG) yang mengadopsi arsitektur Jamstack (JavaScript, APIs, and Markup) akan menghasilkan (saat proses build) seluruh file HTML, CSS, dan JavaScript terlebih dahulu. Untuk setiap permintaan pengguna, server web (atau CDN) hanya akan mengembalikan file statis yang sudah dihasilkan tersebut, sehingga mampu memberikan kecepatan luar biasa dan keamanan yang kuat.&lt;/p>
&lt;h3 id="12-keunggulan-hugo">1.2 Keunggulan Hugo
&lt;/h3>&lt;p>Ada berbagai pilihan SSG seperti Next.js, Gatsby, Jekyll, dan Astro, namun fitur utama Hugo adalah &lt;strong>kecepatan build-nya&lt;/strong>. Berkat pemrosesan konkurensi (pemrosesan paralel) dari bahasa Go, build dapat diselesaikan hanya dalam beberapa detik meskipun situs tersebut memiliki ribuan hingga puluhan ribu halaman. Hal ini secara signifikan mengurangi waktu tunggu pada pipeline CI/CD dan secara langsung meningkatkan pengalaman developer (DX: Developer Experience).&lt;/p>
&lt;hr>
&lt;h2 id="2-perbandingan-arsitektur-layanan-hosting">2. Perbandingan Arsitektur Layanan Hosting
&lt;/h2>&lt;p>Tantangan selanjutnya adalah di mana Anda akan menghosting file statis yang dihasilkan oleh Hugo. Pilihan yang umum di antaranya adalah Cloudflare Pages, GitHub Pages, dan Netlify, masing-masing memiliki arsitektur jaringan yang berbeda di balik layarnya.&lt;/p>
&lt;h3 id="21-cdn-dan-komputasi-edge-edge-computing">2.1 CDN dan Komputasi Edge (Edge Computing)
&lt;/h3>&lt;p>Semua platform ini mendistribusikan konten menggunakan CDN (Content Delivery Network) yang tersebar secara global. Namun, faktor pembedanya bukanlah sekadar menyimpan cache file statis, melainkan apakah mereka mampu mengeksekusi routing permintaan atau memodifikasi header di PoP (Point of Presence) terdekat dengan pengguna melalui &amp;ldquo;komputasi edge&amp;rdquo;.&lt;/p>
&lt;pre class="mermaid">
graph TD
A[&amp;#34;Pengguna (Tokyo)&amp;#34;] --&amp;gt;|Latensi Rendah| B[&amp;#34;Node Edge (NRT)&amp;#34;]
C[&amp;#34;Pengguna (New York)&amp;#34;] --&amp;gt;|Latensi Rendah| D[&amp;#34;Node Edge (EWR)&amp;#34;]
E[&amp;#34;Pengguna (London)&amp;#34;] --&amp;gt;|Latensi Rendah| F[&amp;#34;Node Edge (LHR)&amp;#34;]
B --&amp;gt; G[&amp;#34;Penyimpanan Origin / Object Store&amp;#34;]
D --&amp;gt; G
F --&amp;gt; G
&lt;/pre>
&lt;h3 id="22-github-pages">2.2 GitHub Pages
&lt;/h3>&lt;p>GitHub Pages adalah layanan yang memungkinkan Anda mempublikasikan file HTML, CSS, dan JavaScript langsung dari repositori GitHub. Di belakangnya digunakan CDN seperti Fastly, yang memberikan kinerja yang memadai. Namun, fungsi infrastruktur murninya agak terbatas, karena terdapat batasan dalam menyesuaikan header (misalnya mengatur &lt;code>Cache-Control&lt;/code> atau header keamanan), dan pengaturan pengalihan (redirect) bergantung pada meta refresh HTML atau plugin Jekyll.&lt;/p>
&lt;h3 id="23-cloudflare-pages">2.3 Cloudflare Pages
&lt;/h3>&lt;p>Cloudflare Pages adalah layanan hosting situs statis yang dibangun di atas jaringan Anycast berskala global milik Cloudflare (tersebar di lebih dari 275 kota).
Layanan ini menawarkan penyesuaian kinerja yang luar biasa, termasuk dukungan standar untuk HTTP/3 (QUIC), optimasi gambar, dan integrasi dengan fungsi edge (Cloudflare Workers). Selain itu, tidak ada biaya bandwidth, sehingga keunggulan terbesarnya adalah Anda dapat menjalankannya secara gratis, tidak peduli seberapa besar lonjakan lalu lintas yang terjadi.&lt;/p>
&lt;h3 id="24-netlify">2.4 Netlify
&lt;/h3>&lt;p>Netlify adalah pionir di bidang Jamstack, menawarkan DX (Developer Experience) all-in-one yang mengintegrasikan fungsionalitas formulir, otentikasi (Identity), hingga fungsi serverless. Namun, Anda harus berhati-hati dengan manajemen biaya, karena apabila penggunaan bandwidth melebihi batas gratis (100GB per bulan), tagihan berdasarkan penggunaan dapat menjadi sangat mahal, terutama bagi blog yang banyak memuat gambar dan video.&lt;/p>
&lt;hr>
&lt;h2 id="3-perhitungan-teoretis-kinerja-dan-latensi-model-matematis-dengan-latex">3. Perhitungan Teoretis Kinerja dan Latensi (Model Matematis dengan LaTeX)
&lt;/h2>&lt;p>Dalam mengevaluasi kinerja web, mengurangi latensi (waktu tunda) adalah indikator terpenting. Mari kita buat model matematika tentang seberapa banyak latensi yang dikurangi saat menggunakan CDN (edge) dibandingkan dengan mengakses server origin secara langsung.&lt;/p>
&lt;p>Misalkan probabilitas permintaan pengguna untuk menemukan cache (Cache Hit Ratio) adalah $C$. Maka $0 \le C \le 1$.
Misalkan latensi ke server origin adalah $L_{origin}$, dan latensi ke node edge terdekat adalah $L_{edge}$.&lt;/p>
&lt;p>Rata-rata latensi baru $L_{new}$ dapat dihitung dengan nilai ekspektasi berikut:&lt;/p>
$$ L_{new} = C \times L_{edge} + (1 - C) \times (L_{edge} + L_{origin}) $$&lt;p>Jika disederhanakan, persamaannya menjadi:&lt;/p>
$$ L_{new} = L_{edge} + (1 - C) \times L_{origin} $$&lt;p>Sebagai contoh, ketika seorang pengguna di Tokyo mengakses server origin yang berada di pantai timur Amerika Serikat (New York), mengingat jarak fisik kabel serat optik dan latensi pemrosesan di router, $L_{origin}$ akan berkisar sekitar 200 md (milidetik). Sementara itu, jika menggunakan CDN seperti Cloudflare, karena pengguna akan terhubung ke node edge di Tokyo, $L_{edge}$ akan berkurang menjadi sekitar 10 md.&lt;/p>
&lt;p>Jika kita asumsikan rasio cache hit $C = 0.95$ (95%), maka:&lt;/p>
$$ L_{new} = 10 + (1 - 0.95) \times 200 = 10 + 0.05 \times 200 = 10 + 10 = 20 \text{ ms} $$&lt;p>Dengan demikian, pengenalan CDN dapat secara dramatis mengurangi (sekitar 90%) rata-rata latensi dari 210 md menjadi 20 md.&lt;/p>
&lt;hr>
&lt;h2 id="4-membangun-pipeline-cicd-dengan-github-actions">4. Membangun Pipeline CI/CD dengan GitHub Actions
&lt;/h2>&lt;p>Untuk mengotomatiskan proses pembaruan blog Hugo, kita akan membangun pipeline CI/CD menggunakan GitHub Actions. Melalui pengaturan ini, cukup dengan menulis artikel Markdown di lokal dan menjalankan &lt;code>git push&lt;/code>, proses build akan berjalan otomatis dan langsung di-deploy ke Cloudflare Pages atau GitHub Pages.&lt;/p>
&lt;p>Diagram urutan (sequence diagram) berikut ini menunjukkan alur keseluruhan dari mulai mem-push artikel hingga konten tersebut disampaikan kepada pengguna.&lt;/p>
&lt;pre class="mermaid">
sequenceDiagram
participant U as &amp;#34;Pengguna (Penulis)&amp;#34;
participant G as &amp;#34;Repositori GitHub&amp;#34;
participant A as &amp;#34;GitHub Actions&amp;#34;
participant C as &amp;#34;Cloudflare Pages&amp;#34;
participant V as &amp;#34;Pengunjung&amp;#34;
U-&amp;gt;&amp;gt;G: &amp;#34;git push origin main&amp;#34;
G-&amp;gt;&amp;gt;A: &amp;#34;Memicu Event Push&amp;#34;
A-&amp;gt;&amp;gt;A: &amp;#34;Checkout &amp;amp; Persiapan Hugo&amp;#34;
A-&amp;gt;&amp;gt;A: &amp;#34;hugo --minify (Proses Build)&amp;#34;
A-&amp;gt;&amp;gt;C: &amp;#34;Deploy ke Cloudflare Pages (Direct Upload)&amp;#34;
C--&amp;gt;&amp;gt;A: &amp;#34;URL Deployment (Sukses)&amp;#34;
V-&amp;gt;&amp;gt;C: &amp;#34;Permintaan Halaman Web&amp;#34;
C--&amp;gt;&amp;gt;V: &amp;#34;Mengembalikan HTML Ber-cache (Edge)&amp;#34;
&lt;/pre>
&lt;h3 id="41-konfigurasi-deployment-untuk-cloudflare-pages-direct-upload">4.1 Konfigurasi Deployment untuk Cloudflare Pages (Direct Upload)
&lt;/h3>&lt;p>Untuk Cloudflare Pages, terdapat dua metode: menghubungkan repositori GitHub dan membangunnya di infrastruktur Cloudflare, atau melakukan &amp;ldquo;Direct Upload (Unggah Langsung)&amp;rdquo; dari file statis yang di-build melalui GitHub Actions. Jika Anda ingin mengontrol versi Hugo lebih ketat dan mengintegrasikannya dengan pekerjaan lain (seperti pengujian atau optimasi gambar), disarankan untuk menggunakan metode Direct Upload setelah melakukan build di GitHub Actions.&lt;/p>
&lt;p>Berikut adalah contoh praktis file &lt;code>.github/workflows/deploy.yml&lt;/code> untuk deployment ke Cloudflare Pages.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;Deploy Hugo site to Cloudflare Pages&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">on&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">push&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">branches&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;main&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">workflow_dispatch&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">jobs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">build-and-deploy&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">runs-on&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;ubuntu-latest&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">steps&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;Checkout repository&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">uses&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;actions/checkout@v4&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">with&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">submodules&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;recursive&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">fetch-depth&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="m">0&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;Setup Hugo&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">uses&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;peaceiris/actions-hugo@v3&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">with&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">hugo-version&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;0.125.0&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">extended&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;Build Hugo Site&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">run&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;hugo --minify --gc&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">env&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">HUGO_ENVIRONMENT&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;production&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;Deploy to Cloudflare Pages&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">uses&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;cloudflare/pages-action@v1&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">with&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">apiToken&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">${{ secrets.CLOUDFLARE_API_TOKEN }}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">accountId&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">${{ secrets.CLOUDFLARE_ACCOUNT_ID }}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">projectName&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;nama-proyek-anda&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">directory&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;public&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">gitHubToken&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">${{ secrets.GITHUB_TOKEN }}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">branch&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;main&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Dalam pipeline ini, opsi &lt;code>--minify&lt;/code> meminimalkan HTML/CSS/JS, dan &lt;code>--gc&lt;/code> menghapus file yang tidak diperlukan. Ini merupakan langkah dasar dalam pengoptimalan kinerja.&lt;/p>
&lt;hr>
&lt;h2 id="5-pendalaman-konfigurasi-dns-domain-kustom-dan-rekaman-cname--alias">5. Pendalaman Konfigurasi DNS: Domain Kustom dan Rekaman CNAME / ALIAS
&lt;/h2>&lt;p>Jika Anda menggunakan domain sendiri (kustom) (misalnya: &lt;code>kenji.blog&lt;/code>), pengaturan DNS (Domain Name System) yang tepat sangatlah penting.&lt;/p>
&lt;h3 id="51-keterbatasan-rekaman-cname-dan-zone-apex">5.1 Keterbatasan Rekaman CNAME dan Zone Apex
&lt;/h3>&lt;p>Secara umum, ketika Anda mengarahkan subdomain (misalnya &lt;code>www.kenji.blog&lt;/code>) ke layanan eksternal, Anda menggunakan rekaman &lt;code>CNAME&lt;/code>. Namun, menurut spesifikasi DNS (RFC 1034), Anda tidak dapat menetapkan rekaman &lt;code>CNAME&lt;/code> di root domain (sering disebut Zone Apex atau naked domain, contoh: &lt;code>kenji.blog&lt;/code>). Alasannya, di Zone Apex selalu harus ada rekaman SOA (Start of Authority), NS (Name Server), dan MX (Mail Exchange), dan ada aturan bahwa CNAME tidak dapat berdiri bersama dengan jenis rekaman sumber daya lainnya.&lt;/p>
&lt;h3 id="52-solusi-rekaman-alias--aname--cname-flattening">5.2 Solusi: Rekaman ALIAS / ANAME / CNAME Flattening
&lt;/h3>&lt;p>Untuk menyelesaikan masalah ini, penyedia DNS modern menawarkan fitur perluasan unik.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Rekaman ALIAS / ANAME&lt;/strong>: Server DNS secara dinamis memecahkan nama dan mengembalikan rekaman A (alamat IP) akhir ke klien. Amazon Route 53 dan layanan lainnya mendukung fitur ini.&lt;/li>
&lt;li>&lt;strong>CNAME Flattening&lt;/strong>: Ini adalah fitur yang disediakan oleh Cloudflare. Meskipun Anda mengatur CNAME di Zone Apex, server DNS otoritatif Cloudflare secara otomatis menyelesaikan alamat IP (rekaman A dan AAAA) dan mengembalikannya ke klien secara transparan seolah-olah menggunakan rekaman A.&lt;/li>
&lt;/ul>
&lt;p>Saat menggunakan Cloudflare Pages, mendelegasikan nameserver domain ke Cloudflare dan memanfaatkan &amp;ldquo;CNAME Flattening&amp;rdquo; ini adalah konfigurasi yang paling mulus dan berkinerja tinggi.&lt;/p>
&lt;hr>
&lt;h2 id="6-strategi-cache-dan-kontrol-header-http">6. Strategi Cache dan Kontrol Header HTTP
&lt;/h2>&lt;p>Selain itu, hal yang sangat penting untuk mempercepat situs statis adalah &amp;ldquo;strategi cache&amp;rdquo;. Di Cloudflare Pages, Anda dapat mengontrol header respons HTTP secara rinci dengan menggunakan file yang disediakan (file &lt;code>_headers&lt;/code>).&lt;/p>
&lt;h3 id="61-edge-cache-vs-browser-cache">6.1 Edge Cache vs Browser Cache
&lt;/h3>&lt;p>Secara umum, cache terbagi menjadi dua kategori: &amp;ldquo;Edge Cache&amp;rdquo; yang disimpan di sisi CDN, dan &amp;ldquo;Browser Cache&amp;rdquo; yang disimpan di peramban pengguna.&lt;/p>
&lt;p>Idealnya, file statis (seperti gambar, CSS, JS, yang nama filenya mengandung hash) harus disimpan dalam cache browser untuk jangka waktu yang lama. Di sisi lain, untuk file HTML, lazimnya cache browser dipersingkat (atau dinonaktifkan) dan diserahkan pengelolaannya kepada edge cache agar pembaruan konten dapat segera terlihat.&lt;/p>
&lt;p>Contoh konfigurasi &lt;code>_headers&lt;/code> pada Cloudflare Pages:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl"># File HTML tidak disimpan di cache browser, divalidasi setiap saat
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">/*.html
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Cache-Control: public, max-age=0, must-revalidate
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"># File aset (CSS/JS/Gambar) disimpan di cache browser selama 1 tahun
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">/assets/*
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Cache-Control: public, max-age=31536000, immutable
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">/img/*
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> Cache-Control: public, max-age=31536000, immutable
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="62-formula-perhitungan-pengurangan-biaya-bandwidth">6.2 Formula Perhitungan Pengurangan Biaya Bandwidth
&lt;/h3>&lt;p>Dengan mengatur header cache yang tepat, Anda dapat mengurangi jumlah transfer data dari server (edge) secara signifikan. Biaya bandwidth bulanan ($Cost$) dapat dinyatakan dengan model berikut, yang bergantung pada volume transfer tiap sumber daya $B_i$, rasio cache hit $C_i$, dan harga satuan bandwidth $R$.&lt;/p>
$$ Cost = \sum_{i=1}^{n} \left( B_i \times (1 - C_i) \times R \right) $$&lt;p>Karena lalu lintas keluar (egress) di Cloudflare gratis ($R = 0$), maka beban finansial secara langsung menjadi $0$. Akan tetapi, ketika menggunakan infrastruktur lain seperti GitHub Pages atau menggunakan backend seperti AWS S3, memaksimalkan rasio cache hit $C_i$ ini menjadi kunci dalam memangkas biaya infrastruktur.&lt;/p>
&lt;hr>
&lt;h2 id="7-analisis-akses-yang-menggabungkan-privasi-dan-kinerja">7. Analisis Akses yang Menggabungkan Privasi dan Kinerja
&lt;/h2>&lt;p>Dalam menjalankan blog, analisis akses (Web Analytics) untuk mengetahui seberapa banyak pengguna yang berkunjung sangatlah krusial. Google Analytics (GA4) sudah lama menjadi standar de facto, tetapi situasinya sedang berubah dengan maraknya perlindungan privasi beberapa tahun terakhir (seperti GDPR, CCPA) dan penghapusan Cookie pihak ketiga (Third-party Cookie).&lt;/p>
&lt;h3 id="71-dampaknya-terhadap-kinerja-web">7.1 Dampaknya Terhadap Kinerja Web
&lt;/h3>&lt;p>Menerapkan Google Analytics (khususnya &lt;code>gtag.js&lt;/code> atau Google Tag Manager) menyebabkan pemuatan dan pengeksekusian banyak skrip eksternal, yang berdampak negatif terhadap kinerja (terutama pada metrik TTFB dan waktu pemblokiran thread utama).&lt;/p>
&lt;p>Mari kita uraikan waktu pemuatan situs sebagai berikut:&lt;/p>
&lt;pre class="mermaid">
pie title Rincian Waktu Pemuatan Situs Tipikal
&amp;#34;TTFB (Time to First Byte)&amp;#34; : 15
&amp;#34;Unduhan Konten (HTML/CSS)&amp;#34; : 20
&amp;#34;Parsing &amp;amp; Rendering DOM&amp;#34; : 45
&amp;#34;Analitik &amp;amp; JS Pihak Ketiga&amp;#34; : 20
&lt;/pre>
&lt;p>Tidak jarang alat analisis JS pihak ketiga memakan sekitar 20% hingga 30% dari keseluruhan waktu pemuatan (loading).&lt;/p>
&lt;h3 id="72-implementasi-cloudflare-web-analytics">7.2 Implementasi Cloudflare Web Analytics
&lt;/h3>&lt;p>Oleh karena itu, alternatif yang menarik perhatian saat ini adalah menggunakan alat analitik yang mengutamakan privasi tanpa menggunakan Cookie (Cookieless), seperti Cloudflare Web Analytics atau Plausible Analytics.&lt;/p>
&lt;p>Cloudflare Web Analytics beroperasi hanya dengan menyematkan cuplikan (snippet) JavaScript yang sangat ringan, dan karena tidak menggunakan Cookie, Anda tidak perlu memasang banner persetujuan Cookie (Cookie Consent Banner) yang mengganggu.&lt;/p>
&lt;p>Implementasinya di Hugo juga sangat mudah. Cukup tambahkan cuplikan kode yang diberikan ke dalam &lt;code>layouts/partials/head.html&lt;/code> atau &lt;code>layouts/partials/analytics.html&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-html" data-lang="html">&lt;span class="line">&lt;span class="cl">{{ if eq hugo.Environment &amp;#34;production&amp;#34; }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- Cloudflare Web Analytics --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">script&lt;/span> &lt;span class="na">defer&lt;/span> &lt;span class="na">src&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#39;https://static.cloudflareinsights.com/beacon.min.js&amp;#39;&lt;/span> &lt;span class="na">data-cf-beacon&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#39;{&amp;#34;token&amp;#34;: &amp;#34;TOKEN_BEACON_CLOUDFLARE_ANDA&amp;#34;}&amp;#39;&lt;/span>&lt;span class="p">&amp;gt;&amp;lt;/&lt;/span>&lt;span class="nt">script&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- End Cloudflare Web Analytics --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ end }}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Dengan menambahkan atribut &lt;code>defer&lt;/code>, skrip akan dimuat secara asinkron tanpa memblokir proses parsing HTML, dan akan dieksekusi setelah pembuatan DOM selesai. Hal ini membantu meminimalkan dampak terhadap kecepatan tampilan awal (LCP: Largest Contentful Paint dan FCP: First Contentful Paint).&lt;/p>
&lt;hr>
&lt;h2 id="8-kesimpulan-dan-praktik-terbaik">8. Kesimpulan dan Praktik Terbaik
&lt;/h2>&lt;p>Dalam mengoperasikan situs statis dengan Hugo, menggunakan platform hosting modern seperti Cloudflare Pages atau GitHub Pages menawarkan manfaat luar biasa dalam hal efektivitas biaya, kecepatan tampilan, dan keamanan.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Build Super Cepat&lt;/strong>: Manfaatkan kecepatan Hugo untuk meminimalkan waktu eksekusi pipeline CI/CD (GitHub Actions).&lt;/li>
&lt;li>&lt;strong>Distribusi di Edge&lt;/strong>: Gunakan jaringan edge Cloudflare untuk mengirimkan konten kepada pengguna di seluruh dunia dengan latensi dalam hitungan milidetik.&lt;/li>
&lt;li>&lt;strong>Konfigurasi DNS yang Tepat&lt;/strong>: Manfaatkan CNAME Flattening untuk mengelola Zone Apex (domain kustom) secara aman dan cepat.&lt;/li>
&lt;li>&lt;strong>Optimasi Strategi Cache&lt;/strong>: Gunakan &lt;code>_headers&lt;/code> untuk memisahkan cache browser dan cache edge berdasarkan jenis sumber dayanya dengan tepat.&lt;/li>
&lt;li>&lt;strong>Analitik yang Ringan&lt;/strong>: Terapkan layanan seperti Cloudflare Web Analytics yang peduli terhadap privasi tanpa mengorbankan kinerja.&lt;/li>
&lt;/ol>
&lt;p>Dengan menggabungkan berbagai teknologi ini, Anda dapat membangun sistem blog yang kuat dan skalabel untuk menangani jutaan pengunjung (PV) setiap bulannya secara gratis. Bagi Anda yang sedang mempertimbangkan untuk meluncurkan blog teknis, situs perusahaan, atau situs portofolio, silakan coba kombinasi arsitektur Jamstack + Hugo + Cloudflare Pages ini.&lt;/p></description></item><item><title>Hal-hal yang Harus Dilakukan Engineer untuk Meningkatkan Akses Bulanan di Blog Teknologi</title><link>http://kenji.blog/id/p/tech-blog-growth-strategies-for-engineers/</link><pubDate>Sat, 12 Sep 2026 12:00:00 +0900</pubDate><guid>http://kenji.blog/id/p/tech-blog-growth-strategies-for-engineers/</guid><description>&lt;img src="http://kenji.blog/p/tech-blog-growth-strategies-for-engineers/img/eyecatch.jpg" alt="Featured image of post Hal-hal yang Harus Dilakukan Engineer untuk Meningkatkan Akses Bulanan di Blog Teknologi" />&lt;h2 id="pendahuluan-growth-hack-blog-teknologi-yang-hanya-bisa-dilakukan-oleh-engineer">Pendahuluan: Growth Hack Blog Teknologi yang Hanya Bisa Dilakukan oleh Engineer
&lt;/h2>&lt;p>Banyak software engineer yang memulai blog teknologi, namun tidak banyak yang berhasil mengumpulkan sejumlah akses tertentu serta mempertahankan dan mengembangkannya dalam jangka waktu lama. Menulis artikel teknis berkualitas tinggi adalah prasyarat, namun era di mana &amp;ldquo;menulis artikel yang baik secara alami akan dibaca&amp;rdquo; sudah berakhir. Algoritma mesin pencari saat ini semakin kompleks, dan arus informasi di media sosial bergerak lebih cepat dari sebelumnya.&lt;/p>
&lt;p>Namun, engineer memiliki keunggulan yang tidak dimiliki profesi lain. Keunggulan tersebut adalah kemampuan untuk &amp;ldquo;memahami arsitektur sistem, menggabungkan alat untuk otomatisasi, dan menganalisis data secara terprogram&amp;rdquo;. Dalam artikel ini, kita tidak hanya akan membahas teknik penulisan, melainkan memandang blog teknologi sebagai sebuah &amp;ldquo;produk&amp;rdquo;, dan menjelaskan secara sangat rinci dan praktis mengenai strategi untuk secara dramatis meningkatkan akses bulanan menggunakan kekuatan rekayasa (engineering).&lt;/p>
&lt;hr>
&lt;h2 id="1-arsitektur-seo-blog-teknologi-untuk-engineer">1. Arsitektur SEO Blog Teknologi untuk Engineer
&lt;/h2>&lt;p>Sistem yang menjadi dasar blog (seperti static site generator) dan struktur HTML adalah elemen paling penting agar mesin pencari dapat menginterpretasikan konten dengan benar.&lt;/p>
&lt;h3 id="11-optimasi-core-web-vitals">1.1 Optimasi Core Web Vitals
&lt;/h3>&lt;p>Google menggunakan pengalaman halaman (page experience) sebagai faktor peringkat, dan secara khusus &lt;strong>Core Web Vitals (LCP, FID/INP, CLS)&lt;/strong> tidak dapat diabaikan bahkan dalam blog teknologi.
Blog teknologi sering kali menggunakan banyak blok kode sumber, rumus matematika (MathJax / KaTeX), dan gambar diagram. Hal-hal tersebut dapat menyebabkan keterlambatan dalam rendering halaman.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>LCP (Largest Contentful Paint)&lt;/strong>: Kecepatan pemuatan konten utama pada tampilan pertama. Gunakan WebP atau AVIF untuk gambar eyecatch, dan muat lebih awal (preload) dengan menambahkan atribut &lt;code>fetchpriority=&amp;quot;high&amp;quot;&lt;/code>. Selain itu, buat CSS atau JS besar yang digunakan untuk syntax highlight dimuat secara asinkron (asynchronous), atau desain agar hanya dimuat di halaman yang membutuhkannya.&lt;/li>
&lt;li>&lt;strong>CLS (Cumulative Layout Shift)&lt;/strong>: Pergeseran tata letak saat halaman sedang dimuat. Dengan memesan area tampilan untuk rumus matematika atau gambar menggunakan properti CSS seperti &lt;code>aspect-ratio&lt;/code> sejak awal, Anda dapat mencegah pergeseran mendadak saat DOM disisipkan kemudian.&lt;/li>
&lt;li>&lt;strong>INP (Interaction to Next Paint)&lt;/strong>: Responsivitas terhadap interaksi pengguna. Sangat penting untuk tidak menjalankan JavaScript berat (misalnya, pencarian dinamis teks penuh di sisi klien, atau eksekusi parser Markdown raksasa) di thread utama (main thread), melainkan memindahkannya ke Web Worker atau menghasilkannya sebagai HTML statis (SSG) pada saat proses build.&lt;/li>
&lt;/ul>
&lt;h3 id="12-implementasi-data-terstruktur-json-ld">1.2 Implementasi Data Terstruktur (JSON-LD)
&lt;/h3>&lt;p>Untuk secara eksplisit memberi tahu mesin pencari bahwa halaman tersebut adalah &amp;ldquo;artikel&amp;rdquo; dan &amp;ldquo;siapa&amp;rdquo; penulisnya, terapkan data terstruktur dalam format JSON-LD. Dengan memanfaatkan skema seperti &lt;code>TechArticle&lt;/code> dan &lt;code>SoftwareSourceCode&lt;/code>, konten Anda akan lebih mudah muncul dalam hasil pencarian kaya (rich results) Google, yang mana akan meningkatkan CTR (Click-Through Rate).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-html" data-lang="html">&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">script&lt;/span> &lt;span class="na">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;application/ld+json&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@context&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;https://schema.org&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;TechArticle&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;headline&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;Hal-hal yang Harus Dilakukan Engineer untuk Meningkatkan Akses Bulanan di Blog Teknologi&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;image&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;https://example.com/img/eyecatch.jpg&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;datePublished&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;2026-09-14T10:00:00+09:00&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;author&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;Person&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;Kenji&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;url&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;https://example.com/about/&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;publisher&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;Organization&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;Kenji&amp;#39;s Tech Blog&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;logo&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;ImageObject&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;url&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;https://example.com/img/logo.png&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">script&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="13-html-semantik-dan-optimasi-struktur-dokumen">1.3 HTML Semantik dan Optimasi Struktur Dokumen
&lt;/h3>&lt;p>Meskipun nesting (penyarangan) heading yang tepat (&lt;code>h1&lt;/code> hingga &lt;code>h6&lt;/code>) adalah hal mendasar, pada blog teknologi Anda dituntut untuk menggunakan tag semantik HTML5 seperti &lt;code>article&lt;/code>, &lt;code>section&lt;/code>, &lt;code>aside&lt;/code>, dan &lt;code>nav&lt;/code> secara akurat. Selain itu, dengan menggunakan &lt;code>&amp;lt;code&amp;gt;&lt;/code> atau &lt;code>&amp;lt;pre&amp;gt;&lt;/code> untuk menunjukkan kode sumber, &lt;code>&amp;lt;kbd&amp;gt;&lt;/code> untuk input keyboard, dan &lt;code>&amp;lt;var&amp;gt;&lt;/code> untuk variabel secara tepat, Anda dapat menyediakan HTML yang dapat dibaca mesin (machine-readable). Ini juga merupakan langkah yang sangat efektif untuk memfasilitasi pengindeksan konten oleh AI (pengumpulan data pelatihan LLM atau sistem RAG).&lt;/p>
&lt;hr>
&lt;h2 id="2-psikologi-niat-pencarian-search-intent-dan-strategi-kata-kunci">2. Psikologi Niat Pencarian (Search Intent) dan Strategi Kata Kunci
&lt;/h2>&lt;p>Untuk memaksimalkan arus kunjungan dari mesin pencari (lalu lintas organik), Anda perlu membaca dengan tepat &amp;ldquo;mengapa pengguna mencari kata kunci tersebut,&amp;rdquo; yang dikenal sebagai niat pencarian. Niat pencarian untuk topik teknis pada umumnya dapat diklasifikasikan ke dalam dua kategori.&lt;/p>
&lt;h3 id="21-tipe-pemecahan-kesalahan-troubleshooting-dan-tipe-pembelajaran-sistematisulasan-learning--review">2.1 Tipe &amp;ldquo;Pemecahan Kesalahan&amp;rdquo; (Troubleshooting) dan Tipe &amp;ldquo;Pembelajaran Sistematis/Ulasan&amp;rdquo; (Learning &amp;amp; Review)
&lt;/h3>&lt;ol>
&lt;li>
&lt;p>&lt;strong>Tipe Pemecahan Kesalahan (Troubleshooting Intent)&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>Contoh kata kunci pencarian: &lt;code>Solusi Docker &amp;quot;no space left on device&amp;quot;&lt;/code>, &lt;code>Penyebab Python IndexError list index out of range&lt;/code>&lt;/li>
&lt;li>Psikologi: Pengguna terblokir oleh kesalahan selama pengembangan, dan menginginkan potongan kode atau perintah (command) yang bisa menjadi obat mujarab secara instan.&lt;/li>
&lt;li>Strategi: Sajikan &amp;ldquo;kesimpulan (kode atau perintah untuk memecahkan masalah)&amp;rdquo; di awal artikel (tampilan pertama). Tempatkan latar belakang atau penjelasan rinci tentang mekanismenya setelahnya. Penuhi terlebih dahulu keinginan pengguna untuk &amp;ldquo;ingin segera memperbaikinya&amp;rdquo;. Ini akan membantu menurunkan rasio pentalan (bounce rate).&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Tipe Pembelajaran Sistematis &amp;amp; Ulasan (Learning &amp;amp; Review Intent)&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>Contoh kata kunci pencarian: &lt;code>Perbandingan React vs Vue 2026&lt;/code>, &lt;code>Pengenalan Pemrosesan Asynchronous Rust&lt;/code>, &lt;code>Desain Arsitektur Jaringan GCP&lt;/code>&lt;/li>
&lt;li>Psikologi: Pengguna berencana memilih tech stack baru, atau ingin memperdalam pemahaman mereka dari dasar, dan siap meluangkan waktu untuk membaca.&lt;/li>
&lt;li>Strategi: Perkaya daftar isi (TOC) dan gunakan banyak ilustrasi serta diagram arsitektur (seperti Mermaid). Bandingkan kelebihan dan kekurangan secara objektif, dan sertakan studi kasus (use case) bagaimana teknologi tersebut dapat digunakan dalam pekerjaan nyata. Hal ini dapat meningkatkan waktu menetap (dwell time) di halaman.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ol>
&lt;h3 id="22-model-penurunan-eksponensial-lalu-lintas-dan-strategi-long-tail">2.2 Model Penurunan Eksponensial Lalu Lintas dan Strategi Long-Tail
&lt;/h3>&lt;p>Jumlah akses pada artikel teknis cenderung membentuk lonjakan (spike) karena viral (buzz) di media sosial dan lainnya segera setelah diterbitkan, lalu menurun secara eksponensial. Lalu lintas $V(t)$ ini dapat diperkirakan menggunakan model matematika berikut.&lt;/p>
$$ V(t) = V_0 e^{-\lambda t} + C $$&lt;p>Di mana:&lt;/p>
&lt;ul>
&lt;li>$V(t)$: Volume lalu lintas pada waktu $t$&lt;/li>
&lt;li>$V_0$: Lonjakan lalu lintas awal akibat buzz media sosial sesaat setelah dipublikasikan&lt;/li>
&lt;li>$\lambda$: Konstanta peluruhan yang berkaitan dengan keusangan konten atau efek lupa di media sosial (bergantung pada kecepatan perubahan tren teknologi)&lt;/li>
&lt;li>$C$: Arus masuk pencarian organik yang stabil dari mesin pencari (lalu lintas dasar)&lt;/li>
&lt;/ul>
&lt;p>Kunci untuk mengembangkan akses dalam jangka panjang bukanlah menargetkan buzz sementara ($V_0$), melainkan &lt;strong>bagaimana memperbesar nilai konstanta $C$ (arus masuk berkelanjutan dari mesin pencari)&lt;/strong>. Dengan meliput sejumlah besar &amp;ldquo;kata kunci long-tail&amp;rdquo; yang minim persaingan meskipun volume pencariannya kecil, seperti cara menangani error khusus yang niche atau cara mengintegrasikan alat tertentu, Anda dapat mengembangkan total kumulatif $C$ menjadi sesuatu yang sangat besar.&lt;/p>
&lt;hr>
&lt;h2 id="3-analisis-konten-berbasis-data-menggunakan-api-google-search-console">3. Analisis Konten Berbasis Data menggunakan API Google Search Console
&lt;/h2>&lt;p>Untuk membangun fondasi lalu lintas $C$ yang stabil, perlu menggunakan data dari Google Search Console (GSC) dan menganalisis secara objektif &amp;ldquo;bagaimana Google menilai (mengevaluasi) konten&amp;rdquo;. Namun, mengoperasikan GSC melalui UI Web memiliki batasan. Jika Anda seorang engineer, mari otomatisasi proses analisis ini menggunakan GSC API dan Python.&lt;/p>
&lt;h3 id="31-pendekatan-otomatisasi-dengan-gsc-api-dan-python">3.1 Pendekatan Otomatisasi dengan GSC API dan Python
&lt;/h3>&lt;p>Buatlah sebuah skrip yang secara otomatis dapat mendeteksi &amp;ldquo;artikel yang disayangkan&amp;rdquo;, yaitu ketika peringkat pencarian sebuah artikel tertentu terus menurun dari waktu ke waktu (Decaying Content), atau ketika rasio klik-tayang (CTR) ternyata sangat rendah meskipun jumlah tayangan (impresi) tinggi.
Untuk melakukan ini, kita akan menggunakan &lt;code>google-api-python-client&lt;/code> dan &lt;code>pandas&lt;/code>.&lt;/p>
&lt;h3 id="32-kode-implementasi-python-ekstraksi-otomatis-konten-dengan-ctr-rendah">3.2 Kode Implementasi Python: Ekstraksi Otomatis Konten dengan CTR Rendah
&lt;/h3>&lt;p>Berikut ini adalah contoh skrip yang mengambil data performa pencarian 30 hari terakhir melalui API, lalu mengekstraksi &amp;ldquo;URL artikel dan kata kunci yang memiliki ruang perbaikan besar pada judul atau deskripsi&amp;rdquo; dengan kondisi lebih dari 1000 impresi dan CTR kurang dari 2%.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">pandas&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">pd&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">google.oauth2&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">service_account&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">googleapiclient.discovery&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">build&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">datetime&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 1. Autentikasi dan Pembuatan Layanan API&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">KEY_FILE_LOCATION&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;path/to/your-service-account-key.json&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">SCOPES&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;https://www.googleapis.com/auth/webmasters.readonly&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">SITE_URL&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;https://your-tech-blog.com/&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">credentials&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">service_account&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Credentials&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">from_service_account_file&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">KEY_FILE_LOCATION&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">scopes&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">SCOPES&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">webmasters_service&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">build&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;searchconsole&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;v1&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">credentials&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">credentials&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 2. Perhitungan Periode Permintaan (30 hari terakhir)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">today&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">datetime&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">date&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">today&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">end_date&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">today&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">datetime&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">timedelta&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">days&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">))&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strftime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;%Y-%m-&lt;/span>&lt;span class="si">%d&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">start_date&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">today&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">datetime&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">timedelta&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">days&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">32&lt;/span>&lt;span class="p">))&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strftime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;%Y-%m-&lt;/span>&lt;span class="si">%d&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 3. Eksekusi Permintaan API&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">request&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;startDate&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">start_date&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;endDate&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">end_date&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;dimensions&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;query&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;page&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;rowLimit&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">5000&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">webmasters_service&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">searchanalytics&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">siteUrl&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">SITE_URL&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">body&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">request&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">execute&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 4. Pemrosesan dan Pemfilteran Data dengan Pandas DataFrame&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="s1">&amp;#39;rows&amp;#39;&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">rows&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;rows&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">row&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">rows&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">data&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;Query&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">row&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;keys&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;URL&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">row&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;keys&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;Clicks&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">row&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;clicks&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;Impressions&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">row&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;impressions&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;CTR&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">row&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;ctr&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;Position&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">row&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;position&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">df&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DataFrame&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Kondisi filter: Impresi &amp;gt;= 1000 dan CTR &amp;lt; 2%&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">target_df&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">df&lt;/span>&lt;span class="p">[(&lt;/span>&lt;span class="n">df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;Impressions&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="mi">1000&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">df&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;CTR&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mf">0.02&lt;/span>&lt;span class="p">)]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Urutkan berdasarkan Posisi secara menaik (prioritaskan yang peringkatnya tinggi namun jarang diklik)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">target_df&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">target_df&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sort_values&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">by&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;Position&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ascending&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;【Daftar Rekomendasi Perbaikan Judul/Meta Deskripsi】&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target_df&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">head&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Ekspor ke CSV jika diperlukan&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># target_df.to_csv(&amp;#39;improve_candidates.csv&amp;#39;, index=False)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Data tidak ditemukan.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Dengan menjalankan skrip ini secara berkala menggunakan cron atau GitHub Actions, Anda dapat memutuskan &amp;ldquo;judul artikel mana yang perlu ditulis ulang&amp;rdquo; dengan pendekatan yang selalu didorong oleh data (data-driven). Sangat penting untuk melakukan peningkatan berkelanjutan berbasis data (Continuous Content Improvement seperti halnya CI/CD) dan bukan hanya mengandalkan intuisi.&lt;/p>
&lt;hr>
&lt;h2 id="4-manajemen-siklus-hidup-artikel-dan-strategi-penulisan-ulang">4. Manajemen Siklus Hidup Artikel dan Strategi Penulisan Ulang
&lt;/h2>&lt;p>Menulis dan memublikasikan artikel teknis bukanlah akhir dari segalanya. Seiring dengan perkembangan teknologi (seperti peningkatan versi framework, depresiasi API, dll.), konten dapat dengan cepat menjadi usang. Terus menyajikan informasi lama tidak hanya akan merusak kredibilitas blog, tetapi juga berdampak negatif pada evaluasi SEO.&lt;/p>
&lt;h3 id="41-manajemen-siklus-hidup-konten-gantt-chart">4.1 Manajemen Siklus Hidup Konten (Gantt Chart)
&lt;/h3>&lt;p>Siklus hidup operasional yang ideal untuk sebuah konten diilustrasikan dengan Mermaid Gantt chart berikut ini.&lt;/p>
&lt;pre class="mermaid">
gantt
title Manajemen Siklus Hidup Konten Berbasis Data
dateFormat YYYY-MM-DD
axisFormat %m/%d
section &amp;#34;Fase 1: Perencanaan &amp;amp; Penulisan&amp;#34;
&amp;#34;Analisis Kata Kunci &amp;amp; Tren Pencarian&amp;#34; :a1, 2026-09-01, 3d
&amp;#34;Draf &amp;amp; Verifikasi Kode&amp;#34; :a2, after a1, 5d
&amp;#34;Revisi &amp;amp; Pengeditan&amp;#34; :a3, after a2, 2d
section &amp;#34;Fase 2: Publikasi &amp;amp; Promosi&amp;#34;
&amp;#34;Deployment dengan Pipeline CI/CD&amp;#34; :p1, 2026-09-11, 1d
&amp;#34;Distribusi Otomatis Media Sosial (X, LinkedIn, RSS)&amp;#34; :p2, 2026-09-11, 1d
&amp;#34;Penyebaran ke Hatena Bookmark, dll.&amp;#34; :p3, after p2, 3d
section &amp;#34;Fase 3: Observasi &amp;amp; Analisis&amp;#34;
&amp;#34;Periode Pengumpulan Data GSC&amp;#34; :m1, 2026-09-14, 28d
&amp;#34;Evaluasi Performa dengan API Python&amp;#34;:m2, after m1, 2d
section &amp;#34;Fase 4: Peningkatan (Penulisan Ulang)&amp;#34;
&amp;#34;Perbaikan Judul Artikel dengan CTR Rendah&amp;#34; :r1, after m2, 3d
&amp;#34;Pembaruan Kode ke Versi Terbaru&amp;#34;:r2, after r1, 4d
&lt;/pre>
&lt;p>Seperti yang ditunjukkan di atas, kunci untuk menjaga dan meningkatkan lalu lintas adalah memperlakukan pembuatan artikel seolah-olah sebuah proyek pengembangan perangkat lunak, dan memasukkan fase pemeliharaan (penulisan ulang) setelah rilis ke dalam rencana operasional.&lt;/p>
&lt;h3 id="42-model-matematis-roi-laba-atas-investasi-pembuatan-konten">4.2 Model Matematis ROI (Laba Atas Investasi) Pembuatan Konten
&lt;/h3>&lt;p>Karena engineer menghabiskan waktu berharga mereka untuk menulis artikel, return on investment (ROI) harus selalu dipertimbangkan.
ROI pada blog dapat dirumuskan sebagai berikut.&lt;/p>
$$ ROI = \frac{\sum_{t=1}^{T} \left( Rev_{ad}(t) + Val_{brand}(t) + Val_{skill}(t) \right) - Cost_{time}}{\text{Cost}_{time}} \times 100 \ (\%) $$&lt;ul>
&lt;li>$T$: Masa pakai efektif artikel (periode hingga usang)&lt;/li>
&lt;li>$Rev_{ad}(t)$: Pendapatan langsung dari iklan, pendapatan afiliasi, atau sponsor&lt;/li>
&lt;li>$Val_{brand}(t)$: Nilai konversi moneter dari dampak positif terhadap karier karena memperlihatkan keterampilan teknis (peningkatan penawaran gaji saat pindah kerja, permintaan untuk menjadi pembicara, dll.)&lt;/li>
&lt;li>$Val_{skill}(t)$: Nilai peningkatan keterampilan diri dari proses pembelajaran dan riset yang dilakukan demi menulis artikel tersebut&lt;/li>
&lt;li>$Cost_{time}$: Waktu yang dihabiskan untuk menulis artikel, membuat diagram, dan memverifikasi kode (dikonversi ke tarif per jam sendiri)&lt;/li>
&lt;/ul>
&lt;p>Hal hebat dari memiliki blog teknologi adalah, meskipun $Rev_{ad}$ mungkin kecil, $Val_{brand}$ dan $Val_{skill}$ cenderung menjadi sangat besar. Secara khusus, artikel teknis berkualitas tinggi bisa langsung menjadi portofolio Anda, dan menunjukkan kekuatan luar biasa dalam mencari pekerjaan atau proyek sampingan.&lt;/p>
&lt;hr>
&lt;h2 id="5-distribusi-melalui-integrasi-github-actions-dan-alat-otomatisasi-eksternal">5. Distribusi Melalui Integrasi GitHub Actions dan Alat Otomatisasi Eksternal
&lt;/h2>&lt;p>Setelah konten dibuat, tantangannya adalah bagaimana menyampaikannya kepada audiens target secara efisien (distribusi). Memublikasikan tautan ke setiap platform media sosial secara manual sangat tidak efisien dan sama sekali tidak mencerminkan cara kerja seorang engineer.&lt;/p>
&lt;h3 id="51-arsitektur-otomatisasi-berbagi-di-media-sosial">5.1 Arsitektur Otomatisasi Berbagi di Media Sosial
&lt;/h3>&lt;p>Kita akan membangun arsitektur otomatis yang menangani mulai dari saat file Markdown di-merge ke branch main di repositori GitHub, meliputi build, deployment, hingga pengumuman otomatis ke berbagai platform.&lt;/p>
&lt;pre class="mermaid">
flowchart TD
A[&amp;#34;Developer (Git Push)&amp;#34;] --&amp;gt; B[&amp;#34;Repositori GitHub&amp;#34;]
B --&amp;gt;|Webhook| C[&amp;#34;GitHub Actions (CI/CD)&amp;#34;]
C --&amp;gt;|Build| D[&amp;#34;Static Site Generator (Hugo/Gatsby)&amp;#34;]
D --&amp;gt;|Deploy| E[&amp;#34;Hosting (Vercel / Cloudflare Pages)&amp;#34;]
D --&amp;gt;|Generate| F[&amp;#34;RSS Feed (index.xml)&amp;#34;]
F --&amp;gt;|Ditarik oleh| G[&amp;#34;Zapier / IFTTT / Make&amp;#34;]
G --&amp;gt;|Panggilan API| H[&amp;#34;Posting Otomatis X (Twitter)&amp;#34;]
G --&amp;gt;|Panggilan API| I[&amp;#34;Postingan Artikel LinkedIn&amp;#34;]
G --&amp;gt;|Panggilan API| J[&amp;#34;Webhook Komunitas Discord / Slack&amp;#34;]
C --&amp;gt;|Skrip Actions| K[&amp;#34;API Cross-Post Qiita / Zenn&amp;#34;]
&lt;/pre>
&lt;h3 id="52-poin-poin-dalam-membangun-pipeline-otomatisasi">5.2 Poin-poin dalam Membangun Pipeline Otomatisasi
&lt;/h3>&lt;ol>
&lt;li>
&lt;p>&lt;strong>Build dan Deployment dengan GitHub Actions&lt;/strong>
Jika menggunakan static site generator, gunakan GitHub Actions untuk mengotomatiskan pembuatan HTML dan deployment ke layanan hosting (seperti Vercel, Netlify, Cloudflare Pages, dll.). Di sini, sangat efektif untuk memasukkan proses optimasi gambar (misalnya konversi otomatis ke WebP) ke dalam pipeline build sebagai bagian dari optimasi Core Web Vitals yang telah disebutkan sebelumnya.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Integrasi Media Sosial menggunakan Trigger RSS di Zapier/IFTTT&lt;/strong>
Saat build dilakukan, generator situs akan membuat RSS feed terbaru (XML). Baca file ini di iPaaS (Integration Platform as a Service) seperti Zapier atau Make (sebelumnya Integromat) dan atur alur kerja seperti &amp;ldquo;Jika item baru ditambahkan di RSS, publikasikan judul dan URL-nya ke X (Twitter) dan LinkedIn&amp;rdquo;. Dengan ini, notifikasi ke pengikut (followers) akan otomatis terkirim begitu artikel diterbitkan.&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;strong>Cross-Posting ke Qiita/Zenn (Penggunaan Tag Canonical)&lt;/strong>
Saat otoritas domain (domain power) blog korporat atau pribadi Anda masih lemah, meminjam kekuatan platform teknis seperti Qiita atau Zenn untuk menarik pengunjung adalah ide yang patut dicoba. Namun, menyalin dan menempel begitu saja berisiko mendapatkan penalti SEO sebagai konten duplikat.
Masalah ini dapat diatasi dengan menambahkan &lt;strong>tag Canonical&lt;/strong> di metadata artikel di Qiita atau Zenn, yang diarahkan ke URL artikel orisinal di blog Anda sendiri. Dengan memicu API di berbagai platform dari GitHub Actions dan membuat skrip untuk membuat artikel dari file Markdown Anda, distribusi multi-saluran dapat sepenuhnya diotomatisasi.&lt;/p>
&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="penutup-menjalankan-siklus-peningkatan-berkelanjutan">Penutup: Menjalankan Siklus Peningkatan Berkelanjutan
&lt;/h2>&lt;p>Untuk secara dramatis meningkatkan jumlah kunjungan bulanan ke blog teknologi Anda, selain tindakan &amp;ldquo;menulis&amp;rdquo;, pendekatan teknis seperti yang diperkenalkan kali ini sangat diperlukan.&lt;/p>
&lt;ol>
&lt;li>Membangun arsitektur situs dan HTML yang solid dengan mempertimbangkan SEO&lt;/li>
&lt;li>Desain artikel yang memahami niat pencarian pengguna (pemecahan masalah vs pembelajaran sistematis)&lt;/li>
&lt;li>Analisis data sepenuhnya memanfaatkan API Google Search Console dan Python&lt;/li>
&lt;li>Manajemen siklus hidup konten dan penulisan ulang dengan mempertimbangkan ROI&lt;/li>
&lt;li>Otomatisasi penuh dalam distribusi melalui integrasi CI/CD dan Zapier&lt;/li>
&lt;/ol>
&lt;p>Jika Anda dapat mengintegrasikan semua hal ini sebagai sebuah sistem, blog teknologi akan menjadi aset (asset) paling kuat yang akan mendorong karier Anda. Bagi engineer yang khawatir tentang jumlah akses yang mandek, kami harap Anda mencoba memulai &amp;ldquo;growth hack blog&amp;rdquo; Anda mulai hari ini. Keahlian pemrograman dan kemampuan desain arsitektur yang Anda asah dalam tugas-tugas pengembangan niscaya akan menjadi senjata terbesar Anda dalam menjalankan blog.&lt;/p></description></item><item><title>Mencegah Kehabisan Ide Artikel Teknologi! Metode Input dan Penciptaan Ide yang Efisien</title><link>http://kenji.blog/id/p/tech-blog-idea-generation-and-input-strategy/</link><pubDate>Sat, 12 Sep 2026 12:00:00 +0900</pubDate><guid>http://kenji.blog/id/p/tech-blog-idea-generation-and-input-strategy/</guid><description>&lt;img src="http://kenji.blog/p/tech-blog-idea-generation-and-input-strategy/img/eyecatch.jpg" alt="Featured image of post Mencegah Kehabisan Ide Artikel Teknologi! Metode Input dan Penciptaan Ide yang Efisien" />&lt;p>Sebagai seorang engineer atau researcher yang mengelola blog teknologi, ada satu rintangan yang hampir pasti akan Anda hadapi. Yaitu &amp;ldquo;kehabisan ide&amp;rdquo;. Meskipun beberapa artikel pertama dapat ditulis dengan lancar, seiring berjalannya waktu, tidak jarang kita merasa tersiksa oleh kekhawatiran seperti &amp;ldquo;Saya tidak tahu apa yang harus ditulis selanjutnya&amp;rdquo; atau &amp;ldquo;Input saya sangat kurang untuk menghasilkan output&amp;rdquo;. Menulis blog teknologi tidak hanya bergantung pada keterampilan menulis, tetapi juga sangat bergantung pada perancangan sistem yang mencakup pengumpulan pengetahuan harian, pengorganisasian, dan penggabungan elemen-elemen tersebut untuk menciptakan nilai baru.&lt;/p>
&lt;p>Dalam artikel ini, kami akan menjelaskan secara sangat rinci dan teknis tentang &lt;strong>pipeline input dan output yang disistematisasi&lt;/strong> untuk terus menghasilkan ide artikel teknologi secara semi-permanen. Kita akan mulai dengan mekanisme untuk secara otomatis mengekstrak topik yang sedang tren menggunakan API dari sumber informasi luar negeri berkualitas tinggi seperti Hacker News dan Lobsters, serta menjalankannya secara rutin dengan GitHub Actions. Kemudian, informasi yang terkumpul akan disistematisasi sebagai pengetahuan menggunakan metode Zettelkasten dengan Obsidian, dan dikombinasikan dengan Embeddings API dari OpenAI serta Pinecone (database vektor) untuk memungkinkan pencarian semantik, membangun sistem Manajemen Pengetahuan Pribadi (PKM: Personal Knowledge Management) yang canggih.&lt;/p>
&lt;p>Selain itu, untuk mengimbangi keterbatasan daya ingat manusia, kita akan mempraktikkan Pengulangan Berjarak (Spaced Repetition) menggunakan Anki berdasarkan kurva kelupaan Ebbinghaus, dan mendalami serangkaian proses untuk menyublimasikan pengetahuan yang telah melekat menjadi ide-ide baru melalui &amp;ldquo;Kreativitas Kombinatorial (Combinatorial Creativity)&amp;rdquo;, lengkap dengan model matematis spesifik dan contoh implementasi skrip Python.&lt;/p>
&lt;h2 id="1-entropi-informasi-dan-mekanisme-kehabisan-ide">1. Entropi Informasi dan Mekanisme &amp;ldquo;Kehabisan Ide&amp;rdquo;
&lt;/h2>&lt;p>Mengapa kita mengalami &amp;ldquo;kehabisan ide&amp;rdquo;? Dilihat dari perspektif teori informasi, ini dapat dikatakan sebagai keadaan di mana &amp;ldquo;jumlah informasi&amp;rdquo; dari sistem pengetahuan yang kita miliki telah habis, atau telah menjadi homogen.&lt;/p>
&lt;p>Entropi informasi $H(X)$ yang digagas oleh Claude Shannon merepresentasikan ketidakpastian (atau tingkat kejutan) dari informasi yang diperoleh dari suatu sumber informasi.&lt;/p>
$$ H(X) = - \sum_{i=1}^{n} P(x_i) \log_2 P(x_i) $$&lt;p>Di sini, $X$ adalah variabel acak dari topik yang diperoleh dari sumber informasi, dan $P(x_i)$ adalah probabilitas menemukan topik $x_i$ tersebut. Jika Anda selalu melihat situs web yang sama (misalnya, hanya situs berita domestik tertentu atau dokumentasi tumpukan teknologi yang sama), $P(x_i)$ tertentu menjadi sangat tinggi, yang mengakibatkan penurunan entropi $H(X)$ dari keseluruhan sistem. Keadaan entropi rendah berarti keadaan di mana &amp;ldquo;tidak ada penemuan (kejutan) baru&amp;rdquo;, dan inilah akar penyebab dari &amp;ldquo;kehabisan ide&amp;rdquo;.&lt;/p>
&lt;p>Untuk menjaga entropi tetap tinggi, kita perlu secara sengaja memasukkan sumber informasi yang biasanya tidak kita akses sebagai noise, dan meratakan distribusi probabilitas dalam bersentuhan dengan topik-topik yang belum diketahui. Inilah alasan terbesar mengapa kita harus mengotomatisasi input dari berbagai sumber informasi.&lt;/p>
&lt;h2 id="2-membangun-pipeline-pengumpulan-informasi-otomatis-hacker-news--lobsters-api">2. Membangun Pipeline Pengumpulan Informasi Otomatis: Hacker News &amp;amp; Lobsters API
&lt;/h2>&lt;p>Untuk mendapatkan input yang berkualitas tinggi, akan sangat efektif untuk mengekstrak informasi tren dari komunitas engineer berkualitas baik dengan tingkat noise yang rendah. Hacker News (dioperasikan oleh Y Combinator) dan Lobsters adalah tempat terbaik di mana diskusi teknis yang mendalam berlangsung. Namun, menelusuri situs-situs ini setiap hari memakan waktu dan menghabiskan sumber daya kognitif.&lt;/p>
&lt;p>Oleh karena itu, kita akan membuat skrip menggunakan Python untuk secara otomatis mengekstrak artikel dengan skor tertentu atau lebih tinggi dari API ini.&lt;/p>
&lt;h3 id="skrip-ekstraksi-artikel-tren-dengan-python">Skrip Ekstraksi Artikel Tren dengan Python
&lt;/h3>&lt;p>Skrip berikut mengambil artikel yang memenuhi kriteria tertentu dari Firebase API Hacker News dan umpan JSON Lobsters, dan mengeluarkannya sebagai file Markdown.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;span class="lnt">67
&lt;/span>&lt;span class="lnt">68
&lt;/span>&lt;span class="lnt">69
&lt;/span>&lt;span class="lnt">70
&lt;/span>&lt;span class="lnt">71
&lt;/span>&lt;span class="lnt">72
&lt;/span>&lt;span class="lnt">73
&lt;/span>&lt;span class="lnt">74
&lt;/span>&lt;span class="lnt">75
&lt;/span>&lt;span class="lnt">76
&lt;/span>&lt;span class="lnt">77
&lt;/span>&lt;span class="lnt">78
&lt;/span>&lt;span class="lnt">79
&lt;/span>&lt;span class="lnt">80
&lt;/span>&lt;span class="lnt">81
&lt;/span>&lt;span class="lnt">82
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">requests&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">json&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">datetime&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">datetime&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">os&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Pengaturan&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">HN_TOPSTORIES_URL&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;https://hacker-news.firebaseio.com/v0/topstories.json&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">HN_ITEM_URL&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;https://hacker-news.firebaseio.com/v0/item/&lt;/span>&lt;span class="si">{}&lt;/span>&lt;span class="s2">.json&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">LOBSTERS_URL&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;https://lobste.rs/hottest.json&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">MIN_HN_SCORE&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">100&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">MIN_LOBSTERS_SCORE&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">10&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">OUTPUT_DIR&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;./daily_inputs&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_hacker_news_trends&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;Mengambil artikel teratas dengan skor tinggi dari Hacker News&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Fetching Hacker News top stories...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">HN_TOPSTORIES_URL&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">200&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">story_ids&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()[:&lt;/span>&lt;span class="mi">30&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="c1"># Batasi 30 besar&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">trending_stories&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">story_id&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">story_ids&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">item_resp&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">HN_ITEM_URL&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">format&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">story_id&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">item_resp&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">200&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">item&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">item_resp&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">item&lt;/span> &lt;span class="ow">and&lt;/span> &lt;span class="n">item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;score&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="n">MIN_HN_SCORE&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">trending_stories&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;title&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;title&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;url&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;url&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;https://news.ycombinator.com/item?id=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">story_id&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;score&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;score&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;source&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Hacker News&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">trending_stories&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_lobsters_trends&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;Mengambil artikel dengan skor tinggi dari Lobsters&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Fetching Lobsters hottest stories...&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">requests&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">LOBSTERS_URL&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">status_code&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">200&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">items&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">json&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">trending_stories&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">item&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">items&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;score&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="n">MIN_LOBSTERS_SCORE&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">trending_stories&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;title&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;title&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;url&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;url&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;comments_url&amp;#34;&lt;/span>&lt;span class="p">)),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;score&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">item&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;score&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;source&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="s2">&amp;#34;Lobsters&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">trending_stories&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">save_to_markdown&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">stories&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;Menyimpan artikel yang diambil sebagai file Markdown&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">path&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">exists&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">OUTPUT_DIR&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">makedirs&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">OUTPUT_DIR&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">today_str&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">datetime&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">now&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strftime&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;%Y-%m-&lt;/span>&lt;span class="si">%d&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">filepath&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">path&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">OUTPUT_DIR&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;trends_&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">today_str&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.md&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">with&lt;/span> &lt;span class="nb">open&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">filepath&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;w&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">encoding&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;utf-8&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">f&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;# Daily Tech Trends: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">today_str&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="se">\n\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">story&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">stories&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">f&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;## [&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">story&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;title&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">](&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">story&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;url&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">)&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">f&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;- **Source**: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">story&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;source&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">f&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;- **Score**: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">story&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;score&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">f&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;- **Notes**: (Tambahkan observasi Anda di sini)&lt;/span>&lt;span class="se">\n\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Saved &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">stories&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> stories to &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">filepath&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">hn_stories&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_hacker_news_trends&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">lobsters_stories&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_lobsters_trends&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">all_stories&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">hn_stories&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">lobsters_stories&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Urutkan berdasarkan skor secara menurun&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">all_stories&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sort&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="k">lambda&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;score&amp;#34;&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="n">reverse&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">save_to_markdown&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">all_stories&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Skrip ini memberikan nilai lebih dari sekadar pembaca RSS sederhana. Dengan memfilter berdasarkan skor, kita hanya mengekstrak topik teknis yang benar-benar diperhatikan oleh komunitas (sinyal tinggi dengan noise rendah).&lt;/p>
&lt;h2 id="3-penjadwalan-dan-otomatisasi-dengan-github-actions">3. Penjadwalan dan Otomatisasi dengan GitHub Actions
&lt;/h2>&lt;p>Menjalankan skrip Python yang telah dibuat secara manual setiap hari sangat merepotkan. Dasar dari otomatisasi adalah mengurangi campur tangan manusia semaksimal mungkin. Kita akan membangun mekanisme untuk menjalankan skrip setiap hari pada waktu yang ditentukan dan mengkomit hasilnya secara otomatis ke repositori menggunakan fitur Cron dari GitHub Actions.&lt;/p>
&lt;p>Buat file &lt;code>.github/workflows/daily_trends.yml&lt;/code> di root proyek, dan tulis sebagai berikut.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Daily Tech Trends Scraper&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">on&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">schedule&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">cron&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;0 0 * * *&amp;#39;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># Dijalankan setiap hari pada 0:00 UTC (9:00 JST)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">workflow_dispatch&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># Untuk eksekusi manual&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">jobs&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">scrape-and-commit&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">runs-on&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">ubuntu-latest&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">steps&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Checkout Repository&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">uses&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">actions/checkout@v3&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Setup Python&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">uses&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">actions/setup-python@v4&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">with&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">python-version&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;3.10&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Install Dependencies&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">run&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">|&lt;/span>&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> python -m pip install --upgrade pip
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> pip install requests
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> &lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Run Scraper Script&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">run&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">python scripts/fetch_trends.py&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="nt">name&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Commit and Push Changes&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">run&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">|&lt;/span>&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> git config --local user.email &amp;#34;action@github.com&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> git config --local user.name &amp;#34;GitHub Action&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> git add daily_inputs/
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> git commit -m &amp;#34;Auto-update daily tech trends [skip ci]&amp;#34; || echo &amp;#34;No changes to commit&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="sd"> git push&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Dengan ini, setiap pagi saat Anda membuka Obsidian, topik penting hari itu akan secara otomatis ditambahkan ke kotak masuk (&lt;code>daily_inputs/&lt;/code>) dalam format Markdown.&lt;/p>
&lt;h2 id="4-pembentukan-jaringan-pengetahuan-menggunakan-zettelkasten-dan-obsidian">4. Pembentukan Jaringan Pengetahuan menggunakan Zettelkasten dan Obsidian
&lt;/h2>&lt;p>Informasi yang terkumpul secara otomatis masih sekadar &amp;ldquo;data&amp;rdquo;. Diperlukan proses untuk menyublimasikannya menjadi &amp;ldquo;pengetahuan&amp;rdquo;. Di sinilah metode Zettelkasten dan Obsidian berperan.&lt;/p>
&lt;p>Zettelkasten adalah metode pembuatan catatan yang dirancang oleh sosiolog Jerman, Niklas Luhmann. Alih-alih mengklasifikasikan catatan ke dalam folder hierarkis, metode ini menjaga setiap catatan tetap kecil (atomik) dan menghubungkannya dengan tautan, sehingga membangun jaringan pengetahuan yang menyerupai sirkuit saraf otak.&lt;/p>
&lt;p>Pada umumnya terdapat 3 jenis catatan dalam Zettelkasten:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Fleeting Notes (Catatan Sekilas)&lt;/strong>: Mencatat ide-ide yang muncul atau informasi yang dikumpulkan untuk sementara. Markdown dari informasi tren yang dibuat secara otomatis sebelumnya termasuk dalam kategori ini.&lt;/li>
&lt;li>&lt;strong>Literature Notes (Catatan Literatur)&lt;/strong>: Ringkasan dengan kata-kata sendiri setelah membaca artikel atau buku.&lt;/li>
&lt;li>&lt;strong>Permanent Notes (Catatan Permanen)&lt;/strong>: Berisi pemikiran utuh mengenai satu topik. Inilah yang menjadi benih langsung dari artikel blog.&lt;/li>
&lt;/ol>
&lt;p>Dengan menggunakan fitur backlink Obsidian (&lt;code>[[Nama Catatan]]&lt;/code>), misalnya dengan menautkan catatan &amp;ldquo;Kepemilikan di Rust&amp;rdquo; dan &amp;ldquo;Sejarah Garbage Collection&amp;rdquo;, Anda dapat menemukan koneksi ide yang tidak terduga.&lt;/p>
&lt;h2 id="5-pencarian-semantik-menggunakan-database-vektor-pinecone-dan-openai-embeddings">5. Pencarian Semantik Menggunakan Database Vektor (Pinecone) dan OpenAI Embeddings
&lt;/h2>&lt;p>Ketika jumlah catatan bertambah menjadi ratusan hingga ribuan, akan sulit menemukan catatan yang dituju hanya dengan pencarian kata kunci biasa (pencarian teks penuh). Pencarian semantik, yang memanfaatkan Embeddings dari Large Language Model (LLM), menunjukkan kehebatannya ketika Anda ingin &amp;ldquo;Mencari catatan yang secara konsep mirip meskipun kata kuncinya tidak teringat&amp;rdquo;.&lt;/p>
&lt;p>Menggunakan model &lt;code>text-embedding-ada-002&lt;/code> (atau &lt;code>text-embedding-3-small&lt;/code>) dari OpenAI, setiap catatan Markdown Obsidian dikonversi menjadi vektor multi-dimensi (array numerik yang terdiri dari ratusan hingga ribuan dimensi). Di dalam ruang vektor ini, kalimat dengan makna yang mirip akan memiliki jarak fisik yang lebih dekat antar vektornya.&lt;/p>
&lt;p>Untuk mengukur kemiripan antar vektor, Cosine Similarity (Kesamaan Kosinus) secara luas digunakan.&lt;/p>
$$ \text{similarity} = \cos(\theta) = \frac{\mathbf{A} \cdot \mathbf{B}}{\|\mathbf{A}\| \|\mathbf{B}\|} = \frac{\sum_{i=1}^{n} A_i B_i}{\sqrt{\sum_{i=1}^{n} A_i^2} \sqrt{\sum_{i=1}^{n} B_i^2}} $$&lt;p>$\mathbf{A}$ dan $\mathbf{B}$ masing-masing adalah vektor dari string kueri dan vektor dari catatan. Untuk melakukan perhitungan ini dengan cepat, kita menggunakan database vektor seperti Pinecone atau Qdrant.&lt;/p>
&lt;h3 id="contoh-implementasi-pencarian-semantik">Contoh Implementasi Pencarian Semantik
&lt;/h3>&lt;p>Berikut adalah bagian dari skrip Python yang memindai direktori catatan Obsidian, melakukan vektorisasi dengan OpenAI API, lalu mengunggahnya (upsert - masukkan/perbarui) ke Pinecone.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;span class="lnt">62
&lt;/span>&lt;span class="lnt">63
&lt;/span>&lt;span class="lnt">64
&lt;/span>&lt;span class="lnt">65
&lt;/span>&lt;span class="lnt">66
&lt;/span>&lt;span class="lnt">67
&lt;/span>&lt;span class="lnt">68
&lt;/span>&lt;span class="lnt">69
&lt;/span>&lt;span class="lnt">70
&lt;/span>&lt;span class="lnt">71
&lt;/span>&lt;span class="lnt">72
&lt;/span>&lt;span class="lnt">73
&lt;/span>&lt;span class="lnt">74
&lt;/span>&lt;span class="lnt">75
&lt;/span>&lt;span class="lnt">76
&lt;/span>&lt;span class="lnt">77
&lt;/span>&lt;span class="lnt">78
&lt;/span>&lt;span class="lnt">79
&lt;/span>&lt;span class="lnt">80
&lt;/span>&lt;span class="lnt">81
&lt;/span>&lt;span class="lnt">82
&lt;/span>&lt;span class="lnt">83
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">os&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">glob&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">openai&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">OpenAI&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">pinecone&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Pinecone&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ServerlessSpec&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Pengaturan API Key (Didapat dari environment variables)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">OPENAI_API_KEY&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getenv&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;OPENAI_API_KEY&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">PINECONE_API_KEY&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getenv&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;PINECONE_API_KEY&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">client&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">OpenAI&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">api_key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">OPENAI_API_KEY&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">pc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Pinecone&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">api_key&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">PINECONE_API_KEY&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">INDEX_NAME&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;obsidian-notes&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">OBSIDIAN_DIR&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;/path/to/obsidian/vault/PermanentNotes&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">init_pinecone&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;Inisialisasi indeks Pinecone&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">INDEX_NAME&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">pc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">list_indexes&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">names&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">pc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create_index&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">INDEX_NAME&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">dimension&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1536&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># Dimensi untuk text-embedding-3-small / ada-002&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">metric&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;cosine&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">spec&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">ServerlessSpec&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cloud&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;aws&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">region&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;us-east-1&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">pc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Index&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">INDEX_NAME&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_embedding&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;Vektorisasi teks menggunakan OpenAI API&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">client&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">embeddings&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">input&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">text&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">model&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;text-embedding-3-small&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">embedding&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">sync_notes_to_pinecone&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">index&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;Membaca file Markdown, vektorisasi, dan menyimpannya ke Pinecone&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">md_files&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">glob&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">glob&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">path&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">OBSIDIAN_DIR&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;*.md&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">vectors&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">filepath&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">md_files&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">filename&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">path&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">basename&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">filepath&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">with&lt;/span> &lt;span class="nb">open&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">filepath&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;r&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">encoding&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;utf-8&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">content&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">f&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">read&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Proses hanya jika konten catatan tidak kosong&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Embedding note: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">filename&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">embedding&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_embedding&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">content&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Format Pinecone (id, vector, metadata)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">vectors&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;id&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">filename&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;values&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">embedding&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;metadata&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;text&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="p">[:&lt;/span>&lt;span class="mi">500&lt;/span>&lt;span class="p">]}&lt;/span> &lt;span class="c1"># Sebagian teks untuk ditampilkan pada hasil pencarian&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Upsert melalui batch processing&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">vectors&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">index&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">upsert&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">vectors&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">vectors&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Successfully upserted &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">vectors&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> notes.&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">search_similar_ideas&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">index&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">query_text&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">top_k&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;Mencari catatan yang mirip dengan kueri untuk keperluan ide&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">query_embedding&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_embedding&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">query_text&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">results&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">index&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">vector&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">query_embedding&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">top_k&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">top_k&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">include_metadata&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">--- Search Results for: &amp;#39;&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">query_text&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#39; ---&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="k">match&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">results&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;matches&amp;#34;&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Score: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">match&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;score&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.4f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> | Note: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">match&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;id&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Preview: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">match&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;metadata&amp;#39;&lt;/span>&lt;span class="p">][&lt;/span>&lt;span class="s1">&amp;#39;text&amp;#39;&lt;/span>&lt;span class="p">][:&lt;/span>&lt;span class="mi">100&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">...&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">idx&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">init_pinecone&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Saat dijalankan pertama kali, panggil sync_notes_to_pinecone(idx) untuk membangun DB&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">sync_notes_to_pinecone&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">idx&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Pencarian untuk ide artikel blog&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">search_similar_ideas&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">idx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;Mempercepat inferensi machine learning di browser menggunakan WebAssembly&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Dengan menggunakan sistem ini, ketika Anda bertanya, &amp;ldquo;Saya ingin menulis tentang &amp;lsquo;WebAssembly&amp;rsquo; yang sedang ramai di Hacker News minggu ini, tapi apakah saya pernah menulis catatan terkait sebelumnya?&amp;rdquo;, AI akan dengan instan mengambil Permanent Notes (Catatan Permanen) terdahulu yang relevan secara semantik. Hal ini memungkinkan penulisan artikel mendalam yang sepenuhnya memanfaatkan aset pengetahuan Anda di masa lalu.&lt;/p>
&lt;h2 id="6-pengulangan-berjarak-memanfaatkan-kurva-kelupaan-ebbinghaus-dan-anki">6. Pengulangan Berjarak Memanfaatkan Kurva Kelupaan Ebbinghaus dan Anki
&lt;/h2>&lt;p>Tidak peduli seberapa baik pengetahuan dicatat dalam buku catatan, akan sulit untuk menghubungkan berbagai konsep secara fasih selama proses penulisan jika pengetahuan tersebut belum tertanam di otak penulis. Di sinilah &amp;ldquo;Kurva Kelupaan Ebbinghaus&amp;rdquo; hadir, yang merupakan pemodelan matematis dari mekanisme memori manusia.&lt;/p>
&lt;p>Kurva kelupaan didekati dengan persamaan berikut:&lt;/p>
$$ R = e^{-\frac{t}{S}} $$&lt;p>Di mana:&lt;/p>
&lt;ul>
&lt;li>$R$ adalah tingkat retensi memori (Retrievability, rentang 0 hingga 1)&lt;/li>
&lt;li>$t$ adalah waktu berlalu setelah pembelajaran&lt;/li>
&lt;li>$S$ adalah stabilitas (Stability) atau kekuatan memori&lt;/li>
&lt;/ul>
&lt;p>Tepat setelah mempelajari konsep baru, $S$ berukuran kecil, dan $R$ turun (lupa) secara dramatis seiring berjalannya waktu $t$. Namun, jika Anda melakukan peninjauan kembali (Recall) pada saat-saat yang tepat ketika Anda hampir lupa, kecepatan kelupaan selanjutnya akan melambat ($S$ membesar), dan ingatan tersebut akan beralih menjadi memori jangka panjang.&lt;/p>
&lt;p>Perangkat lunak yang secara otomatis menghitung waktu peninjauan kembali optimal dengan menggunakan algoritme (seperti SuperMemo 2) dan menyajikannya sebagai kartu flash (flashcard) adalah &amp;ldquo;Anki&amp;rdquo;.&lt;/p>
&lt;p>Sebagai pendekatan yang kuat untuk menghasilkan ide blog teknologi, &lt;strong>mengonversi konten Permanent Notes di Obsidian menjadi kartu flash Anki&lt;/strong> bisa dilakukan.
Misalnya, Anda bisa mendaftarkan pertanyaan seputar dasar-dasar teknis ke dalam Anki, seperti &amp;ldquo;Apa 3 elemen dari Teorema CAP?&amp;rdquo; atau &amp;ldquo;Mengapa indeks B-Tree memiliki performa pencarian O(log N)?&amp;rdquo;, lalu meninjaunya kembali sebagai rutinitas harian. Begitu pengetahuan tersebut terindeks dalam otak sebagai memori jangka panjang, informasi-informasi itu akan terhubung di bawah sadar saat Anda mandi atau berjalan-jalan, sehingga memicu ilham (momen Eureka) seperti, &amp;ldquo;Ah, sepertinya saya bisa menulis artikel tentang algoritme konsensus sistem terdistribusi.&amp;rdquo;&lt;/p>
&lt;h2 id="7-kreativitas-kombinatorial-combinatorial-creativity">7. Kreativitas Kombinatorial (Combinatorial Creativity)
&lt;/h2>&lt;p>Melalui pipeline sejauh ini, kita telah mewujudkan &amp;ldquo;Input berbagai informasi&amp;rdquo;, &amp;ldquo;Pengorganisasian dan pencarian AI melalui Zettelkasten&amp;rdquo;, dan &amp;ldquo;Menanamkannya ke memori jangka panjang melalui Anki&amp;rdquo;. Langkah terakhir adalah memadukan elemen-elemen ini untuk menghasilkan ide artikel teknologi yang sama sekali baru melalui &amp;ldquo;Kreativitas Kombinatorial (Combinatorial Creativity)&amp;rdquo;.&lt;/p>
&lt;p>Inovasi dan kreativitas tidak dikatakan muncul dari ketiadaan, melainkan dari kombinasi baru atas elemen-elemen yang sudah ada. Kutipan terkenal Steve Jobs mengatakan, &amp;ldquo;Kreativitas hanyalah menghubungkan hal-hal.&amp;rdquo;&lt;/p>
&lt;p>Untuk pola kombinasi dalam blog teknologi, matriks berikut bisa dipertimbangkan:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>[Teknologi Lama] × [Paradigma Baru]&lt;/strong>: Contoh &amp;ldquo;Belajar dari arsitektur COBOL tentang anti-pattern dalam desain arsitektur microservices modern&amp;rdquo;&lt;/li>
&lt;li>&lt;strong>[Frontend] × [Konsep Backend]&lt;/strong>: Contoh &amp;ldquo;Menjelaskan algoritme pembaruan Virtual DOM React dari perspektif tingkat isolasi transaksi database&amp;rdquo;&lt;/li>
&lt;li>&lt;strong>[Matematika/Teori Abstrak] × [Implementasi Konkret]&lt;/strong>: Contoh &amp;ldquo;Memahami optimasi penjadwalan Pod di Kubernetes melalui teori graf&amp;rdquo;&lt;/li>
&lt;/ol>
&lt;p>Untuk menciptakan kombinasi ini secara sengaja, kita dapat memanfaatkan sistem pencarian semantik Pinecone yang telah dibangun, mengekstrak konsep A dan konsep B secara acak, dan memberikan prompt ke AI (seperti ChatGPT), &amp;ldquo;Berikan 5 ide judul dan draf daftar isi untuk blog teknologi yang menggabungkan 2 konsep ini&amp;rdquo;, sehingga mampu menghasilkan ide-ide artikel dari sudut pandang orisinal tanpa batas yang tidak pernah terpikirkan oleh kita sendiri.&lt;/p>
&lt;h2 id="8-arsitektur-keseluruhan-sistem">8. Arsitektur Keseluruhan Sistem
&lt;/h2>&lt;p>Seluruh arsitektur dari &amp;ldquo;pengumpulan informasi hingga penciptaan ide&amp;rdquo; untuk mencegah kehabisan ide artikel teknologi yang telah dibahas sejauh ini dirangkum dalam diagram alir Mermaid di bawah ini.&lt;/p>
&lt;pre class="mermaid">
flowchart TD
A[&amp;#34;Hacker News / Lobsters API&amp;#34;] --&amp;gt;|Skrip Ekstraksi Python| B[&amp;#34;Data Tren Mentah&amp;#34;]
C[&amp;#34;GitHub Actions (Cron)&amp;#34;] --&amp;gt;|Jadwal Eksekusi Rutin| A
B --&amp;gt;|Konversi Format Markdown| D[&amp;#34;Input Harian (Fleeting Notes)&amp;#34;]
D --&amp;gt;|Membaca dan Meringkas Manual| E[&amp;#34;Obsidian Zettelkasten&amp;#34;]
E --&amp;gt;|Pembuatan Catatan Permanen| F[&amp;#34;Permanent Notes&amp;#34;]
F --&amp;gt;|Proses Sinkronisasi Otomatis| G[&amp;#34;OpenAI Embeddings API&amp;#34;]
G --&amp;gt;|Konversi Vektor| H[&amp;#34;Pinecone Vector Database&amp;#34;]
H --&amp;gt;|Pencarian Semantik| I[&amp;#34;Penemuan &amp;amp; Ekstraksi Pengetahuan Terkait&amp;#34;]
F --&amp;gt;|Pembuatan Kartu Flash| J[&amp;#34;Anki (Spaced Repetition)&amp;#34;]
J --&amp;gt;|Inspirasi dari Memori Jangka Panjang| K[&amp;#34;Combinatorial Creativity&amp;#34;]
I --&amp;gt; K
K --&amp;gt;|Pembuatan Plot / Draf Susunan| L[&amp;#34;Draf Artikel Blog (Penulisan Artikel)&amp;#34;]
&lt;/pre>
&lt;p>Karakteristik sistem ini adalah &lt;strong>pemisahan yang sempurna antara &amp;ldquo;pekerjaan intelektual yang harus dilakukan manual (meringkas, mengobservasi, menulis)&amp;rdquo; dengan &amp;ldquo;pekerjaan yang sebaiknya diserahkan pada mesin (pengumpulan, pencarian, penjadwalan pengulangan berjarak)&amp;rdquo;&lt;/strong>. Dengan hal ini, penulis dapat memfokuskan diri sepenuhnya pada &amp;ldquo;berpikir&amp;rdquo; dan &amp;ldquo;mengkombinasikan&amp;rdquo; yang merupakan hal-hal bernilai tambah paling tinggi.&lt;/p>
&lt;h2 id="9-model-transisi-keadaan-dari-ide-hingga-publikasi">9. Model Transisi Keadaan dari Ide hingga Publikasi
&lt;/h2>&lt;p>Siklus hidup ide-ide yang terkumpul di Zettelkasten, hingga akhirnya diterbitkan sebagai artikel blog, dapat digambarkan dengan diagram transisi keadaan di bawah ini. Kita menggunakan alat dan pendekatan yang tepat pada setiap keadaannya.&lt;/p>
&lt;pre class="mermaid">
stateDiagram-v2
[*] --&amp;gt; Capture[&amp;#34;Idea Capture (Penangkapan Ide)&amp;#34;]
Capture[&amp;#34;Idea Capture (Penangkapan Ide)&amp;#34;] --&amp;gt; Fleeting[&amp;#34;Fleeting Notes (Catatan Sementara)&amp;#34;]
Fleeting[&amp;#34;Fleeting Notes (Catatan Sementara)&amp;#34;] --&amp;gt; Permanent[&amp;#34;Permanent Notes (Catatan Permanen)&amp;#34;]
Permanent[&amp;#34;Permanent Notes (Catatan Permanen)&amp;#34;] --&amp;gt; Brainstorming[&amp;#34;Brainstorming (Pencarian Semantik AI)&amp;#34;]
Permanent[&amp;#34;Permanent Notes (Catatan Permanen)&amp;#34;] --&amp;gt; Memorization[&amp;#34;Memorization (Peninjauan Anki)&amp;#34;]
Memorization[&amp;#34;Memorization (Peninjauan Anki)&amp;#34;] --&amp;gt; Brainstorming[&amp;#34;Brainstorming (Pencarian Semantik AI)&amp;#34;]
Brainstorming[&amp;#34;Brainstorming (Pencarian Semantik AI)&amp;#34;] --&amp;gt; Outlining[&amp;#34;Outlining (Pembuatan Draf Susunan / Daftar Isi)&amp;#34;]
Outlining[&amp;#34;Outlining (Pembuatan Draf Susunan / Daftar Isi)&amp;#34;] --&amp;gt; Drafting[&amp;#34;Drafting (Penulisan Draf Awal)&amp;#34;]
Drafting[&amp;#34;Drafting (Penulisan Draf Awal)&amp;#34;] --&amp;gt; Review[&amp;#34;Review &amp;amp; Edit (Revisi &amp;amp; Penyuntingan)&amp;#34;]
Review[&amp;#34;Review &amp;amp; Edit (Revisi &amp;amp; Penyuntingan)&amp;#34;] --&amp;gt; Published[&amp;#34;Published (Publikasi Blog)&amp;#34;]
Published[&amp;#34;Published (Publikasi Blog)&amp;#34;] --&amp;gt; [*]
&lt;/pre>
&lt;p>Dengan menyadari alur kerja ini, menjadi lebih jelas &amp;ldquo;pada fase mana diri kita sedang terjebak&amp;rdquo;. Saat ide tidak muncul, Anda cukup kembali ke fase &amp;ldquo;Capture&amp;rdquo; atau &amp;ldquo;Permanent&amp;rdquo; untuk memeriksa apakah pipeline input berjalan normal.&lt;/p>
&lt;h2 id="kesimpulan-menulis-adalah-sistem">Kesimpulan: Menulis adalah &amp;ldquo;Sistem&amp;rdquo;
&lt;/h2>&lt;p>&amp;ldquo;Kehabisan ide blog teknologi&amp;rdquo; bukanlah disebabkan oleh kurangnya kemampuan individu atau penurunan motivasi, melainkan &lt;strong>merupakan konsekuensi tak terelakkan dari tidak terbangunnya sistem yang dapat mensirkulasikan pengetahuan&lt;/strong>.&lt;/p>
&lt;p>Seperti yang diperkenalkan pada artikel ini,&lt;/p>
&lt;ol>
&lt;li>Mengamankan input berkualitas dengan noise rendah melalui &lt;strong>API dan otomatisasi&lt;/strong>&lt;/li>
&lt;li>Membangun jaringan pengetahuan dengan Zettelkasten menggunakan &lt;strong>Obsidian&lt;/strong>&lt;/li>
&lt;li>Melakukan pencarian semantik aset pengetahuan diri sendiri melalui &lt;strong>OpenAI dan Pinecone&lt;/strong>&lt;/li>
&lt;li>Memperkuat indeks di dalam otak dengan memanfaatkan &lt;strong>Anki&lt;/strong> dan kurva kelupaan Ebbinghaus&lt;/li>
&lt;li>&lt;strong>Kreativitas kombinatorial&lt;/strong> yang memadukan konsep-konsep yang ada&lt;/li>
&lt;/ol>
&lt;p>Dengan membangun pipeline komprehensif yang memadukan semuanya, alih-alih mengering, ide blog Anda akan terus bereproduksi dan bertambah banyak seiring dengan makin seringnya Anda menulis.&lt;/p>
&lt;p>Anda tidak perlu membangun segalanya dengan sempurna sejak awal. Sebagai permulaan, cobalah membuat skrip sederhana yang mengakses API Hacker News, dan biasakan untuk mencatat artikel yang menarik perhatian Anda dalam format markdown. Saya berharap blog teknologi Anda akan menjadi sumber ide-ide cemerlang bagi generasi mendatang.&lt;/p></description></item><item><title>SEO untuk Blog Hugo: Pengaturan Frontmatter yang Secara Dramatis Meningkatkan Jumlah Pengunjung</title><link>http://kenji.blog/id/p/hugo-blog-seo-frontmatter-tips/</link><pubDate>Sat, 12 Sep 2026 12:00:00 +0900</pubDate><guid>http://kenji.blog/id/p/hugo-blog-seo-frontmatter-tips/</guid><description>&lt;img src="http://kenji.blog/p/hugo-blog-seo-frontmatter-tips/img/eyecatch.jpg" alt="Featured image of post SEO untuk Blog Hugo: Pengaturan Frontmatter yang Secara Dramatis Meningkatkan Jumlah Pengunjung" />&lt;p>Hugo adalah salah satu generator situs statis (SSG) tercepat di dunia, ditulis dalam bahasa Go. Karena kecepatan build yang luar biasa dan sistem template yang fleksibel, Hugo sangat didukung oleh banyak insinyur dan blogger. Namun, hanya karena sebuah situs dibangun dan ditampilkan dengan cepat bukan berarti situs tersebut akan dinilai tinggi oleh mesin pencari (seperti Google atau Bing) dan menjangkau pengguna.&lt;/p>
&lt;p>Untuk meningkatkan peringkat pencarian, meningkatkan penyebaran di media sosial, dan pada akhirnya secara dramatis meningkatkan lalu lintas ke blog Anda, optimasi mesin pencari (SEO) yang cermat sangatlah penting. Inti dari strategi SEO di Hugo adalah kolaborasi antara &lt;strong>frontmatter&lt;/strong> (yang ditulis di awal setiap artikel markdown) dan &lt;strong>template&lt;/strong> (Layouts) yang menafsirkannya dan menyebarkan metadata di dalam tag &lt;code>&amp;lt;head&amp;gt;&lt;/code> HTML.&lt;/p>
&lt;p>Dalam artikel ini, kami akan menjelaskan secara menyeluruh cara memaksimalkan fitur Hugo untuk mengimplementasikan strategi SEO tingkat lanjut, dengan volume yang melebihi 10.000 karakter, mulai dari pengaturan frontmatter hingga berbagai meta tag, OGP (Open Graph Protocol), Twitter Cards, dan output data terstruktur menggunakan JSON-LD.&lt;/p>
&lt;hr>
&lt;h2 id="1-latar-belakang-matematis-seo-dan-lalu-lintas">1. Latar Belakang Matematis SEO dan Lalu Lintas
&lt;/h2>&lt;p>Sebelum masuk ke implementasi spesifik, mari kita pahami secara matematis mengapa metadata SEO yang detail itu penting. Lalu lintas pencarian $T$ yang dapat diperoleh sebuah situs web ditentukan oleh volume pencarian kata kunci yang ditargetkan dan rasio klik-tayang (CTR) berdasarkan peringkat pencarian.&lt;/p>
&lt;p>Ini dapat dinyatakan dalam rumus berikut:&lt;/p>
$$ T = \sum_{i=1}^{n} V_i \times CTR(R_i) $$&lt;ul>
&lt;li>$V_i$ : Volume pencarian bulanan untuk kata kunci $i$&lt;/li>
&lt;li>$R_i$ : Peringkat pencarian untuk kata kunci $i$&lt;/li>
&lt;li>$CTR(R_i)$ : Rasio klik-tayang (CTR) pada peringkat $R_i$&lt;/li>
&lt;/ul>
&lt;p>Dari faktor-faktor ini, peringkat pencarian $R_i$ bergantung pada banyak faktor seperti kualitas konten dan backlink (PageRank), tetapi algoritma PageRank awal Google dimodelkan sebagai berikut:&lt;/p>
$$ PR(u) = \frac{1-d}{N} + d \sum_{v \in B(u)} \frac{PR(v)}{L(v)} $$&lt;ul>
&lt;li>$PR(u)$ : PageRank dari halaman $u$&lt;/li>
&lt;li>$d$ : Faktor redaman (Damping factor, biasanya 0.85)&lt;/li>
&lt;li>$B(u)$ : Kumpulan halaman yang menautkan ke halaman $u$&lt;/li>
&lt;li>$L(v)$ : Jumlah tautan keluar dari halaman $v$&lt;/li>
&lt;/ul>
&lt;p>Hal penting di sini adalah, &lt;strong>selain upaya untuk meningkatkan peringkat pencarian $R_i$, bagaimana memaksimalkan rasio klik-tayang $CTR(R_i)$&lt;/strong>. Dengan mengoptimalkan judul dan cuplikan (description) yang ditampilkan di hasil pencarian (SERP), dan gambar utama (OGP) saat dibagikan di media sosial, Anda dapat secara sengaja meningkatkan $CTR(R_i)$. Pengaturan SEO pada frontmatter secara langsung terhubung dengan pemaksimalan $CTR$ ini.&lt;/p>
&lt;hr>
&lt;h2 id="2-proses-build-hugo-dan-peran-frontmatter">2. Proses Build Hugo dan Peran Frontmatter
&lt;/h2>&lt;p>Hugo membaca frontmatter (YAML/TOML/JSON) di dalam file markdown dan meneruskannya sebagai variabel halaman ke mesin template. Pertama, mari kita pahami aliran informasi ini secara visual.&lt;/p>
&lt;pre class="mermaid">
flowchart TD
A[&amp;#34;File Markdown&amp;#34;] --&amp;gt; B[&amp;#34;Parsing Frontmatter&amp;#34;]
A --&amp;gt; C[&amp;#34;Parsing Konten&amp;#34;]
B --&amp;gt; D[&amp;#34;Variabel Halaman Hugo (.Title, .Params)&amp;#34;]
C --&amp;gt; D
E[&amp;#34;layouts/partials/head.html&amp;#34;] --&amp;gt; F[&amp;#34;Mesin Template Go&amp;#34;]
D --&amp;gt; F
F --&amp;gt; G[&amp;#34;Tag &amp;lt;head&amp;gt; HTML Akhir&amp;#34;]
G --&amp;gt; H[&amp;#34;Googlebot / Crawler&amp;#34;]
G --&amp;gt; I[&amp;#34;Scraper Media Sosial (OGP)&amp;#34;]
&lt;/pre>
&lt;p>Dengan cara ini, nilai yang ditetapkan di frontmatter diteruskan ke &lt;code>head.html&lt;/code> sebagai variabel seperti &lt;code>.Title&lt;/code> dan &lt;code>.Params.description&lt;/code>, dan ditampilkan sebagai metadata HTML akhir. Oleh karena itu, keberhasilan SEO terdiri dari dua langkah: &amp;ldquo;mendefinisikan informasi yang tepat di frontmatter&amp;rdquo; dan &amp;ldquo;mengubahnya dengan benar menjadi HTML dalam template&amp;rdquo;.&lt;/p>
&lt;hr>
&lt;h2 id="3-pengaturan-metadata-dasar-title-description-canonical-url">3. Pengaturan Metadata Dasar: Title, Description, Canonical URL
&lt;/h2>&lt;p>Tag paling dasar agar mesin pencari memahami konten halaman Anda adalah &lt;code>&amp;lt;title&amp;gt;&lt;/code> dan &lt;code>&amp;lt;meta name=&amp;quot;description&amp;quot;&amp;gt;&lt;/code>. Selain itu, &lt;code>&amp;lt;link rel=&amp;quot;canonical&amp;quot;&amp;gt;&lt;/code> juga wajib ada untuk menghindari hukuman karena konten duplikat.&lt;/p>
&lt;h3 id="31-contoh-pengaturan-frontmatter">3.1. Contoh Pengaturan Frontmatter
&lt;/h3>&lt;p>Kami menyiapkan kolom khusus untuk SEO di frontmatter artikel.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">title: &amp;#39;SEO untuk Blog Hugo&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Pengaturan Frontmatter yang Secara Dramatis Meningkatkan Jumlah Pengunjung&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">seo_title: &amp;#39;Panduan Lengkap SEO Hugo: Meningkatkan Lalu Lintas dengan Frontmatter&amp;#39; # Opsional&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">Untuk mesin pencari&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">description&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;Metode strategi SEO lanjutan menggunakan frontmatter Hugo. Penjelasan terperinci tentang cara mengatur OGP, JSON-LD, dan metadata.&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">slug&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;hugo-seo-frontmatter-tips&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">canonicalUrl&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;https://example.com/post/hugo-seo-frontmatter-tips/&amp;#34;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># URL kanonis eksplisit&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="32-implementasi-layoutspartialsheadhtml">3.2. Implementasi &lt;code>layouts/partials/head.html&lt;/code>
&lt;/h3>&lt;p>Kami akan membuat template HTML untuk mengeluarkan variabel-variabel ini dengan benar.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-html" data-lang="html">&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- Optimasi Judul --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ $title := .Title }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ if .Params.seo_title }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> {{ $title = .Params.seo_title }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ end }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">title&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>{{ $title }} | {{ .Site.Title }}&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">title&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- Optimasi Description --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ $description := .Summary | plainify | truncate 120 }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ if .Params.description }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> {{ $description = .Params.description }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ end }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;description&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;{{ $description }}&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- Canonical URL (Kanonisasi) --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ $canonical := .Permalink }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ if .Params.canonicalUrl }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> {{ $canonical = .Params.canonicalUrl }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ end }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">link&lt;/span> &lt;span class="na">rel&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;canonical&amp;#34;&lt;/span> &lt;span class="na">href&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;{{ $canonical }}&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- Kontrol Robot (mis. pengaturan tolak indeks) --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ if .Params.noindex }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;robots&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;noindex, nofollow&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ else }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;robots&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;index, follow&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ end }}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Dengan menggunakan &lt;code>.Summary&lt;/code> Hugo sebagai fallback, Anda dapat secara otomatis mengekstrak kalimat awal artikel bahkan jika &lt;code>description&lt;/code> belum diatur.&lt;/p>
&lt;hr>
&lt;h2 id="4-ogp-dan-twitter-cards-memaksimalkan-ctr-di-media-sosial">4. OGP dan Twitter Cards: Memaksimalkan CTR di Media Sosial
&lt;/h2>&lt;p>Untuk membuat artikel Anda muncul dalam format kartu yang menarik saat dibagikan di SNS seperti Twitter (X) atau Facebook, pengaturan Open Graph Protocol (OGP) dan Twitter Cards sangatlah penting. Ini juga dibuat secara dinamis dari frontmatter.&lt;/p>
&lt;h3 id="41-masalah-dengan-template-bawaan">4.1. Masalah dengan Template Bawaan
&lt;/h3>&lt;p>Hugo memiliki template bawaan yang mudah digunakan yaitu &lt;code>{{ template &amp;quot;_internal/opengraph.html&amp;quot; . }}&lt;/code>, namun kurang dapat disesuaikan dan mungkin tidak sesuai dengan lingkungan bahasa tertentu atau persyaratan khusus. Karena itu, kami sangat menyarankan untuk mengimplementasikan tag OGP kustom Anda sendiri di dalam &lt;code>head.html&lt;/code>.&lt;/p>
&lt;h3 id="42-menentukan-gambar-di-frontmatter">4.2. Menentukan Gambar di Frontmatter
&lt;/h3>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">image&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;img/eyecatch.jpg&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">images&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;img/eyecatch-large.jpg&amp;#34;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c"># Untuk beberapa gambar atau jalur absolut&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="43-kode-implementasi-kustom-ogp-dan-twitter-cards">4.3. Kode Implementasi Kustom OGP dan Twitter Cards
&lt;/h3>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-html" data-lang="html">&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- Open Graph Protocol --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">property&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;og:title&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;{{ $title }}&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">property&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;og:description&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;{{ $description }}&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">property&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;og:type&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;{{ if .IsPage }}article{{ else }}website{{ end }}&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">property&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;og:url&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;{{ .Permalink }}&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">property&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;og:site_name&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;{{ .Site.Title }}&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- Resolusi OGP Image --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ $ogImage := &amp;#34;&amp;#34; }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ if .Params.image }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> {{ $ogImage = .Params.image | absURL }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ else if .Params.images }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> {{ $ogImage = index .Params.images 0 | absURL }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ else if .Site.Params.defaultImage }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> {{ $ogImage = .Site.Params.defaultImage | absURL }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ end }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ if $ogImage }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">property&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;og:image&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;{{ $ogImage }}&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;twitter:image&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;{{ $ogImage }}&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;twitter:card&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;summary_large_image&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ else }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;twitter:card&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;summary&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ end }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- Twitter Cards --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;twitter:title&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;{{ $title }}&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;twitter:description&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;{{ $description }}&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ if .Site.Params.twitterAccount }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">meta&lt;/span> &lt;span class="na">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;twitter:site&amp;#34;&lt;/span> &lt;span class="na">content&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;@{{ .Site.Params.twitterAccount }}&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ end }}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Dengan memasukkan fungsi &lt;code>absURL&lt;/code>, Anda dapat mengonversi URL gambar relatif menjadi URL absolut. Karena jalur absolut diperlukan untuk OGP, proses ini sangatlah penting.&lt;/p>
&lt;hr>
&lt;h2 id="5-implementasi-data-terstruktur-json-ld">5. Implementasi Data Terstruktur (JSON-LD)
&lt;/h2>&lt;p>Dalam SEO modern, &lt;strong>JSON-LD (JavaScript Object Notation for Linked Data)&lt;/strong> telah menjadi metode utama untuk secara akurat menyampaikan struktur semantik halaman ke mesin pencari. Dengan mengatur ini, rich snippet (peringkat bintang, nama penulis, tanggal publikasi, dll.) lebih mungkin muncul di hasil pencarian.&lt;/p>
&lt;h3 id="51-struktur-json-ld">5.1. Struktur JSON-LD
&lt;/h3>&lt;p>Untuk artikel blog, kita akan mengimplementasikan dua skema utama: skema &lt;code>Article&lt;/code> (Artikel) dan skema &lt;code>BreadcrumbList&lt;/code> (Daftar Breadcrumb).&lt;/p>
&lt;pre class="mermaid">
flowchart TD
A[&amp;#34;Definisi Schema.org&amp;#34;] --&amp;gt; B[&amp;#34;Skema Article&amp;#34;]
A --&amp;gt; C[&amp;#34;Skema BreadcrumbList&amp;#34;]
B --&amp;gt; D[&amp;#34;headline&amp;#34;]
B --&amp;gt; E[&amp;#34;datePublished&amp;#34;]
B --&amp;gt; F[&amp;#34;dateModified&amp;#34;]
B --&amp;gt; G[&amp;#34;author&amp;#34;]
B --&amp;gt; H[&amp;#34;image&amp;#34;]
C --&amp;gt; I[&amp;#34;ListItem 1&amp;#34;]
C --&amp;gt; J[&amp;#34;ListItem 2&amp;#34;]
I --&amp;gt; K[&amp;#34;position: 1&amp;#34;]
I --&amp;gt; L[&amp;#34;name: Beranda&amp;#34;]
J --&amp;gt; M[&amp;#34;position: 2&amp;#34;]
J --&amp;gt; N[&amp;#34;name: Kategori / Blog&amp;#34;]
&lt;/pre>
&lt;h3 id="52-pembuatan-json-ld-di-template-hugo">5.2. Pembuatan JSON-LD di Template Hugo
&lt;/h3>&lt;p>Memanfaatkan variabel frontmatter seperti &lt;code>.Date&lt;/code> dan &lt;code>.Lastmod&lt;/code>, JSON-LD dihasilkan secara dinamis. Ditulis di &lt;code>head.html&lt;/code> menggunakan tag &lt;code>&amp;lt;script type=&amp;quot;application/ld+json&amp;quot;&amp;gt;&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;span class="lnt">59
&lt;/span>&lt;span class="lnt">60
&lt;/span>&lt;span class="lnt">61
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-html" data-lang="html">&lt;span class="line">&lt;span class="cl">{{ if .IsPage }}
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">script&lt;/span> &lt;span class="na">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;application/ld+json&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@context&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;https://schema.org&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;Article&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;mainEntityOfPage&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;WebPage&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@id&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ .Permalink }}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;headline&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ .Title | htmlEscape }}&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;description&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ $description | htmlEscape }}&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;image&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ $ogImage }}&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;datePublished&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ .Date.Format &amp;#34;&lt;/span>&lt;span class="mi">2006&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">01&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">02&lt;/span>&lt;span class="nx">T15&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mi">04&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mi">05&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">07&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mi">00&lt;/span>&lt;span class="s2">&amp;#34; }}&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;dateModified&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ .Lastmod.Format &amp;#34;&lt;/span>&lt;span class="mi">2006&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">01&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">02&lt;/span>&lt;span class="nx">T15&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mi">04&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mi">05&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="mi">07&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mi">00&lt;/span>&lt;span class="s2">&amp;#34; }}&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;author&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;Person&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ if .Params.author }}{{ .Params.author }}{{ else }}{{ .Site.Params.author }}{{ end }}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;publisher&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;Organization&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ .Site.Title }}&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;logo&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;ImageObject&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;url&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ .Site.Params.logo | absURL }}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">script&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- Skema BreadcrumbList --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">script&lt;/span> &lt;span class="na">type&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;application/ld+json&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@context&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;https://schema.org&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;BreadcrumbList&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;itemListElement&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;ListItem&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;position&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;Beranda&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;item&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ .Site.BaseURL }}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{{&lt;/span> &lt;span class="nx">$position&lt;/span> &lt;span class="o">:=&lt;/span> &lt;span class="mi">2&lt;/span> &lt;span class="p">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{{&lt;/span> &lt;span class="nx">range&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="nx">Params&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">categories&lt;/span> &lt;span class="p">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">,{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;ListItem&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;position&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{{&lt;/span> &lt;span class="nx">$position&lt;/span> &lt;span class="p">}},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ . }}&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;item&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ &amp;#34;&lt;/span>&lt;span class="nx">categories&lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="s2">&amp;#34; | relLangURL }}{{ . | urlize | lower }}/&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{{&lt;/span> &lt;span class="nx">$position&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">add&lt;/span> &lt;span class="nx">$position&lt;/span> &lt;span class="mi">1&lt;/span> &lt;span class="p">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{{&lt;/span> &lt;span class="nx">end&lt;/span> &lt;span class="p">}}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">,{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;@type&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;ListItem&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;position&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{{&lt;/span> &lt;span class="nx">$position&lt;/span> &lt;span class="p">}},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ .Title | htmlEscape }}&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;item&amp;#34;&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s2">&amp;#34;{{ .Permalink }}&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">script&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">{{ end }}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Saat memperluas string di dalam JSON-LD, poin pentingnya adalah menggunakan &lt;code>htmlEscape&lt;/code> (atau &lt;code>jsonify&lt;/code>) untuk mencegah rusaknya tanda kutip ganda. Dengan demikian, simbol apa pun yang digunakan dalam frontmatter, Anda dapat mencegah kesalahan sintaks JSON.&lt;/p>
&lt;hr>
&lt;h2 id="6-teknik-pemanfaatan-lanjutan-frontmatter">6. Teknik Pemanfaatan Lanjutan Frontmatter
&lt;/h2>&lt;p>Selain metadata SEO dasar, frontmatter Hugo memiliki fitur untuk mewujudkan strategi SEO yang lebih canggih.&lt;/p>
&lt;h3 id="61-penanganan-pengalihan-menggunakan-alias-aliases">6.1. Penanganan Pengalihan menggunakan Alias (Aliases)
&lt;/h3>&lt;p>Saat Anda bermigrasi ke Hugo dari layanan blog sebelumnya, atau saat Anda mengubah struktur permalink, Anda perlu mengalihkan lalu lintas dari URL lama ke URL baru. Dengan menggunakan kolom &lt;code>aliases&lt;/code> Hugo, Anda dapat secara otomatis membuat halaman penyegaran HTTP-Equiv (meta redirect) untuk URL lama.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">title&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;Judul Artikel Baru&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">slug&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;new-seo-post&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">aliases&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;/old-category/old-seo-post/&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>- &lt;span class="s2">&amp;#34;/2020/05/12/seo-tips/&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="62-waktu-kedaluwarsa-artikel-dan-penjadwalan">6.2. Waktu Kedaluwarsa Artikel dan Penjadwalan
&lt;/h3>&lt;p>Untuk artikel kampanye dalam waktu terbatas, atau informasi yang kehilangan nilainya saat sudah usang, Anda dapat mengatur &lt;code>expiryDate&lt;/code> agar mengecualikannya dari hasil build setelah tanggal dan waktu tertentu, sehingga tidak ditampilkan di situs (akan mengembalikan 404). Ini mencegah konten lama berkualitas rendah tetap berada di indeks dan menurunkan peringkat situs secara keseluruhan.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">title&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;Teknik SEO Terbatas Tahun 2026&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">publishDate&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;2026-01-01T00:00:00Z&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">expiryDate&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s2">&amp;#34;2026-12-31T23:59:59Z&amp;#34;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nn">---&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;hr>
&lt;h2 id="7-kinerja-situs-dan-core-web-vitals">7. Kinerja Situs dan Core Web Vitals
&lt;/h2>&lt;p>Dalam SEO, &lt;strong>kecepatan memuat halaman&lt;/strong> sama pentingnya dengan optimasi tag. Google memasukkan Core Web Vitals (LCP, FID/INP, CLS) sebagai faktor peringkat.&lt;/p>
&lt;p>Sebagai situs statis, Hugo pada dasarnya memiliki TTFB (Time to First Byte) yang sangat baik, tetapi untuk blog yang menggunakan banyak gambar, optimasi gambar adalah suatu keharusan. Dengan menggabungkan fitur pemrosesan gambar Hugo yang kuat (Image Processing) dengan frontmatter, Anda dapat mengotomatiskan konversi ke format generasi berikutnya (seperti WebP) dan mengubah ukuran saat proses build.&lt;/p>
&lt;p>Misalnya, Anda dapat membuat shortcode yang secara otomatis menghasilkan gambar WebP di sisi template dari jalur gambar yang ditentukan di frontmatter. Ini dapat secara dramatis meningkatkan penilaian SEO Anda.&lt;/p>
&lt;hr>
&lt;h2 id="8-kesimpulan">8. Kesimpulan
&lt;/h2>&lt;p>Dalam pengoperasian blog menggunakan Hugo, frontmatter bukanlah sekadar &amp;ldquo;daftar pengaturan&amp;rdquo;, melainkan &amp;ldquo;panel kontrol&amp;rdquo; untuk berinteraksi dengan mesin pencari dan media sosial.&lt;/p>
&lt;p>Dengan menerapkan poin-poin yang dijelaskan dalam artikel ini secara menyeluruh, fondasi SEO blog Anda akan menjadi sangat kuat.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Pembuatan metadata dasar yang dinamis&lt;/strong>: Menghasilkan Title, Description, dan Canonical dengan andal&lt;/li>
&lt;li>&lt;strong>Optimasi berbagi di media sosial&lt;/strong>: Meningkatkan CTR melalui implementasi kustom OGP dan Twitter Cards&lt;/li>
&lt;li>&lt;strong>Dukungan penuh untuk data terstruktur&lt;/strong>: Mendukung Rich Results menggunakan JSON-LD (Article, Breadcrumb)&lt;/li>
&lt;li>&lt;strong>Manajemen lalu lintas tingkat lanjut&lt;/strong>: Pengalihan menggunakan Aliases dan kontrol robot menggunakan meta tag&lt;/li>
&lt;/ol>
&lt;p>Meskipun algoritma mesin pencari terus berkembang dari hari ke hari, prinsip dasar SEO—menyediakan sinyal agar mesin pencari dapat &amp;ldquo;memahami konten halaman dengan benar&amp;rdquo;—tetap tidak berubah. Dengan menguasai mesin template yang fleksibel dan frontmatter Hugo, Anda dapat terus mengirimkan sinyal berkualitas tinggi tersebut dan meningkatkan jumlah pengunjung blog Anda secara dramatis.&lt;/p></description></item><item><title>Strategi Menulis Ulang Artikel Teknis Menggunakan Google Search Console</title><link>http://kenji.blog/id/p/google-search-console-rewrite-strategy/</link><pubDate>Sat, 12 Sep 2026 12:00:00 +0900</pubDate><guid>http://kenji.blog/id/p/google-search-console-rewrite-strategy/</guid><description>&lt;img src="http://kenji.blog/p/google-search-console-rewrite-strategy/img/eyecatch.jpg" alt="Featured image of post Strategi Menulis Ulang Artikel Teknis Menggunakan Google Search Console" />&lt;h2 id="1-pendahuluan-pentingnya-menulis-ulang-di-blog-teknis-dan-pendekatan-berbasis-data">1. Pendahuluan: Pentingnya Menulis Ulang di Blog Teknis dan Pendekatan Berbasis Data
&lt;/h2>&lt;p>Dalam mengelola blog teknis atau media milik (owned media) yang ditujukan untuk developer, &amp;ldquo;menulis ulang artikel lama&amp;rdquo; sama pentingnya, atau bahkan lebih penting, daripada terus-menerus menulis artikel baru. Khususnya pada topik IT dan teknologi, informasi cepat menjadi usang. Bukan hal yang aneh jika snippet kode atau spesifikasi API yang ditulis beberapa tahun lalu kini telah usang (Deprecated). Namun, sekadar memperbarui artikel lama secara asal-asalan tidak akan memaksimalkan trafik (kunjungan) dari mesin pencari.&lt;/p>
&lt;p>Oleh karena itu, artikel ini akan menjelaskan strategi tingkat lanjut untuk mengidentifikasi artikel teknis mana yang harus ditulis ulang dengan menggunakan data dari &lt;strong>Google Search Console (selanjutnya disebut GSC)&lt;/strong> dan &lt;strong>Google Analytics 4 (GA4)&lt;/strong>. Dengan menggunakan pendekatan berbasis data dan matematis, strategi ini bertujuan untuk meningkatkan peringkat pencarian dan rasio klik-tayang (CTR) secara drastis.&lt;/p>
&lt;p>Secara khusus, artikel ini akan membahas secara komprehensif mulai dari cara menemukan &amp;ldquo;artikel yang kehilangan peluang&amp;rdquo; dengan CTR rendah dibandingkan jumlah impresi (tayangan) menggunakan Python dan BigQuery untuk mengintegrasikan data GSC dan GA4, hingga metode untuk mengidentifikasi kata kunci yang kurang pada heading H2 atau H3 menggunakan analisis TF-IDF dari NLP (Natural Language Processing) untuk mengisi celah konten secara efisien.&lt;/p>
&lt;hr>
&lt;h2 id="2-analisis-kesenjangan-antara-ctr-yang-diharapkan-dan-ctr-aktual-pengenalan-model-matematis">2. Analisis Kesenjangan antara CTR yang Diharapkan dan CTR Aktual (Pengenalan Model Matematis)
&lt;/h2>&lt;p>Salah satu metrik paling dasar dalam SEO adalah &amp;ldquo;Rasio Klik-Tayang (CTR) terhadap peringkat pencarian&amp;rdquo;. Secara umum, jika peringkat pencarian ada di posisi 1, CTR-nya sekitar 25-30%, di posisi 2 sekitar 15%, dan menurun drastis setelah itu. Hubungan antara peringkat dan CTR ini dapat dimodelkan sebagai distribusi yang mengikuti Hukum Pangkat (Power Law).&lt;/p>
&lt;p>CTR yang diharapkan $CTR(r)$ untuk peringkat $r$ diketahui dapat diperkirakan dengan rumus berikut:&lt;/p>
$$
CTR(r) = a \cdot r^{-b}
$$&lt;p>Di sini, $a$ adalah CTR yang diharapkan saat berada di posisi 1 (misal: $0.30$ untuk 30%), dan $b$ adalah parameter peluruhan (umumnya antara $1.0$ hingga $1.5$).&lt;/p>
&lt;p>Pendekatan paling efektif saat memilih artikel yang akan ditulis ulang adalah &lt;strong>menemukan artikel (kata kunci) yang &amp;ldquo;CTR aktual&amp;rdquo;-nya jauh di bawah &amp;ldquo;CTR yang diharapkan&amp;rdquo; ini&lt;/strong>. Misalnya, meskipun peringkat pencarian berada di posisi 3 (CTR yang diharapkan sekitar 10%), tetapi CTR aktual hanya 2%. Dalam kasus ini, sangat mungkin ada ketidaksesuaian antara niat pencarian (search intent) dengan judul/deskripsi, atau klik direbut oleh faktor kompetitor seperti rich snippet.&lt;/p>
&lt;p>Grafik berikut adalah ilustrasi yang menunjukkan kesenjangan antara CTR yang diharapkan dan CTR aktual pada sebuah blog teknis.&lt;/p>
&lt;pre class="mermaid">
xychart-beta
title Expected CTR vs Actual CTR by Position
x-axis [&amp;#34;1&amp;#34;, &amp;#34;2&amp;#34;, &amp;#34;3&amp;#34;, &amp;#34;4&amp;#34;, &amp;#34;5&amp;#34;, &amp;#34;6&amp;#34;, &amp;#34;7&amp;#34;, &amp;#34;8&amp;#34;, &amp;#34;9&amp;#34;, &amp;#34;10&amp;#34;]
y-axis &amp;#34;CTR (%)&amp;#34; 0 --&amp;gt; 35
line [30.5, 15.2, 10.1, 7.5, 5.2, 4.1, 3.2, 2.5, 2.0, 1.5]
bar [32.1, 14.0, 8.5, 4.0, 5.0, 2.1, 1.5, 1.0, 1.2, 0.5]
&lt;/pre>
&lt;p>(* Garis menunjukkan CTR yang diharapkan, sedangkan diagram batang menunjukkan CTR aktual. Terlihat jelas bahwa pada posisi ke-4 dan ke-8 nilainya jauh di bawah ekspektasi.)&lt;/p>
&lt;hr>
&lt;h2 id="3-ekstraksi-data-performa-pencarian-secara-otomatis-menggunakan-api-gsc-python">3. Ekstraksi Data Performa Pencarian Secara Otomatis Menggunakan API GSC (Python)
&lt;/h2>&lt;p>Walaupun memungkinkan untuk mengunduh CSV dari UI web GSC untuk dianalisis, cara terbaik untuk melakukan analisis berkelanjutan atau pada blog berskala besar adalah membangun sistem ekstraksi data otomatis dengan Python menggunakan API GSC.&lt;/p>
&lt;p>Berikut adalah snippet Python yang menggunakan &lt;code>google-api-python-client&lt;/code> untuk mengambil data performa (jumlah klik, jumlah impresi, CTR, peringkat rata-rata) berdasarkan halaman dan kueri pada periode tertentu.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">pandas&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">pd&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">google.oauth2&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">service_account&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">googleapiclient.discovery&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">build&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_gsc_data&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">key_path&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">site_url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">start_date&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">end_date&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Memuat kredensial dan membangun klien API&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">credentials&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">service_account&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Credentials&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">from_service_account_file&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">key_path&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">scopes&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;https://www.googleapis.com/auth/webmasters.readonly&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">service&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">build&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;searchconsole&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;v1&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">credentials&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">credentials&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Mengatur payload permintaan API (menentukan halaman dan kueri sebagai dimensi)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">request&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;startDate&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">start_date&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;endDate&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">end_date&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;dimensions&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;page&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;query&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;rowLimit&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mi">25000&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Menjalankan API&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">response&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">service&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">searchanalytics&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">query&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">siteUrl&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">site_url&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">body&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">request&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">execute&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Mengekstrak data dari respons dan mengubahnya menjadi Pandas DataFrame&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">rows&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">response&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;rows&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">row&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">rows&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">keys&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">row&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;keys&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">data&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;page&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">keys&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;query&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">keys&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;clicks&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">row&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;clicks&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;impressions&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">row&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;impressions&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;ctr&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">row&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;ctr&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s1">&amp;#39;position&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">row&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;position&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DataFrame&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Contoh eksekusi&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># df_gsc = get_gsc_data(&amp;#39;credentials.json&amp;#39;, &amp;#39;https://kenji.blog/&amp;#39;, &amp;#39;2026-08-01&amp;#39;, &amp;#39;2026-08-31&amp;#39;)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># print(df_gsc.head())&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Melalui skrip ini, Anda dapat memperoleh data terperinci yang menghubungkan URL halaman dan kueri pencarian sebagai DataFrame. Hal ini memungkinkan Anda untuk memahami secara komprehensif kata kunci apa yang memunculkan artikel tertentu.&lt;/p>
&lt;hr>
&lt;h2 id="4-pemfilteran-kata-kunci-teknis-menggunakan-regular-expression-regex">4. Pemfilteran Kata Kunci Teknis Menggunakan Regular Expression (Regex)
&lt;/h2>&lt;p>Fitur yang sangat kuat dalam menganalisis blog teknis adalah &lt;strong>filter regular expression (Regex)&lt;/strong> di GSC.
Misalnya, jika Anda menulis artikel yang mencakup berbagai topik mulai dari frontend, backend, hingga infrastruktur, Anda mungkin hanya ingin mengekstrak &amp;ldquo;artikel tutorial dan error seputar Python dan Pandas&amp;rdquo; untuk menentukan prioritas penulisan ulang.&lt;/p>
&lt;p>Menggunakan filter regex kustom GSC memungkinkan Anda untuk menyaring kueri dengan kondisi yang kompleks.&lt;/p>
&lt;p>&lt;strong>Contoh Praktis Pemfilteran Kata Kunci Teknis:&lt;/strong>&lt;/p>
&lt;ul>
&lt;li>Penyelidikan error terkait Python: &lt;code>^(python|pandas|numpy|matplotlib).* (error|exception|bug|エラー|動かない)&lt;/code>&lt;/li>
&lt;li>Pembangunan infrastruktur terkait AWS: &lt;code>(aws|amazon web services|ec2|s3|lambda).* (構築|設定|チュートリアル|tutorial|how to)&lt;/code>&lt;/li>
&lt;li>Pembaruan versi library tertentu: &lt;code>(react|vue|angular) (v17|v18|v3) (migration|マイグレーション|移行)&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>Ketika mengintegrasikan ini ke dalam permintaan API GSC, Anda dapat menerapkan kondisi regex dengan memanfaatkan &lt;code>dimensionFilterGroups&lt;/code>. Dengan menggunakan pemfilteran ini, Anda dapat menargetkan kata kunci penyelesaian masalah bernilai tinggi yang diketik oleh para developer yang &amp;ldquo;benar-benar sedang mengalami kendala&amp;rdquo;.&lt;/p>
&lt;hr>
&lt;h2 id="5-mengintegrasikan-data-ga4-dan-gsc-dengan-bigquerypandas">5. Mengintegrasikan Data GA4 dan GSC dengan BigQuery/Pandas
&lt;/h2>&lt;p>Data GSC saja hanya memberi tahu &amp;ldquo;peringkat pencarian dan CTR&amp;rdquo;. Untuk mengetahui &amp;ldquo;berapa lama pengguna yang sampai ke artikel tersebut benar-benar tinggal, dan apakah mereka mencapai konversi (misal: navigasi ke repositori GitHub, atau pendaftaran newsletter)&amp;rdquo;, kita perlu mengintegrasikannya (JOIN) dengan data dari &lt;strong>Google Analytics 4 (GA4)&lt;/strong>.&lt;/p>
&lt;p>Jika Anda menyimpan data ekspor GA4 dan data ekspor massal GSC di BigQuery, Anda dapat menggabungkan keduanya menggunakan query SQL seperti di bawah ini untuk mengekstrak &amp;ldquo;artikel dengan jumlah impresi tinggi dan peringkat pencarian yang lumayan, namun memiliki bounce rate (rasio pantulan) tinggi atau waktu engagement singkat&amp;rdquo;.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-sql" data-lang="sql">&lt;span class="line">&lt;span class="cl">&lt;span class="k">WITH&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">gsc_data&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">AS&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">SELECT&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">AS&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">page_path&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">SUM&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">impressions&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">AS&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">total_impressions&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">SUM&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">clicks&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">AS&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">total_clicks&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">AVG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">sum_top_position&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">AS&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">avg_position&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">FROM&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="o">`&lt;/span>&lt;span class="n">project&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">searchconsole&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">searchdata_url_impression&lt;/span>&lt;span class="o">`&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">WHERE&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">data_date&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">BETWEEN&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;2026-08-01&amp;#39;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">AND&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;2026-08-31&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">GROUP&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">BY&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">url&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">),&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="n">ga4_data&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">AS&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">SELECT&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">REGEXP_REPLACE&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">SELECT&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">value&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">string_value&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">FROM&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">UNNEST&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">event_params&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">WHERE&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">key&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;page_location&amp;#39;&lt;/span>&lt;span class="p">),&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="s1">&amp;#39;^https?://[^/]+&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">AS&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">page_path&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">COUNT&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">DISTINCT&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">user_pseudo_id&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">AS&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">users&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">AVG&lt;/span>&lt;span class="p">((&lt;/span>&lt;span class="k">SELECT&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">value&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">int_value&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">FROM&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">UNNEST&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">event_params&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">WHERE&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">key&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;engagement_time_msec&amp;#39;&lt;/span>&lt;span class="p">))&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">/&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mi">1000&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">AS&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">avg_engagement_sec&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">FROM&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="o">`&lt;/span>&lt;span class="n">project&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">analytics_123456789&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">events_&lt;/span>&lt;span class="o">*`&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">WHERE&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">event_name&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="s1">&amp;#39;page_view&amp;#39;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">GROUP&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">BY&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">page_path&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">SELECT&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">g&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">page_path&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">g&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">total_impressions&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">g&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">total_clicks&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">SAFE_DIVIDE&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">g&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">total_clicks&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">g&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">total_impressions&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">AS&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">ctr&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">g&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">avg_position&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">users&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">avg_engagement_sec&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">FROM&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">gsc_data&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">g&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">JOIN&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">ga4_data&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">ON&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">g&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">page_path&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">page_path&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">WHERE&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">g&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">total_impressions&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mi">1000&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">AND&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">g&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">avg_position&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">BETWEEN&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">AND&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mi">15&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">ORDER&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">BY&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">g&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">total_impressions&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">DESC&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Dengan menggunakan hasil ini, klasifikasikan target penulisan ulang dalam matriks seperti berikut:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>High Impression, Low CTR, High Engagement (Impresi Tinggi, CTR Rendah, Engagement Tinggi)&lt;/strong>:
Artikel yang membuat pembaca puas asalkan mereka mengekliknya di hasil pencarian. Prioritas utamanya hanya &lt;strong>merevisi judul dan deskripsi meta (meta description)&lt;/strong>.&lt;/li>
&lt;li>&lt;strong>High CTR, Low Engagement (CTR Tinggi, Engagement Rendah)&lt;/strong>:
Artikel yang diklik, tetapi pengguna pergi karena kontennya mengecewakan. Perlu ditulis ulang secara besar-besaran pada bagian isi, seperti &lt;strong>memperbaiki paragraf pengantar, memperbarui kode ke versi terbaru, dan meningkatkan kelengkapan informasi (menambahkan H2/H3)&lt;/strong>.&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="6-analisis-kesenjangan-konten-menggunakan-nlp-dan-tf-idf">6. Analisis Kesenjangan Konten Menggunakan NLP dan TF-IDF
&lt;/h2>&lt;p>Setelah berhasil mengidentifikasi artikel mana yang harus ditulis ulang, langkah selanjutnya adalah menganalisis &amp;ldquo;secara spesifik heading (H2/H3) atau kata kunci apa yang perlu ditambahkan&amp;rdquo;. Daripada hanya menebak-nebak, kita akan menggunakan &lt;strong>TF-IDF (Term Frequency-Inverse Document Frequency) dalam pemrosesan bahasa alami (NLP)&lt;/strong>.&lt;/p>
&lt;p>TF-IDF adalah metrik statistik untuk mengevaluasi seberapa penting sebuah kata dalam suatu dokumen.&lt;/p>
$$
TF\text{-}IDF(t, d) = tf(t, d) \times \log\left(\frac{N}{df(t)}\right)
$$&lt;p>Di mana:&lt;/p>
&lt;ul>
&lt;li>$tf(t, d)$ adalah frekuensi kemunculan kata $t$ pada dokumen $d$&lt;/li>
&lt;li>$N$ adalah jumlah total dokumen&lt;/li>
&lt;li>$df(t)$ adalah jumlah dokumen yang mengandung kata $t$&lt;/li>
&lt;/ul>
&lt;p>&lt;strong>Pendekatan:&lt;/strong>&lt;/p>
&lt;ol>
&lt;li>Mengambil data teks dari 10 artikel teratas (situs kompetitor) untuk kata kunci target dengan cara web scraping atau metode lainnya.&lt;/li>
&lt;li>Menyiapkan data teks artikel dari situs kita sendiri.&lt;/li>
&lt;li>Menggunakan &lt;code>TfidfVectorizer&lt;/code> dari &lt;code>scikit-learn&lt;/code> pada Python untuk mengekstrak kata kunci (kata fitur) yang muncul dengan skor tinggi secara umum di artikel kompetitor, tetapi tidak ada, atau skornya jauh lebih rendah, pada artikel di situs kita.&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">sklearn.feature_extraction.text&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">TfidfVectorizer&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">pandas&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">pd&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">numpy&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">np&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># documents = [teks situs sendiri, teks kompetitor 1, teks kompetitor 2, ...]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Di sini kita asumsikan menggunakan daftar teks bahasa Jepang yang sudah dipisah per kata menggunakan morphological analysis (seperti MeCab)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">extract_missing_keywords&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">documents&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">vectorizer&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">TfidfVectorizer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">max_df&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mf">0.9&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">min_df&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">tfidf_matrix&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">vectorizer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">fit_transform&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">documents&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">feature_names&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">vectorizer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_feature_names_out&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Menghitung skor TF-IDF rata-rata untuk artikel kompetitor (indeks 1 dan seterusnya)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">competitor_mean_tfidf&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">np&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">mean&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tfidf_matrix&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">:]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">toarray&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">axis&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Mengambil skor TF-IDF artikel dari situs kita (indeks 0)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">my_article_tfidf&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">tfidf_matrix&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">toarray&lt;/span>&lt;span class="p">()[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Menghitung kesenjangan kata yang penting bagi kompetitor, tetapi tidak ada (atau sedikit) di situs kita&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">gap_scores&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">competitor_mean_tfidf&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">my_article_tfidf&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Mengekstrak kata-kata teratas dengan kesenjangan yang besar&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">df_gap&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pd&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">DataFrame&lt;/span>&lt;span class="p">({&lt;/span>&lt;span class="s1">&amp;#39;keyword&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">feature_names&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;gap_score&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">gap_scores&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">df_gap&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">df_gap&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sort_values&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">by&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;gap_score&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ascending&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">False&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">df_gap&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">head&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">20&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># Contoh: missing_keywords = extract_missing_keywords(processed_docs)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># print(missing_keywords)&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Melalui analisis ini, Anda bisa secara kuantitatif menemukan &lt;strong>topik yang hilang (kesenjangan konten)&lt;/strong>. Misalnya, &amp;ldquo;Ternyata artikel peringkat atas membahas tentang &amp;lsquo;Cara deploy ke container Docker&amp;rsquo; dan &amp;lsquo;Membangun pipeline CI/CD&amp;rsquo;, padahal artikel saya tidak menyinggung hal itu sama sekali&amp;rdquo;.&lt;/p>
&lt;p>Kata-kata kunci penting yang ditemukan sebaiknya tidak sekadar disisipkan sembarangan di dalam teks. Anda harus menambahkannya sebagai bagian bermakna melalui &lt;strong>heading (tag Heading H2 atau H3)&lt;/strong>, lalu menulis penjelasan teknis yang mendetail dan menyertakan snippet kode pada heading tersebut. Hal ini dapat secara drastis meningkatkan penilaian dari Google.&lt;/p>
&lt;hr>
&lt;h2 id="7-pipeline-data-dan-siklus-peningkatan-berkelanjutan">7. Pipeline Data dan Siklus Peningkatan Berkelanjutan
&lt;/h2>&lt;p>Proses yang dijelaskan di atas bukan sekadar untuk dilakukan sekali lalu selesai; mengubahnya menjadi pipeline yang berjalan secara berkelanjutan adalah kunci keberhasilan SEO. Di bawah ini adalah arsitektur keseluruhan dan alur operasional yang direpresentasikan menggunakan diagram alur (flowchart) Mermaid.&lt;/p>
&lt;pre class="mermaid">
flowchart TD
A[&amp;#34;Data API GSC (Impresi, Klik, Peringkat)&amp;#34;] --&amp;gt; C[&amp;#34;BigQuery / Data Warehouse&amp;#34;]
B[&amp;#34;Data Ekspor GA4 (Tayangan Halaman, Waktu Engagement)&amp;#34;] --&amp;gt; C
C --&amp;gt; D[&amp;#34;Penggabungan &amp;amp; Analisis Data dengan Python / Pandas&amp;#34;]
D --&amp;gt; E[&amp;#34;Identifikasi Artikel Impresi Tinggi / CTR Rendah&amp;#34;]
E --&amp;gt; F[&amp;#34;Scraping Kompetitor NLP &amp;amp; Ekstraksi Kata Kunci TF-IDF&amp;#34;]
F --&amp;gt; G[&amp;#34;Optimalkan Tag H2/H3 &amp;amp; Tulis Ulang Konten&amp;#34;]
G --&amp;gt; H[&amp;#34;Publikasikan Artikel yang Diperbarui&amp;#34;]
H --&amp;gt; I[&amp;#34;Pantau Perubahan CTR (Yang Diharapkan vs Aktual)&amp;#34;]
I --&amp;gt; |&amp;#34;Siklus Umpan Balik&amp;#34;| A
&lt;/pre>
&lt;p>Dengan mensistemasikan serangkaian langkah ini—mulai dari pengumpulan data dari GSC dan GA4, pemilihan target melalui analisis, optimalisasi konten dengan NLP, hingga pemantauan hasilnya—blog atau media Anda akan menjadi aset yang terus berkembang secara otomatis.&lt;/p>
&lt;hr>
&lt;h2 id="8-kesimpulan-dan-prospek-di-masa-mendatang">8. Kesimpulan dan Prospek di Masa Mendatang
&lt;/h2>&lt;p>Menulis ulang artikel teknis dengan memanfaatkan Google Search Console bukanlah sekadar memperbaiki kalimat. Itu adalah sebuah proses rekayasa tingkat lanjut, di mana kita memanfaatkan data dan model matematis untuk menghadirkan solusi optimal dalam menghadapi &amp;ldquo;kotak hitam&amp;rdquo; bernama algoritma mesin pencari.&lt;/p>
&lt;p>Berikut ringkasan metode yang dibahas dalam artikel ini:&lt;/p>
&lt;ol>
&lt;li>Menghitung &lt;strong>kesenjangan antara CTR yang diharapkan dan CTR aktual&lt;/strong> untuk mengidentifikasi artikel dengan dampak perbaikan yang besar.&lt;/li>
&lt;li>Menggunakan &lt;strong>API GSC dan Python&lt;/strong> untuk mengekstrak data performa secara otomatis.&lt;/li>
&lt;li>Menggabungkan data engagement GA4 pada &lt;strong>BigQuery&lt;/strong> dan memperbaiki isi artikel yang memiliki bounce rate tinggi.&lt;/li>
&lt;li>Menemukan kesenjangan konten dengan kompetitor melalui &lt;strong>analisis NLP menggunakan TF-IDF&lt;/strong> dan mengoptimalkan heading (H2/H3).&lt;/li>
&lt;/ol>
&lt;p>Tren teknologi terus berubah. Untuk secara akurat merespons error dan masalah yang sedang dihadapi pembaca, pertimbangkanlah untuk menjadikan strategi penulisan ulang berbasis data ini sebagai bagian dari operasional harian Anda.&lt;/p></description></item></channel></rss>