Bible API Β· Go Β· Open Source

Satu mesin,
banyak sumber.

API Alkitab berbasis Go dengan arsitektur adapter β€” local JSON sebagai default, scrape alkitab.mobi sebagai opsi. Satu binari, tanpa database, tanpa pernah mendistribusikan teks berhak cipta.

~/alkitab-api
# jalankan dalam satu baris
$ go run ./cmd/alkitab-api
  β†’ listening on :3000 (scrape=false)

# ambil satu ayat
$ curl localhost:3000/v1/kjv/3john/1/4
{
  "version": "kjv",
  "verses": [
    { "verse": 4,
      "content": "I have no greater joy…" }
  ]
}
Filosofi

Hak cipta adalah masalah arsitektur.

Sebagian besar terjemahan Alkitab β€” termasuk Terjemahan Baru β€” berstatus berhak cipta. Proyek ini menanggapinya bukan dengan mengabaikan, melainkan dengan merancang ulang: teks bawaan adalah domain-publik, akses ke terjemahan berhak cipta bersifat opt-in dan hanya terjadi saat runtime.

i.

Bring Your Own Data

Mesin tidak membawa teks berhak cipta. Cukup letakkan berkas JSON di ALKITAB_DATA_DIR dan ia langsung terbaca di samping contoh domain-publik yang sudah tertanam.

ii.

Scrape adalah opt-in

Akses ke Terjemahan Baru tetap mungkin lewat adapter scrape yang diaktifkan dengan ALKITAB_SCRAPE=1 β€” sekadar proxy saat runtime, tanpa redistribusi.

iii.

Tiga lapis, satu arah

Transport, mesin, adapter. Dependensi hanya mengalir ke dalam. Itu yang membuat BYOD dan opt-in scrape bekerja tanpa menulis ulang inti.

Design tokens
Paper
#F5EFE1
Paper-2
#EFE7D4
Ink
#1C1813
Rubric
#9A3B2D
Olive
#64703F
Gold
#9A7B2E
Display Β· FrauncesTeks suci
Body Β· Frauncesayat yang berbicara
Code Β· JetBrains/v1/kjv/3john/1
EyebrowBible API
Arsitektur

Tiga lapisan, dependensi mengalir ke dalam.

REST menyentuh mesin; mesin membungkus sebuah Source; adapter mengimplementasikan kontrak itu. Arahkan kursor atau ketuk tiap lapis untuk menonjolkannya.

Lapisan Β· Transport
server
REST di atas stdlib net/http. Routing pola Go 1.22, tanpa dependensi. Mapping error terpusat di sini.
Handlernet/http

7 rute: translations, books, chapter, verse, search, daily, random.

mapErr β†’ 404/501/400/500ResolveBookIDsort deterministik
HTTP
Lapisan Β· Inti
engine
Pure domain. Cache pasal in-memory, dan tiga operasi yang ditopang kapabilitas Corpus.
Enginecache

Membungkus satu Source. Menyimpan pasal agar tidak di-fetch ulang.

Chapter()Search()DailyVerse()RandomVerse()
Chaincomposite

Menggabungkan source secara berurutan: local dulu, scrape saat tidak ada.

fallback ErrNotFound / ErrUnsupportedVersionmerge Translations
Source / Corpus
Lapisan Β· Adapter
sources
Dua implementasi Source. Hanya yang punya korpus in-memory yang menopang search/daily/random.
localdefault

JSON + go:embed, di-scan di memori. Contoh KJV domain-publik tertanam.

Corpus βœ“scan O(n)ALKITAB_DATA_DIR
scrapeopt-in

Mengikis alkitab.mobi via goquery. Timeout 10s, body dibatasi 4 MiB, error tidak bocor.

Corpus βœ— β†’ 501tb Β· bahasa daerah

Kapabilitas Corpus diperiksa lewat type assertion β€” search/daily/random jujur mengembalikan 501 saat sumber aktif tidak punya korpus.

