Kenapa Kamu Butuh Custom Notifikasi di Hugo? #
Saat kamu melakukan migrasi blog — misalnya dari Blogger, WordPress, atau platform lain ke Hugo — ada satu hal yang sering diabaikan: memberitahu pembaca.
Pembaca lama mungkin masih mengakses URL lama. SEO-mu sedang dalam transisi. Dan tanpa notifikasi, mereka tidak tahu apa yang sedang terjadi.
Hugo tidak menyediakan komponen notifikasi bawaan. Tapi dengan sistem partial template-nya yang fleksibel, kamu bisa membangun sendiri — dan hasilnya bersih, ringan, serta mudah dikustomisasi.
Apa yang Akan Kita Bangun? #

Notifikasi yang akan kita buat memiliki fitur:
- ✅ Banner warning berwarna kuning dengan ikon peringatan
- ✅ Tombol dismiss — sekali ditutup, tidak muncul lagi (pakai
localStorage) - ✅ Animasi fade-in saat halaman dimuat
- ✅ Dark mode support penuh via Tailwind CSS
- ✅ Dukungan multilanguage via Hugo i18n (opsional)
- ✅ Kompatibel dengan tema Blowfish dan tema Hugo lainnya
Struktur File yang Dibutuhkan #
layouts/
partials/
notification.html ← file utama partial notifikasi
i18n/
en.yaml ← teks notifikasi bahasa Inggris
id.yaml ← teks notifikasi bahasa IndonesiaLangkah 1: Buat File Partial Notifikasi #
Buat file baru di layouts/partials/notification.html.
Catatan: Folder
layouts/ada di root project Hugo-mu, bukan di dalam folder tema. Ini penting — Hugo memprioritaskan file dilayouts/project di atas file di dalam tema, sehingga kamu tidak perlu mengubah file tema secara langsung.
Versi dengan Multilanguage (Direkomendasikan) #
<!-- layouts/partials/notification.html -->
<div class="flex pb-2" id="migration-notice-wrapper">
<div
id="migration-notice"
class="bg-yellow-100 dark:bg-yellow-900 border border-yellow-300 dark:border-yellow-700 text-yellow-800 dark:text-yellow-200 p-4 rounded-lg shadow-xl flex items-start space-x-3 transition-all duration-300 ease-in-out transform max-w-xl"
role="alert"
style="display: none; opacity: 0; margin: 0 auto;"
>
<!-- Icon Peringatan -->
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 flex-shrink-0 mt-0.5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.3 16c-.77 1.333.192 3 1.732 3z" />
</svg>
<!-- Konten Teks -->
<div class="flex-grow">
<p class="font-bold text-sm">{{ i18n "migration_notice" | safeHTML }}</p>
<p class="text-sm">{{ i18n "migration_notice_details" | safeHTML }}</p>
</div>
<!-- Tombol Tutup -->
<button
id="dismiss-notice"
type="button"
class="text-yellow-800 dark:text-yellow-200 hover:text-yellow-900 dark:hover:text-yellow-100 transition duration-150 ease-in-out p-1 -m-1 rounded-full focus:outline-none focus:ring-2 focus:ring-yellow-500"
aria-label="Tutup pemberitahuan"
>
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>
</button>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const notice = document.getElementById('migration-notice');
const dismissBtn = document.getElementById('dismiss-notice');
// Cek apakah user sudah pernah menutup notifikasi
const isDismissed = localStorage.getItem('migrationNoticeDismissed');
if (!isDismissed) {
// Tampilkan dengan animasi fade-in setelah 500ms
setTimeout(() => {
notice.style.display = 'flex';
setTimeout(() => {
notice.style.opacity = '1';
}, 10);
}, 500);
}
// Handle klik tombol dismiss
dismissBtn.addEventListener('click', () => {
notice.style.opacity = '0';
setTimeout(() => {
notice.style.display = 'none';
// Simpan status dismiss ke localStorage
localStorage.setItem('migrationNoticeDismissed', 'true');
}, 300);
});
});
</script>Versi Tanpa Multilanguage (Simple) #
Jika blog kamu hanya satu bahasa, gunakan versi ini — lebih simpel dan tidak perlu file i18n:
<!-- layouts/partials/notification.html -->
<div class="flex pb-2" id="migration-notice-wrapper">
<div
id="migration-notice"
class="bg-yellow-100 dark:bg-yellow-900 border border-yellow-300 dark:border-yellow-700 text-yellow-800 dark:text-yellow-200 p-4 rounded-lg shadow-xl flex items-start space-x-3 transition-all duration-300 ease-in-out transform max-w-xl"
role="alert"
style="display: none; opacity: 0; margin: 0 auto;"
>
<!-- Icon Peringatan -->
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 flex-shrink-0 mt-0.5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.3 16c-.77 1.333.192 3 1.732 3z" />
</svg>
<!-- Konten Teks — ganti sesuai kebutuhanmu -->
<div class="flex-grow">
<p class="font-bold text-sm">Situs sedang dalam migrasi.</p>
<p class="text-sm">Beberapa halaman mungkin belum tersedia. Terima kasih atas pengertianmu.</p>
</div>
<!-- Tombol Tutup -->
<button
id="dismiss-notice"
type="button"
class="text-yellow-800 dark:text-yellow-200 hover:text-yellow-900 dark:hover:text-yellow-100 transition duration-150 ease-in-out p-1 -m-1 rounded-full focus:outline-none focus:ring-2 focus:ring-yellow-500"
aria-label="Tutup pemberitahuan"
>
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd" />
</svg>
</button>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const notice = document.getElementById('migration-notice');
const dismissBtn = document.getElementById('dismiss-notice');
const isDismissed = localStorage.getItem('migrationNoticeDismissed');
if (!isDismissed) {
setTimeout(() => {
notice.style.display = 'flex';
setTimeout(() => { notice.style.opacity = '1'; }, 10);
}, 500);
}
dismissBtn.addEventListener('click', () => {
notice.style.opacity = '0';
setTimeout(() => {
notice.style.display = 'none';
localStorage.setItem('migrationNoticeDismissed', 'true');
}, 300);
});
});
</script>Langkah 2: Sisipkan Partial ke baseof.html (Tema Blowfish) #
Jika Kamu Belum Punya baseof.html di layouts/ #
Tema Blowfish menyimpan baseof.html di dalam folder tema (themes/blowfish/layouts/_default/baseof.html). Kamu tidak boleh mengedit file di dalam folder tema langsung — perubahan akan hilang saat tema diupdate.
Cara yang benar:
-
Copy file dari tema ke project-mu:
cp themes/blowfish/layouts/_default/baseof.html layouts/_default/baseof.html -
Buat folder jika belum ada:
mkdir -p layouts/_default
Hugo akan otomatis menggunakan versi di layouts/ milikmu.
Tambahkan Partial ke baseof.html #
Cari bagian ini di layouts/_default/baseof.html:
{{ $header := print "header/" site.Params.header.layout ".html" }}
{{ if templates.Exists ( printf "partials/%s" $header ) }}
{{ partial $header . }}
{{ else }}
{{ partial "header/basic.html" . }}
{{ end }}Tambahkan satu baris di bawahnya:
{{ $header := print "header/" site.Params.header.layout ".html" }}
{{ if templates.Exists ( printf "partials/%s" $header ) }}
{{ partial $header . }}
{{ else }}
{{ partial "header/basic.html" . }}
{{ end }}
{{/* migration-notice */}}
{{ partial "notification.html" . }}Untuk Tema Hugo Lainnya #
Temukan baseof.html di tema yang kamu gunakan, lalu sisipkan partial tepat setelah tag <header> atau blok partial header selesai dirender. Prinsipnya sama: notifikasi ditampilkan di bawah header, sebelum konten utama.
Contoh umum untuk tema lain:
{{ partial "header.html" . }}
{{/* Notifikasi kustom */}}
{{ partial "notification.html" . }}
<main>
{{ block "main" . }}{{ end }}
</main>Langkah 3: Setup Multilanguage (Opsional) #
Jika kamu menggunakan Hugo dengan multiple language, tambahkan teks notifikasi ke file i18n.
i18n/en.yaml
#
- id: "migration_notice"
translation: "Site is under migration from Blogger to Hugo."
- id: "migration_notice_details"
translation: "Some pages may be temporarily unavailable. Thank you for your patience."i18n/id.yaml
#
- id: "migration_notice"
translation: "Situs sedang dalam migrasi dari Blogger ke Hugo."
- id: "migration_notice_details"
translation: "Beberapa halaman mungkin belum tersedia sementara. Terima kasih atas pengertianmu."Hugo akan otomatis memilih teks yang sesuai berdasarkan bahasa aktif pengunjung.
Penjelasan Fitur: Bagaimana Ini Bekerja? #
1. Dismissible dengan localStorage #
const isDismissed = localStorage.getItem('migrationNoticeDismissed');Saat user menutup notifikasi, status disimpan ke localStorage browser mereka. Saat halaman di-refresh atau user berpindah halaman, notifikasi tidak muncul lagi — karena Hugo memeriksa localStorage sebelum menampilkannya.
Ini penting untuk UX: kamu tidak ingin notifikasi muncul terus-terusan dan mengganggu pembaca.
2. Animasi Fade-in #
setTimeout(() => {
notice.style.display = 'flex';
setTimeout(() => {
notice.style.opacity = '1';
}, 10);
}, 500);Delay 500ms sebelum muncul memberi waktu halaman untuk selesai dimuat, sehingga notifikasi terasa mulus — bukan langsung “pop” yang mengagetkan.
3. Dark Mode Support #
Kelas Tailwind seperti dark:bg-yellow-900 dan dark:text-yellow-200 otomatis aktif saat tema Blowfish beralih ke dark mode. Tidak perlu JavaScript tambahan untuk ini.
4. Aksesibilitas #
role="alert"memberi tahu screen reader bahwa ini adalah notifikasi pentingaria-label="Tutup pemberitahuan"pada tombol X memastikan pengguna assistive technology bisa menutup notifikasi- Focus ring (
focus:ring-2) pada tombol dismiss untuk navigasi keyboard
Tips Kustomisasi #
Ganti warna banner: Ubah kelas yellow menjadi blue, red, green, atau warna lain sesuai konteksmu:
<!-- Info (biru) -->
class="bg-blue-100 dark:bg-blue-900 border border-blue-300 ..."
<!-- Error/Penting (merah) -->
class="bg-red-100 dark:bg-red-900 border border-red-300 ..."
<!-- Sukses (hijau) -->
class="bg-green-100 dark:bg-green-900 border border-green-300 ..."Reset notifikasi untuk testing: Buka browser console dan jalankan:
localStorage.removeItem('migrationNoticeDismissed');Tampilkan notifikasi hanya di halaman tertentu: Tambahkan kondisi Hugo di partial:
{{ if eq .RelPermalink "/" }}
<!-- notifikasi hanya tampil di homepage -->
{{ end }}Kesimpulan #
Custom notifikasi di Hugo tidak butuh plugin, tidak butuh JavaScript framework berat, dan tidak butuh mengubah file tema secara langsung.
Dengan satu file partial, beberapa baris JavaScript vanilla, dan opsional file i18n — kamu sudah punya sistem notifikasi yang:
- Ramah pengguna (dismissible, animasi halus)
- Aksesibel (ARIA attributes)
- Mendukung dark mode
- Mudah dikustomisasi untuk use case lain (maintenance, promo, pengumuman)
Langkah selanjutnya: setelah migrasi selesai, cukup hapus {{ partial "notification.html" . }} dari baseof.html — bersih tanpa bekas.
Ada pertanyaan atau kendala saat implementasi? Tulis di kolom komentar.