Site Search untuk Personal Website — Membantu Pembaca Menemukan Halaman yang Mereka Ingat

Site Search untuk Personal Website — Membantu Pembaca Menemukan Halaman yang Mereka Ingat

Sebagian pembaca datang dari search engine, membaca satu halaman, lalu pergi. Sebagian lain mengingat sebuah kalimat beberapa bulan kemudian dan kembali, tetapi tidak lagi ingat judul atau URL-nya. Personal website mungkin terlihat kecil, tetapi setelah berisi catatan, tutorial, dan esai selama bertahun-tahun, mencari satu halaman yang samar-samar diingat bisa terasa seperti mencari obeng tertentu di laci tanpa label.

Site search memberi pembaca jalan langsung untuk masuk kembali ke arsip. Fitur ini tidak harus meniru Google atau menambahkan hosted service yang besar. Untuk banyak personal website, search index kecil yang mudah dipahami sudah cukup. Panduan ini membahas pilihan pendekatan, membangun implementasi client-side, dan memperhatikan detail yang mengubah sebuah kotak teks menjadi bagian website yang benar-benar berguna.

Search adalah navigasi untuk ingatan yang tidak sempurna

Menu bekerja saat pengunjung memahami kategori yang kita buat. Halaman arsip berguna saat mereka mengingat tanggal. Tag membantu saat penulis dan pembaca memakai kosakata yang sama. Search menangani situasi yang lebih berantakan: seseorang ingat “artikel tentang link lama itu,” tetapi lupa bahwa judulnya memuat istilah “link rot.” Pengunjung dapat menggambarkan tujuan dengan kata-katanya sendiri.

Karena itu, search sebaiknya melengkapi navigasi, bukan menggantikannya. Menu yang jelas tetap memperkenalkan isi website kepada pengunjung baru, sementara search membantu pembaca lama mengambil kembali sesuatu yang spesifik. Bayangkan sebuah dapur: label pada lemari memberi struktur, tetapi bisa bertanya di mana filter kopi disimpan tetap berguna ketika struktur itu belum ada di kepala kita.

Pilih pendekatan yang sesuai dengan ukuran arsip

Ada tiga pendekatan umum. Server-side search melakukan query ke database setiap kali seseorang mengirim kata pencarian. Pendekatan ini mudah berkembang dan mampu memberi ranking akurat atas seluruh konten, tetapi memerlukan backend code, input validation, rate limiting, dan pemeliharaan. Hosted service dapat menawarkan typo tolerance dan ranking canggih, tetapi menambah ketergantungan eksternal serta mungkin mengirim query pengunjung kepada perusahaan lain.

Client-side search mengunduh index ringkas lalu memfilternya di browser. Ini cocok untuk personal website statis atau berukuran sedang: tidak memerlukan search server, query tetap berada di perangkat pembaca, dan fitur dapat terus bekerja dari salinan cache. Batas utamanya adalah ukuran index. Jika JSON membesar hingga beberapa megabyte atau memuat ribuan dokumen panjang, mengunduh dan memprosesnya pada setiap kunjungan menjadi pemborosan.

Mulailah dari title, summary, URL, dan mungkin tags. Index kecil ini sering memberi hasil lebih baik daripada mengindeks setiap kata karena menekankan pokok bahasan setiap halaman. Full-text search dapat ditambahkan nanti ketika penggunaan nyata menunjukkan metadata belum cukup.

Buat search index yang kecil dan eksplisit

Index dapat dibuat saat proses build atau publishing website berjalan. Jangan memeliharanya manual jika artikel sudah tersimpan di CMS; salinan manual pada akhirnya akan berbeda. Export hanya halaman public berstatus published, hapus HTML dari summary, dan gunakan canonical URL. File sederhana dapat berbentuk seperti ini:

[
  {
    "title": "Preventing Link Rot on a Personal Website",
    "url": "/preventing-link-rot-personal-website/",
    "summary": "Practical ways to preserve references and repair old links.",
    "tags": ["web", "maintenance"]
  },
  {
    "title": "A Useful 404 Page for a Personal Website",
    "url": "/useful-404-page-personal-website/",
    "summary": "Turn a dead end into a helpful route back into the site.",
    "tags": ["web", "navigation"]
  }
]

Biarkan schema tetap sederhana. Field yang stabil lebih mudah dibuat, di-cache, dan dikonsumsi daripada struktur cerdik yang dioptimalkan terlalu dini. Pastikan juga draft private dan metadata sensitif tidak ikut. Search index adalah dokumen public, meskipun tidak ada halaman terlihat yang menaut langsung kepadanya.

Buat search form yang accessible

Interface harus tetap masuk akal sebelum JavaScript berjalan. Gunakan <form> sungguhan, label yang terlihat, dan search input. Jika tersedia server endpoint, form dapat submit ke sana sebagai fallback; jika tidak, jelaskan dengan baik bahwa interactive search memerlukan JavaScript, bukan menampilkan tombol yang diam-diam tidak bekerja.

<form id="site-search" role="search">
  <label for="search-query">Search this site</label>
  <input id="search-query" name="q" type="search"
         autocomplete="off" minlength="2">
  <button type="submit">Search</button>
</form>
<p id="search-status" aria-live="polite"></p>
<ol id="search-results"></ol>

Label tidak dapat digantikan placeholder text: placeholder menghilang saat pengguna mengetik dan sering memiliki contrast rendah. Live status mengumumkan jumlah hasil kepada pengguna screen reader tanpa memindahkan keyboard focus secara tiba-tiba. Ordered list memberi hasil sebuah struktur yang bermakna.

Filter dan beri ranking tanpa membuatnya misterius

