Skip to content

Berita (News)

Ringkasan

Modul Berita mengelola artikel, publikasi, dan pengumuman yang ditampilkan di laman publik. Ini adalah CMS lengkap: kategori artikel, konten dwibahasa (terlokalisasi), penyunting teks kaya, tag SEO, gambar unggulan (thumbnail), pratinjau perangkat langsung, analitik pembaca, dan mesin rekomendasi yang dipersonalisasi.

Modul ini memiliki dua sisi:

  • Panel admin — cluster Filament di /portal/news (label navigasi News, grup Master).
  • Situs publik — laman /articles beserta endpoint analitik/API.

Entitas Utama

EntitasDeskripsi
ArticleKonten berita — judul/konten/ringkasan terlokalisasi, slug, tag, kategori, sekolah, penulis, thumbnail, SEO meta, tanggal terbit, status aktif
ArticleCategoryPengelompokan kategori artikel — nama/deskripsi terlokalisasi, slug, status aktif
ArticleAnalyticAnalitik sesi baca per artikel — fingerprint, durasi, kedalaman scroll, selesai/tidak, perangkat, lokasi geografis

Panel Admin (/portal/news)

Cluster ini berisi tiga area:

AreaURLFungsi
Articles/portal/news/articlesKelola artikel (daftar, buat, ubah, lihat)
Article Categories/portal/news/article-categoriesKelola kategori
Popular Articles/portal/news/popular-articles-pageDasbor analitik pembaca

1. Articles — Halaman Daftar

Kolom

KolomCatatan
Name (judul)Dapat dicari, terlokalisasi
SchoolMenampilkan nama sekolah atau placeholder General
CategoryNama kategori atau -
SlugDapat dicari
AuthorDapat dicari, - jika kosong
StatusBadge — Active (hijau) / Inactive (abu-abu)

Filter

  • Status — filter ternary: Aktif / Nonaktif
  • School — pilihan dengan opsi General
  • Category — pilihan dari kategori yang ada
  • Published Date — rentang tanggal (dari / sampai)
  • Created Date — rentang tanggal (dari / sampai)

Pencarian global menggunakan pencarian teks penuh (Meilisearch) — mencocokkan judul, konten, dan ringkasan dalam kedua bahasa, plus penulis dan tag, dengan peringkat relevansi.

Aksi per baris: Lihat, Ubah. Aksi massal: Hapus (baris terpilih).

2. Articles — Formulir Buat / Ubah

Formulir terbagi menjadi kolom Umum / Konten terlokalisasi (lebar 3) dan sidebar Thumbnail / SEO (lebar 1).

Bagian Umum

KolomWajibCatatan
School (opsional)TidakDefault General — tanpa sekolah
CategoryTidakPilihan dengan + buat opsi (buat inline: slug + nama/deskripsi terlokalisasi)
SlugYaHarus unik (divalidasi) — mis. panduan-pendaftaran
AuthorTidakTeks bebas, mis. Admin
Published AtTidakPilih tanggal, tanggal minimum = hari ini (penjadwalan)
TagsTidakInput tag dipisah koma/enter

Konten terlokalisasi (tab per bahasa, EN/ID)

KolomWajib (bahasa dasar)Catatan
Name (judul)YaTeks biasa
ExcerptYaTextarea, dirender sebagai pratinjau HTML di halaman detail publik
ContentYaPenyunting teks kaya headless (heading, kutipan, media, menu cepat /)

Tab lokalisasi menyediakan tombol Auto-translate yang menyalin konten bahasa dasar ke bahasa saat ini.

Bagian Thumbnail

KolomCatatan
Upload ImageUnggah gambar (disk publik, folder articles/, editor gambar), disimpan sebagai Asset, pratinjau via ImageKit
Alt textMaks 150 karakter, untuk aksesibilitas

