cara membuat sistem bookmark hierarkis dengan tag untuk riset dan referensi jangka panjang
Kalau kamu sering riset untuk proyek coding, menulis artikel, atau sekadar mengumpulkan referensi teknis, pasti pernah mengalami masalah ini: bookmark browser menumpuk tanpa struktur, link hilang di tengah ratusan tab, atau lupa konteks kenapa dulu menyimpan artikel tertentu. Sistem bookmark hierarkis dengan tag bisa jadi solusi praktis. Artikel ini akan memandu kamu membuat sistem tersebut menggunakan tools sederhana yang bisa dijalankan di Termux atau laptop, tanpa perlu layanan cloud berbayar.
Kenapa Perlu Sistem Bookmark Sendiri?
Browser bookmark memang praktis, tapi punya keterbatasan: sulit dicari ulang setelah berbulan-bulan, tidak bisa menambahkan catatan panjang, dan tidak portabel antar perangkat tanpa sinkronisasi akun. Sistem berbasis file lokal dengan SQLite atau JSON memberi kontrol penuh: kamu bisa backup, migrasi, atau bahkan otomasi pencarian dengan script. Tag hierarkis memungkinkan satu bookmark masuk ke beberapa kategori sekaligus, misalnya "python/web-scraping" dan "tutorial/pemula".
Pilihan Teknologi yang Realistis
Untuk sistem bookmark lokal, ada beberapa pendekatan yang terbukti stabil:
SQLite + Python: Cocok kalau kamu sudah familiar dengan SQL dan ingin query fleksibel. Database SQLite ringan, tidak butuh server, dan bisa dibuka langsung dengan tools seperti sqlite3 di terminal.
JSON + jq: Lebih sederhana untuk pemula. Simpan bookmark dalam format JSON, lalu gunakan jq untuk filter dan pencarian. Cocok untuk koleksi di bawah 1000 item.
Markdown + grep: Paling minimalis. Setiap bookmark jadi entry Markdown dengan frontmatter YAML untuk metadata. Pencarian pakai grep atau ripgrep. Mudah dibaca manusia, tapi lambat untuk dataset besar.
Untuk tutorial ini, kita pakai pendekatan SQLite karena balance antara fleksibilitas dan performa.
Langkah Praktis
- Setup database awal. Install SQLite di Termux dengan
pkg install sqlite. Buat file database:sqlite3 bookmarks.db. Definisikan skema tabel:CREATE TABLE bookmarks ( id INTEGER PRIMARY KEY, url TEXT NOT NULL, title TEXT, notes TEXT, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE tags ( id INTEGER PRIMARY KEY, name TEXT UNIQUE NOT NULL ); CREATE TABLE bookmark_tags ( bookmark_id INTEGER, tag_id INTEGER, FOREIGN KEY(bookmark_id) REFERENCES bookmarks(id), FOREIGN KEY(tag_id) REFERENCES tags(id) );
Struktur ini memisahkan tag dari bookmark, jadi satu tag bisa dipakai berkali-kali tanpa duplikasi. - Buat script Python untuk menambah bookmark. Simpan sebagai
add_bookmark.py:import sqlite3 import sys def add_bookmark(url, title, tags, notes=""): conn = sqlite3.connect('bookmarks.db') c = conn.cursor() c.execute("INSERT INTO bookmarks (url, title, notes) VALUES (?, ?, ?)", (url, title, notes)) bookmark_id = c.lastrowid for tag in tags.split(','): tag = tag.strip() c.execute("INSERT OR IGNORE INTO tags (name) VALUES (?)", (tag,)) c.execute("SELECT id FROM tags WHERE name=?", (tag,)) tag_id = c.fetchone()[0] c.execute("INSERT INTO bookmark_tags VALUES (?, ?)", (bookmark_id, tag_id)) conn.commit() conn.close() print(f"Bookmark ditambahkan dengan ID {bookmark_id}") if __name__ == "__main__": add_bookmark(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4] if len(sys.argv) > 4 else "")Jalankan dengan:python add_bookmark.py "https://example.com" "Judul Artikel" "python,tutorial" "Catatan opsional" - Buat script pencarian. Simpan sebagai
search_bookmarks.py:import sqlite3 import sys def search(query): conn = sqlite3.connect('bookmarks.db') c = conn.cursor() c.execute(""" SELECT DISTINCT b.id, b.url, b.title, GROUP_CONCAT(t.name, ', ') as tags FROM bookmarks b LEFT JOIN bookmark_tags bt ON b.id = bt.bookmark_id LEFT JOIN tags t ON bt.tag_id = t.id WHERE b.title LIKE ? OR b.notes LIKE ? OR t.name LIKE ? GROUP BY b.id """, (f"%{query}%", f"%{query}%", f"%{query}%")) for row in c.fetchall(): print(f"[{row[0]}] {row[2]}\n {row[1]}\n Tags: {row[3]}\n") conn.close() if __name__ == "__main__": search(sys.argv[1])Cari bookmark dengan:python search_bookmarks.py "python" - Tambahkan fitur ekspor. Untuk backup atau migrasi, buat script ekspor ke JSON:
import sqlite3 import json conn = sqlite3.connect('bookmarks.db') c = conn.cursor() c.execute(""" SELECT b.id, b.url, b.title, b.notes, b.created_at, GROUP_CONCAT(t.name, ',') as tags FROM bookmarks b LEFT JOIN bookmark_tags bt ON b.id = bt.bookmark_id LEFT JOIN tags t ON bt.tag_id = t.id GROUP BY b.id """) bookmarks = [] for row in c.fetchall(): bookmarks.append({ "id": row[0], "url": row[1], "title": row[2], "notes": row[3], "created_at": row[4], "tags": row[5].split(',') if row[5] else [] }) with open('bookmarks_export.json', 'w') as f: json.dump(bookmarks, f, indent=2) print(f"Exported {len(bookmarks)} bookmarks") - Otomasi dengan alias. Tambahkan ke
~/.bashrcatau~/.zshrc:alias bm-add='python ~/bookmarks/add_bookmark.py' alias bm-search='python ~/bookmarks/search_bookmarks.py'
Sekarang kamu bisa langsungbm-add "url" "title" "tags"dari terminal mana pun.
Kesalahan yang Sering Terjadi
- Tidak konsisten dalam penamaan tag. Gunakan konvensi seperti lowercase dan pisahkan hierarki dengan slash:
python/web-scraping, bukanPython Web Scraping. Ini memudahkan pencarian dan filtering. - Lupa backup database. SQLite file bisa corrupt kalau terjadi crash saat write. Buat cron job sederhana:
0 2 * * * cp ~/bookmarks.db ~/bookmarks_backup_$(date +\%Y\%m\%d).db - Menyimpan kredensial dalam notes. Jangan simpan password atau API key di field notes. Gunakan password manager terpisah.
- Tidak validasi URL. Tambahkan validasi dasar di script untuk menghindari typo atau URL tidak lengkap yang bikin database berantakan.
- Over-engineering di awal. Mulai dengan fitur minimal: tambah, cari, tag. Fitur seperti full-text search atau web interface bisa ditambahkan nanti kalau memang butuh.
Tips Aman dan Etis
Sistem bookmark lokal memberi kontrol penuh, tapi juga tanggung jawab. Jangan gunakan untuk menyimpan link phishing, malware, atau konten ilegal. Kalau kamu scraping metadata dari URL (misalnya ambil title otomatis), respect robots.txt dan rate limiting. Jangan spam request ke server orang lain.
Untuk sinkronisasi antar perangkat, hindari upload database mentah ke cloud publik tanpa enkripsi. Gunakan Git dengan repository private, atau enkripsi file dengan GPG sebelum upload. Alternatif lain: gunakan Syncthing untuk sinkronisasi peer-to-peer tanpa server tengah.
Kalau kamu develop fitur web interface, jangan expose ke internet tanpa autentikasi. Cukup bind ke localhost dan akses lewat SSH tunnel kalau perlu remote access.
Pengalaman Lapangan
Setelah pakai sistem ini selama beberapa bulan, beberapa pola yang muncul: tag hierarkis paling berguna untuk topik teknis yang overlap (misalnya "docker/networking" dan "linux/networking"). Field notes jadi tempat simpan konteks kenapa bookmark itu penting, bukan cuma copy-paste excerpt. Pencarian full-text lebih sering dipakai daripada browsing hierarki, jadi investasi waktu untuk indexing worth it.
Satu hal yang underrated: timestamp. Bookmark dari 2 tahun lalu sering sudah outdated, terutama untuk dokumentasi framework yang fast-moving. Tambahkan field last_verified dan review berkala.
Kesimpulan
Sistem bookmark hierarkis dengan tag bukan cuma soal organisasi, tapi juga tentang membangun knowledge base pribadi yang tahan lama. Dengan SQLite dan Python, kamu punya kontrol penuh tanpa tergantung layanan pihak ketiga. Mulai sederhana, iterasi sesuai kebutuhan, dan jangan lupa backup. Sistem yang baik adalah yang benar-benar kamu pakai, bukan yang paling kompleks.