Siklus permintaan

Bagaimana satu GET menjadi ayat.

Dari path hingga JSON, setiap langkah melalui satu titik: Engine.

i

Menerima GET /v1/kjv/3john/1

Router Go 1.22 menangkap path values. {chapter} divalidasi numerik; bukan β†’ 400.

ii

Resolve book β†’ id

ResolveBookID menerima id, nama Inggris, atau nama Indonesia (case-insensitive) dan menormalisasinya ke "3john".

iii

Engine mengecek cache

Cache in-memory version:book:chapter dijamin RWMutex. Kena β†’ langsung kembali. Luput β†’ lanjut ke source.

iv

Source menjawab (local, atau Chain β†’ scrape)

local.Chapter membaca JSON tertanam. Jika versi tak ada dan scrape aktif, Chain meneruskan ke adapter scrape.

v

JSON keluar

Hasil di-cache, diserialisasi. Error bertipe memetakan ke kode status yang tepat β€” tak ada pesan internal yang bocor.

Endpoint

Tujuh rute, kontrak sederhana.

JSON masuk, JSON keluar. {book} menerima id, nama, atau singkatan β€” Inggris maupun Indonesia.

GET
/v1/translations
Daftar terjemahan

Terjemahan yang tersedia di source aktif (contoh tertanam + direktori data).

GET
/v1/{version}/books
Struktur kitab

Daftar kitab, jumlah pasal, dan kategori PL/PB untuk satu terjemahan.

GET
/v1/{version}/{book}/{chapter}
Satu pasal

Seluruh ayat, termasuk judul bagian.

GET
/v1/{version}/{book}/{chapter}/{verse}
Satu ayat

Disaring ke satu nomor ayat.

GET
/v1/search?q={q}&version={v}
Pencarian teks

Substring case-insensitive di korpus lokal.

GET
/v1/daily?version={v}
Ayat hari ini

Deterministik per tanggal & versi (UTC).

GET
/v1/random?version={v}
Ayat acak

Seed otomatis dari math/rand/v2.

Demo

Ambil ayat, langsung.

Coba ambil 3 Yohanes 1:4 dari server lokal, atau lihat contoh jika server belum berjalan.

butuh go run ./cmd/alkitab-api di port 3000
response Β· kjv Β· 3john 1:4
// contoh respons (server belum dihubungi)
{
  "version": "kjv",
  "book": "3john",
  "chapter": 1,
  "verses": [
    {
      "verse": 4,
      "content": "I have no greater joy than to hear that my children walk in truth.",
      "type": "content",
      "order": 0
    }
  ]
}

Bring Your Own Data

β€œTidak ada teks berhak cipta di repositori ini β€” dan sengaja demikian.”

Contoh tertanam adalah domain-publik β€” KJV, hanya 3 Yohanes & Filemon. File runtime dengan id yang sama menimpa contoh tertanam. Terjemahan berhak cipta seperti TB Β© LAI hanya bisa diakses saat runtime lewat proxy scrape β€” tanggung jawab operator, bukan proyek.

ALKITAB_PORTport listen Β· default 3000
ALKITAB_DATA_DIRdirektori terjemahan tambahan
ALKITAB_SCRAPE1 β†’ aktifkan adapter scrape
ALKITAB_BASE_URLbasis scrape Β· default alkitab.mobi
alkitab-data/tb.json
// format BYOD β€” satu file per terjemahan
{
  "translation": {
    "id": "tb",
    "name": "Terjemahan Baru",
    "language": "id"
  },
  "books": [
    { "id": "john",
      "name": "Yohanes",
      "abbr": "Yoh",
      "testament": "NT",
      "chapters": 21,
      "chapter_data": [
        { "number": 1,
          "verses": [
            { "verse": 1,
              "type": "content",
              "content": "…" }
          ] }
      ] }
  ]
}