Bagian SEO

  • Meta tags repeater (modal) — daftar pasangan {name, content}.
  • name adalah pilihan kunci SEO yang telah ditentukan (mis. description, keywords, og:title, og:image, twitter:...) dengan opsi + buat untuk nama kustom; setiap nama hanya boleh dipakai sekali (divalidasi UniqueSeoName).
  • content teks bebas, maks 255 karakter.

3. Articles — Halaman Lihat

Menampilkan:

  • Info umum — slug, kategori, sekolah, penulis, badge status, tag
  • Nilai terlokalisasi — judul, ringkasan (dirender sebagai prosa/pratinjau HTML), konten (dirender dari penyunting teks kaya)
  • Kartu Pratinjau Langsung — iframe halaman artikel publik dengan pemilih perangkat Desktop / Tablet / Mobile, mockup berbingkai, skala responsif, dan status memuat.

4. Article Categories — Halaman Kelola

Formulir

KolomWajibCatatan
SlugYaUnik, maks 100 karakter
ActiveTidakSwitcher, default aktif
Name (terlokalisasi)YaMaks 255 karakter
Description (terlokalisasi)TidakTextarea

Kolom tabel: Name, Slug (badge, dapat dicari/diurutkan), Articles (jumlah per kategori, dapat diurutkan), Active (ikon boolean), Created Date (dapat diurutkan, tersembunyi secara default, dapat diaktifkan).

Aksi per baris: Ubah, Hapus. Urutan default: berdasarkan slug.

Hanya kategori Aktif yang muncul di situs publik.

  • Kartu statistik (polling tiap 60 dtk): Total Kategori Artikel, Artikel Belum Dipublikasikan (published_at null atau di masa depan), Artikel Sudah Dipublikasikan (published_at <= now).
  • Geografi Pembaca — grafik treemap pembacaan per negara (dari geo-IP; grup "Tidak Diketahui").
  • Tabel Artikel Populer — per artikel: Dibaca, Pembaca Unik, Total Waktu (dibaca manusia: 45s / 3m 20s / 1h 5m), Selesai. Urutan default: total waktu menurun. Pagination 5 / 10 / 25. State kosong saat belum ada data analitik.

Alur Publikasi

Diagram berikut menunjukkan bagaimana sebuah artikel bergerak dari formulir admin ke situs publik:

Aturan kunci

  • Artikel terlihat publik hanya jika is_active = true dan published_at terisi dan tidak di masa depan.
  • Menetapkan published_at masa depan menjadwalkan artikel — tetap tersembunyi (belum terbit) hingga tanggal tersebut.
  • Setiap penyimpanan membatalkan cache rekomendasi/analitik sehingga perubahan langsung terlihat.

Situs Publik

Rute

RuteHalamanDeskripsi
GET /articlesArticles/IndexJelajahi + filter + cari artikel
GET /articles/{slug}Articles/ShowDetail artikel dengan rekomendasi
GET /articles/{slug}/iframeArticles/IFrameShowTampilan bersih untuk embed (tanpa kerangka layout), dipakai kartu pratinjau admin

/articles — Daftar

  • Kotak pencarian — pencarian teks penuh atas judul/konten/ringkasan (kedua bahasa), penulis, tag.
  • Sidebar filter — Kategori (multi-pilih), Penulis, Tahun; Urutkan: Terbaru / Terlama / A–Z / Z–A.
  • Jumlah hasil + Pagination, state kosong dengan tombol reset, bilah pencarian lengket dengan scroll-balik halus saat filter berubah.
  • Daftar sisi server dibatasi 100 artikel aktif terbaru; filter/urutkan/pagination terjadi di sisi klien atas set tersebut. Artikel yang lebih lama tetap bisa diakses via URL langsung.
  • Kategori dimuat lambat via Inertia::defer (skeleton hingga siap).

/articles/{slug} — Detail