Untuk arsip kecil, ranking yang transparan lebih baik daripada algoritma rumit. Normalkan huruf, pecah query menjadi beberapa istilah, wajibkan setiap istilah muncul di suatu field, lalu beri bobot title lebih besar daripada summary atau tag. Implementasi berikut mengambil index hanya setelah pencarian valid dan menampilkan hasil tanpa menyisipkan teks index sebagai HTML:

const form = document.querySelector('#site-search');
const input = document.querySelector('#search-query');
const status = document.querySelector('#search-status');
const results = document.querySelector('#search-results');

form.addEventListener('submit', async (event) => {
  event.preventDefault();
  const terms = input.value.toLowerCase().trim().split(/\s+/).filter(Boolean);
  if (terms.join('').length < 2) return;

  const response = await fetch('/search-index.json');
  if (!response.ok) throw new Error('Search index unavailable');
  const pages = await response.json();

  const matches = pages.map((page) => {
    const title = page.title.toLowerCase();
    const details = `${page.summary} ${page.tags.join(' ')}`.toLowerCase();
    if (!terms.every((term) => title.includes(term) || details.includes(term))) return null;
    const score = terms.reduce((sum, term) => sum +
      (title.includes(term) ? 10 : 0) + (details.includes(term) ? 1 : 0), 0);
    return { page, score };
  }).filter(Boolean).sort((a, b) => b.score - a.score).slice(0, 20);

  results.replaceChildren(...matches.map(({ page }) => {
    const item = document.createElement('li');
    const link = document.createElement('a');
    link.href = page.url;
    link.textContent = page.title;
    const summary = document.createElement('p');
    summary.textContent = page.summary;
    item.append(link, summary);
    return item;
  }));
  status.textContent = `${matches.length} result(s) found`;
});

Penggunaan textContent penting. Walaupun index dibuat dari CMS milik kita sendiri, memperlakukan string sebagai teks mencegah fragmen HTML yang tidak sengaja berubah menjadi markup. Tambahkan try...catch dalam production agar kegagalan network menjadi pesan yang mudah dibaca, bukan unhandled error.

Buat empty state yang benar-benar membantu

“No results” memang benar secara teknis, tetapi tidak terlalu membantu. Sarankan pengguna menghapus satu kata, memeriksa ejaan, atau membuka arsip. Pertahankan query pada URL melalui ?q=... agar hasil dapat di-bookmark dan tombol Back bekerja secara alami. Saat ada hasil, tampilkan jumlah serta context yang cukup untuk membedakan halaman dengan title mirip.

Hindari menyorot kecocokan dengan menyusun raw HTML. Jika highlighting penting, pecah teks menjadi node dan bungkus segmen yang cocok dengan aman. Hindari pula memulai request pada setiap keystroke kecuali input memakai debounce. Desain berbasis submit terasa lebih tenang, mengurangi pekerjaan di ponsel bertenaga rendah, dan tetap mudah dipahami.

Performance, privacy, dan konten multilingual

Sajikan index dalam keadaan compressed dan dengan caching headers yang masuk akal. Beri revision baru atau perbarui validator ketika konten berubah. Muat file saat diperlukan alih-alih menambahkannya ke initial payload setiap halaman. Ukur compressed transfer size; angka itu lebih berguna daripada menebak apakah sebuah index termasuk “kecil.”

Client-side search menjaga frasa pencarian tetap lokal, tetapi server log biasa mungkin masih mencatat query jika diletakkan pada URL. Tentukan apakah itu dapat diterima, dan jangan mengirim search terms ke analytics secara default. Search box kadang berisi potongan teks yang ternyata sangat personal.

Untuk website multilingual, terbitkan satu index per locale, misalnya /id/search-index.json, atau sertakan locale field lalu filter sebelum ranking. Jangan mencampur seluruh bahasa begitu saja. Pembaca yang mencari dalam bahasa Indonesia tidak seharusnya melihat hasil berguna tenggelam di bawah halaman English dan German, sementara tokenization khusus bahasa kelak mungkin memerlukan aturan berbeda.

Uji jalur yang benar-benar dipakai pembaca

Buat daftar pengujian singkat dari kosakata artikel nyata. Coba exact title, frasa yang hanya ada pada summary, kapitalisasi berbeda, spasi berlebih, salah eja, query kosong, dan istilah tanpa hasil. Uji operasi keyboard-only serta mobile viewport yang sempit. Putuskan network setelah halaman dimuat untuk melihat apakah pesan kegagalannya dapat dipahami.

Kualitas search bukan sekadar jumlah kecocokan. Halaman yang diharapkan harus muncul dekat posisi teratas, halaman stale atau private tidak boleh pernah muncul, dan artikel baru harus segera masuk ke index. Periksa URL dalam index secara berkala untuk redirect dan respons 404; jangan sampai search menjadi peta lain yang menunjuk ke jalan tertutup.

Fitur search yang kecil boleh tetap kecil

Search untuk personal website yang berguna tidak membutuhkan cluster, ranking model yang opaque, atau surveillance. Ia membutuhkan index bersih, form accessible, pencocokan yang dapat diprediksi, empty state yang membantu, dan publishing process yang selalu memperbaruinya. Mulailah dengan metadata dan client-side filtering, lalu tambahkan kompleksitas hanya ketika arsip dan pembaca menunjukkan kebutuhan nyata.

Jika kamu mengelola personal website, cobalah mencari satu artikel yang hanya samar-samar kamu ingat, bukan artikel yang judulnya sudah kamu hafal. Eksperimen kecil itu menunjukkan apakah navigasi kita mendukung cara ingatan manusia bekerja. Ceritakan di kolom komentar apa yang berhasil, apa yang gagal, atau bagaimana kamu membuat search sendiri; mungkin pemilik website lain sedang mencari potongan yang sama.