Hanya artikel aktif yang ditampilkan; selain itu mengembalikan 404.

  • Header: badge kategori, judul, meta (penulis / tanggal terbit / waktu baca — disembunyikan bila kosong), tautan kembali.
  • Excerpt dirender sebagai pratinjau HTML di atas konten.
  • Badan: konten teks kaya dengan penanda selesai-baca.
  • Lucky Me interstitial — scroll memicu artikel acak lainnya.
  • Sidebar: artikel yang direkomendasikan (dipersonalisasi), artikel terkait per penulis.
  • Bagian seluler: rekomendasi + artikel penulis yang sama.
  • SEO: tag meta kustom dari repeater admin dirender sebagai <meta> (og:* memakai atribut property, lainnya name); fallback wajar (description, og:title, og:description, og:type, og:image, article:author, article:section, article:published_time, og:url).

/articles/{slug}/iframe

Tampilan artikel minimal untuk embed (pratinjau admin, embed pihak ketiga).


Alur SEO

Diagram berikut menunjukkan bagaimana tag meta yang dikonfigurasi di formulir admin dirender di halaman artikel publik:

Kunci bawaan (dari enum SEO): description, keywords, author, robots, og:title, og:description, og:image, og:url, og:type, og:site_name, twitter:card, twitter:title, twitter:description, twitter:image — plus nama kustom apa pun yang ditambahkan via opsi + buat.

Fallback yang selalu dirender di halaman detail: og:title, og:type (article), og:url, og:image (jika ada), article:author, article:section, article:published_time, plus description / og:description yang diturunkan dari ringkasan jika tidak ada tag SEO kustom yang menimpanya.


Analitik

Sesi baca dilacak di sisi klien (mulai / scroll / selesai) lalu dikirim ke server.

Endpoint: POST /api/articles/track

Payload: article_id (wajib), fingerprint_id (wajib), session_id, read_duration_seconds, scroll_depth (0–100), completed, referrer_url.

Perilaku:

  • updateOrCreate pada (artikel, fingerprint, sesi) — satu sesi per pembaca per artikel.
  • Durasi dan kedalaman scroll hanya bertambah (monotonik).
  • IP di-resolve ke negara/kota/zona waktu via ip-api.com (cache 24 jam, best-effort, dilewati untuk localhost).
  • Tipe perangkat dideteksi dari user-agent (desktop / tablet / mobile).
  • Status selesai ditandai saat pembaca melewati penanda akhir artikel (IntersectionObserver).

Alur analitik — dari sesi baca ke dasbor


Mesin Rekomendasi

RoundupService menghasilkan daftar "artikel yang direkomendasikan" (default 8) di halaman detail.

Alur

Skor dasar (cache Redis 10 menit, dibagi antar pengunjung):

SinyalBobot
Kategori sama0,35
Sekolah sama0,15
Popularitas (pembacaan)0,15
Kebaruan (peluruhan selama 6 bulan)0,10

Personalisasi (diterapkan per fingerprint di atas skor dasar cache):

SinyalBobot
Kolaboratif — pembaca artikel ini juga membaca...hingga 0,25
Riwayat kategori pengguna inihingga 0,15

Setiap buat / ubah / hapus artikel membatalkan cache roundup dan analitik (ArticleObserver).


Basis Data

TabelDeskripsi
articlesPK UUID; title/content/excerpt (JSON terlokalisasi), slug (unik, route key), tags, category_id, school_id, author, is_active, published_at, image_asset_id, asset_alt_text, meta (JSON SEO)
article_categoriesPK UUID; name/description terlokalisasi, slug, is_active
article_analyticsPK UUID; article_id, fingerprint_id, session_id, ip_address, user_agent, referrer_url, started_at, last_active_at, read_duration_seconds, scroll_depth, completed, device_type, country, city, timezone

Fitur

Admin — Manajemen Artikel

  • CRUD — buat, ubah, lihat, dan hapus artikel; hapus massal dari daftar.
  • Konten dwibahasa — judul, ringkasan, dan konten terlokalisasi (EN/ID) dengan tab per bahasa.
  • Auto-translate — salin konten bahasa dasar ke bahasa lain dengan satu klik.
  • Penyunting teks kaya — heading, subjudul, kutipan, tautan, dan menu cepat /.
  • Sisipkan media di konten — unggah dan sematkan gambar langsung di dalam badan artikel.
  • Thumbnail — unggah gambar unggulan (dengan editor gambar) plus teks alternatif untuk aksesibilitas, dilayani via ImageKit.
  • Tag SEO meta — repeater pasangan {name, content} dengan kunci bawaan + kustom dan validasi nama unik; dirender sebagai tag <meta> di halaman publik.
  • Penjadwalan — tetapkan tanggal terbit di masa depan; artikel tetap belum dipublikasikan hingga tanggal tersebut.
  • Tags — input tag bebas pada artikel.
  • Kategori — kelola kategori dengan nama terlokalisasi, atau buat inline dari formulir artikel.
  • Pencarian & filter — pencarian teks penuh (Meilisearch) plus filter status/sekolah/kategori/rentang tanggal.
  • Pratinjau perangkat langsung — lihat artikel publik di dalam bingkai desktop/tablet/mobile.

Admin — Dasbor Analitik

  • Ringkasan statistik — total kategori, jumlah artikel terbit, dan belum terbit.
  • Geografi Pembaca — treemap pembacaan per negara.
  • Artikel Populer — pembacaan, pembaca unik, total waktu baca, dan selesai per artikel.

Publik — Artikel

  • Daftar — jelajahi /articles dengan pencarian, filter kategori/penulis/tahun, urutan (terbaru/terlama/A–Z/Z–A), pagination, dan state kosong.
  • Detail artikel — badge kategori, judul, meta penulis/tanggal/waktu baca, ringkasan sebagai pratinjau HTML, dan badan teks kaya.
  • Rekomendasi — daftar "disarankan" yang dipersonalisasi plus artikel terkait per penulis.
  • Lucky Me — interstitial saat scroll yang melompat ke artikel acak.
  • SEO — tag meta kustom, tag Open Graph, dan fallback yang dirender di <head>.
  • Lokalisasi — ganti EN ↔ ID dengan cepat tanpa reload.
  • Tampilan dapat disematkan/articles/{slug}/iframe bersih untuk embed dan pratinjau admin.

Analitik (pelacakan)

  • Sesi baca — lacak mulai, durasi, kedalaman scroll, dan selesai per pembaca.
  • Geo-lokasi — negara/kota/zona waktu di-resolve dari IP (cache, best-effort).
  • Deteksi perangkat — desktop / tablet / mobile dari user-agent.

Berkas Utama

BerkasFungsi
app/Filament/Clusters/Article/ArticleCluster.phpDefinisi cluster — slug news, navigasi
app/Filament/Clusters/Article/Resources/Articles/ArticleResource.phpResource artikel — halaman, mutate/fill data terlokalisasi
app/Filament/Clusters/Article/Resources/Articles/Schemas/ArticleForm.phpFormulir buat/ubah artikel
app/Filament/Clusters/Article/Resources/Articles/Schemas/ArticleInfolist.phpHalaman lihat artikel + kartu pratinjau langsung
app/Filament/Clusters/Article/Resources/Articles/Tables/ArticlesTable.phpDaftar artikel — kolom, filter, pencarian Meilisearch
app/Filament/Clusters/Article/Resources/ArticleCategories/ArticleCategoryResource.phpCRUD kategori
app/Filament/Clusters/Article/Pages/PopularArticlesPage.phpHalaman dasbor analitik
app/Filament/Clusters/Article/Resources/Articles/Widgets/*.phpWidget statistik, tabel populer, treemap geografi
app/Filament/Schemas/Components/Cards/ArticlePreview.phpKomponen pratinjau perangkat langsung
app/Http/Controllers/Landing/ArticleController.phpIndex / show / iframe publik
app/Http/Controllers/Api/ArticleAnalyticController.phpEndpoint pelacakan sesi
app/Http/Controllers/Api/ArticleContentController.phpAmbil konten mentah
app/Http/Controllers/Api/ArticleLuckyController.phpEndpoint artikel acak
app/Services/News/RoundupService.phpSkor rekomendasi + personalisasi
app/Services/News/AnalysisService.phpAgregasi analitik (cache)
app/Observers/News/ArticleObserver.phpPembatalan cache saat artikel berubah
app/Models/News/Article/Article.phpModel Artikel
app/Models/News/ArticleCategory/ArticleCategory.phpModel Kategori
app/Models/News/ArticleAnalytic/ArticleAnalytic.phpModel Analitik
resources/js/pages/landing/Articles/*.svelteHalaman publik daftar / detail / iframe
resources/js/modules/landing/articles/Store frontend, filter, pelacakan analitik, UI rekomendasi

Glosarium

IstilahDefinisi
Article (Artikel)Entri berita yang dikelola di panel admin dan ditampilkan di situs publik
SlugIdentitas unik ramah-URL untuk artikel atau kategori (mis. panduan-pendaftaran); dipakai sebagai route key — artikel dapat diakses di /articles/{slug}
Excerpt (Ringkasan)Ringkasan singkat artikel (terlokalisasi, per bahasa) yang ditampilkan sebagai pratinjau HTML di halaman detail publik dan dipakai sebagai fallback meta-description
Content (Konten)Isi utama artikel, ditulis di penyunting teks kaya (terlokalisasi, per bahasa)
Published At (published_at)Tanggal/waktu artikel menjadi (atau sudah) publik; jika di masa depan, artikel tetap tersembunyi hingga saat tersebut
Is Active (is_active)Flag yang mengontrol visibilitas publik — hanya artikel aktif yang muncul di /articles dan di pencarian
Tags (Tag)Kata kunci bebas yang dilampirkan ke artikel; dapat dicari via pencarian teks penuh
Category (Kategori)Pengelompokan yang mengorganisir artikel; kategori terlokalisasi dan bisa aktif/nonaktif
ThumbnailGambar unggulan artikel (sebuah Asset); ditampilkan di kartu dan dipakai untuk og:image
Alt text (Teks alternatif)Deskripsi aksesibilitas untuk gambar unggulan
Meta (meta)Kolom JSON pada artikel yang menyimpan data repeater SEO (meta.seo — daftar pasangan {name, content})
Tag SEO metaSatu entri {name, content} yang dikonfigurasi di repeater admin, dirender sebagai <meta> di halaman publik (kunci og:* memakai property)
Localization (Lokalisasi)Dukungan kolom yang sama dalam beberapa bahasa (EN/ID) disimpan sebagai JSON; halaman publik me-re-lokalisasi tanpa reload
Fingerprint (fingerprint_id)Identitas stabil sisi klien (cookie/dibangkitkan) yang mengenali pembaca lintas sesi tanpa akun; dipakai untuk analitik dan personalisasi rekomendasi
Session (session_id)Identitas satu sesi baca artikel oleh seorang pembaca
Read duration (read_duration_seconds)Total detik pembaca menghabiskan waktu di sebuah artikel; hanya bertambah (monotonik)
Scroll depth (scroll_depth)Seberapa jauh (0–100%) pembaca menggulir artikel
Completed (completed)Flag yang disetel saat pembaca melewati penanda akhir artikel — dipakai untuk metrik selesai
Sentinel (Penanda)Elemen tersembunyi di akhir badan artikel yang diamati via IntersectionObserver untuk mendeteksi selesai membaca
ArticleAnalyticSatu baris per sesi baca artikel, mengagregasi metrik di atas
Lucky MeInterstitial pemicu-scroll di halaman detail yang menavigasi ke artikel acak lain
Recommended articles (Artikel disarankan)Daftar terpersonalisasi yang dibangkitkan RoundupService (sinyal kategori/sekolah/popularitas/kebaruan + kolaboratif/riwayat)
Reader Geography (Geografi Pembaca)Treemap dasbor pembacaan per negara, di-resolve dari IP pembaca
MeilisearchMesin pencarian teks penuh yang mendukung pencarian global admin dan kotak pencarian publik