<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Derek Ziemer</title>
    <description>The latest articles on DEV Community by Derek Ziemer (@derek_codes).</description>
    <link>https://dev.to/derek_codes</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3819471%2Fcd150f97-9a4b-42c0-bf70-8018fb329f76.png</url>
      <title>DEV Community: Derek Ziemer</title>
      <link>https://dev.to/derek_codes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/derek_codes"/>
    <language>en</language>
    <item>
      <title>From Topic -&gt; Scripture -&gt; Application</title>
      <dc:creator>Derek Ziemer</dc:creator>
      <pubDate>Mon, 23 Mar 2026 13:46:16 +0000</pubDate>
      <link>https://dev.to/derek_codes/from-topic-scripture-application-3207</link>
      <guid>https://dev.to/derek_codes/from-topic-scripture-application-3207</guid>
      <description>&lt;h1&gt;
  
  
  Most Bible APIs stop at verses.
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Let's go further.
&lt;/h2&gt;

&lt;p&gt;Start with a concept: &lt;strong&gt;Suffering&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1 — Resolve the Topic
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--get&lt;/span&gt; https://holybible.dev/api/topics &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer bb_free_demo"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--data-urlencode&lt;/span&gt; &lt;span class="s2"&gt;"q=suffering"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You get a canonical node — not a keyword match, not a guess:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"query"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"suffering"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"matches"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"slug"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"suffering"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Suffering"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"experience"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"match_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"exact"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"anchor_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"verse_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"related"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"slug"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"hope"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hope"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"relation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"related"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"direction"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"outgoing"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"slug"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"patience"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Patience"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"virtue"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"relation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"related"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"direction"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"incoming"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A defined concept. One you can reason from. Related graph nodes surface immediately.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2 — Fetch the Topic Structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://holybible.dev/api/topics/suffering &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer bb_free_demo"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response gives you everything needed to ground the LLM: a canonical description, related concepts like hope and patience, and anchor verses drawn from passages such as Isaiah 53:3, Romans 5:3, 2 Corinthians 4:17, James 1:2, and 1 Peter 4:12.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3 — Generate (Constrained by Scripture)
&lt;/h2&gt;

&lt;p&gt;Take the retrieved anchor passages and pass them to an LLM with one instruction: only use the provided text.&lt;/p&gt;

&lt;p&gt;Here's the full trace:&lt;/p&gt;






&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;════════════════════════════════════════
  Topic: suffering
════════════════════════════════════════

STEP 1 — Resolve Canonical Topic
→ Suffering [experience]

────────────────────────────────────────
STEP 2 — Doctrinal Context
The experience of pain, loss, or hardship that draws the
human soul toward God, hope, and transformation.

────────────────────────────────────────
STEP 3 — Theological Flow
Suffering —related→ Hope
Patience —related→ Suffering

────────────────────────────────────────
STEP 4 — Anchor Scriptures
Isaiah 53:3
Romans 5:3
2 Corinthians 4:17
James 1:2

────────────────────────────────────────
STEP 5 — Scripture-Constrained Generation
🔒 Only retrieved passages may be used.

You've been through something hard. Maybe this week.
Maybe this year. And part of you wonders — does God
even see this?

He sees it. He *lived* it.

Isaiah 53:3 says He was despised. Rejected. Acquainted
with grief. That's not distant theology — that's your
Savior knowing exactly what your Tuesday felt like.

So when Romans 5:3 says we *glory* in tribulations —
that's not crazy talk. That's someone who's been there
telling you the pain has a destination.

James 1:2 says *count it all joy.* Not fake it. Count it.
Like you're doing math. Like there's something real on
the other side of the equation.

And 2 Corinthians 4:17 tells you what that something is —
an *eternal weight of glory* that makes this moment
look light.

Here's my question — what are you calling a dead end
that God is calling a doorway?

Monday morning? Don't run from the hard thing. Name it.
Then say out loud — *this is working something in me.*

Because it is.

════════════════════════════════════════
Result: Structured, Christ-centered, and grounded in canonical Scripture.
════════════════════════════════════════
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What Just Happened
&lt;/h2&gt;

&lt;p&gt;BibleBridge handled the structure: canonical topic, graph relationships, anchor verses.&lt;/p&gt;

&lt;p&gt;The LLM handled the generation — but only inside the text it was given.&lt;/p&gt;

&lt;p&gt;That's the combination that matters.&lt;/p&gt;

&lt;p&gt;This wasn't:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Freeform generation&lt;/li&gt;
&lt;li&gt;Keyword matching&lt;/li&gt;
&lt;li&gt;Stitched-together verses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A canonical topic&lt;/li&gt;
&lt;li&gt;Structured relationships&lt;/li&gt;
&lt;li&gt;Bounded scripture&lt;/li&gt;
&lt;li&gt;An LLM that couldn't wander outside it&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Difference
&lt;/h2&gt;

&lt;p&gt;Most systems can retrieve scripture. This lets you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Follow theological structure&lt;/li&gt;
&lt;li&gt;Enforce grounding&lt;/li&gt;
&lt;li&gt;Generate output that stays inside the text&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not just answers. &lt;strong&gt;Faithful reasoning.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There's more to explore than this example shows — topics, relationships, anchor verses, all queryable. Dig around at BibleBridge and see what you find.&lt;br&gt;
Try the API at &lt;a href="https://holybible.dev" rel="noopener noreferrer"&gt;https://holybible.dev&lt;/a&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>backend</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Why Bible APIs Should Be Version-Agnostic</title>
      <dc:creator>Derek Ziemer</dc:creator>
      <pubDate>Thu, 12 Mar 2026 06:28:53 +0000</pubDate>
      <link>https://dev.to/derek_codes/why-bible-apis-should-be-version-agnostic-nfe</link>
      <guid>https://dev.to/derek_codes/why-bible-apis-should-be-version-agnostic-nfe</guid>
      <description>&lt;p&gt;When I tell developers I built a Bible reference resolver, I can see them mentally categorizing it.&lt;/p&gt;

&lt;p&gt;Regex. String matching. Probably handles Jn316 and John 3:16 and calls it done.&lt;/p&gt;

&lt;p&gt;That's not what this is.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem Nobody Talks About
&lt;/h2&gt;

&lt;p&gt;Most Bible APIs are built around a simple assumption: the developer provides a clean, well-formed reference and the API returns verse text.&lt;/p&gt;

&lt;p&gt;That assumption breaks immediately in production.&lt;/p&gt;

&lt;p&gt;Real users write things like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;iitim3:16-17
Genisis 1:1
acts 2:1 to 4
Rom 8:1-4, 28; 12:1-2
Ps.23, vv.1–3
ESV John 3:16
canticles 2:1
Obadiah 15
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A naive parser handles maybe 60% of these. A regex handles a bit more. But every edge case you add reveals three more you hadn't considered.&lt;/p&gt;

&lt;p&gt;The deeper problem is structural. Most Bible APIs tie their identifiers to a specific translation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;John 3:16 in KJV
John 3:16 in NIV
John 3:16 in ESV
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From a developer perspective, these represent the same coordinate. But most APIs treat them as different entities. That means your stored references, your database indexes, your AI retrieval pipeline—all of it is implicitly tied to a translation choice you made at build time.&lt;/p&gt;

&lt;p&gt;That's fragile architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Bible Software Companies Figured Out (And Kept Private)
&lt;/h2&gt;

&lt;p&gt;Here's something interesting: Bible software companies like Logos and Accordance built extremely sophisticated internal engines over decades. Reference normalization, canonical coordinates, traversal systems, cross-translation alignment—all of it exists, all of it works, and none of it is public.&lt;/p&gt;

&lt;p&gt;The public API ecosystem never caught up. Most public Bible APIs are still essentially:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /verse
GET /chapter
GET /search
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The developer is responsible for everything that happens before and after: parsing user input, validating references, handling edge cases, building traversal logic, and managing coordinates across translations.&lt;/p&gt;

&lt;p&gt;That's a lot of infrastructure to build yourself before you've written a single line of your actual application.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Problem: Input Is Messy, Coordinates Should Not Be
&lt;/h2&gt;

&lt;p&gt;The insight that changed how I thought about this:&lt;/p&gt;

&lt;p&gt;Reference parsing and text retrieval are two different problems.&lt;/p&gt;

&lt;p&gt;Most APIs conflate them. You send a reference, you get text back. Clean input in, content out.&lt;/p&gt;

&lt;p&gt;But in production systems—especially AI systems—you need something in between. You need a layer that takes messy human input and produces reliable, stable, version-agnostic coordinates that your system can store, traverse, and retrieve against regardless of which translation you eventually serve.&lt;/p&gt;

&lt;p&gt;That's what I built.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture: Two Distinct Layers
&lt;/h2&gt;

&lt;p&gt;Layer 1 — Version-Agnostic Infrastructure&lt;/p&gt;

&lt;p&gt;Human Input → Reference Integrity Engine → Canonical Coordinates&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;/resolve&lt;/code&gt; — Normalize any human input to canonical coordinates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;/expand&lt;/code&gt; — Atomic verse IDs from any reference.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;/context&lt;/code&gt; — Traverse surrounding verses by canonical index.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;/lookup&lt;/code&gt; — Reconstruct human-readable references from coordinates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;/diff&lt;/code&gt; — Compare two references and return canonical overlap and differences.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;/range&lt;/code&gt; — Resolve a reference range into canonical boundaries.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;/distance&lt;/code&gt; — Compute verse distance between two coordinates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;/slice&lt;/code&gt; — Retrieve a canonical verse range by verse_index.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Layer 2 — Text Retrieval (Version Required)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;/scripture&lt;/code&gt; — Fetch verse text in a specific translation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;/passage&lt;/code&gt; — Resolve and retrieve in one call.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;/batch&lt;/code&gt; — Bulk retrieval.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;/search&lt;/code&gt; — Full-text search.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Layer 1 works independently of Layer 2. You can use the entire canonical infrastructure stack without ever calling a text retrieval endpoint. Bring your own licensed translation or vector store—the coordinate system works regardless.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Reference Integrity Engine
&lt;/h2&gt;

&lt;p&gt;This is not a parser. A parser converts structured input into structured output. The Reference Integrity Engine handles input that is not well-formed. It recovers from malformed references, resolves ambiguity explicitly, and returns deterministic outputs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real-World Testing Examples&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Roman numeral ordinals: &lt;code&gt;iitim3:16-17&lt;/code&gt; → &lt;code&gt;2Tim.3.16-2Tim.3.17&lt;/code&gt; ✓&lt;/p&gt;

&lt;p&gt;Misspelled words: &lt;code&gt;Genisis 1:1&lt;/code&gt; → &lt;code&gt;Gen.1.1&lt;/code&gt; ✓&lt;/p&gt;

&lt;p&gt;Natural language ranges: &lt;code&gt;acts 2:1 to 4&lt;/code&gt; → &lt;code&gt;Acts.2.1-Acts.2.4&lt;/code&gt; ✓&lt;/p&gt;

&lt;p&gt;Translation identifiers: &lt;code&gt;ESV John 3:16&lt;/code&gt; → &lt;code&gt;John.3.16&lt;/code&gt; (translation: ESV) ✓&lt;/p&gt;

&lt;p&gt;Alternative book names: &lt;code&gt;canticles 2:1&lt;/code&gt; → &lt;code&gt;Song.2.1&lt;/code&gt; ✓&lt;/p&gt;

&lt;p&gt;Single-chapter edge cases: &lt;code&gt;Obadiah 15&lt;/code&gt; → &lt;code&gt;Obad.1.15&lt;/code&gt; ✓&lt;/p&gt;

&lt;p&gt;Compound disjoint references: &lt;code&gt;Rom 8:1-4, 28; 12:1-2&lt;/code&gt; → &lt;code&gt;Rom.8.1-Rom.8.4, Rom.8.28, Rom.12.1-Rom.12.2&lt;/code&gt; ✓&lt;/p&gt;

&lt;h3&gt;
  
  
  Explicit Ambiguity
&lt;/h3&gt;

&lt;p&gt;Input:&lt;br&gt;
&lt;code&gt;Samuel&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"single"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"valid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ambiguous"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"candidates"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1SA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1 Samuel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"osis"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1Sam"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"weight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.8275&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2SA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2 Samuel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"osis"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2Sam"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"weight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;70&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"score"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.8275&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Silent ambiguity resolution is how AI systems produce confident wrong answers. Surfacing it lets the application decide whether to prompt the user or log it for review.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Canonical Coordinate System
&lt;/h2&gt;

&lt;p&gt;Every resolved reference produces stable, version-agnostic coordinates:&lt;/p&gt;

&lt;p&gt;Response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"results_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"verse_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;45008001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"verse_index"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;28118&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"book"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Romans"&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"chapter"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"verse"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"reference"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Romans 8:1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"osis_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Rom.8.1"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These identifiers are immutable. The verse_index is a global sequential position (1 through 31,102), making traversal possible without complex client-side boundary logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters for AI Systems
&lt;/h2&gt;

&lt;p&gt;LLMs often hallucinate Scripture references. Any serious AI application needs a grounding layer. This stack maps directly onto AI pipeline needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Grounding&lt;/strong&gt; — Use &lt;code&gt;/resolve&lt;/code&gt; to validate LLM output before it touches your retrieval system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Indexing&lt;/strong&gt; — Use &lt;code&gt;/expand&lt;/code&gt; to convert references into atomic IDs for vector stores.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;RAG Context&lt;/strong&gt; — Use &lt;code&gt;/context&lt;/code&gt; to retrieve surrounding verses, traversing chapter and book boundaries automatically.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Citations&lt;/strong&gt; — Use &lt;code&gt;/lookup&lt;/code&gt; to reconstruct readable references for the end-user.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What Gets Rejected and Why
&lt;/h2&gt;

&lt;p&gt;Canon-aware validation means the engine knows the physical boundaries of the Bible:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ps 23:99&lt;/code&gt; → Rejected (Invalid verse in span)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;1 john 1-9&lt;/code&gt; → Rejected (Invalid chapter span)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;great commission&lt;/code&gt; → Rejected (Book not recognized)&lt;/p&gt;

&lt;p&gt;Topical phrases are rejected cleanly. The engine resolves Scripture references, not theological concepts.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Honest Limits
&lt;/h2&gt;

&lt;p&gt;English-only: Currently supports English book name recognition.&lt;/p&gt;

&lt;p&gt;No Apocrypha: Books like Sirach or Tobit return clean rejections.&lt;/p&gt;

&lt;h2&gt;
  
  
  One More Thing
&lt;/h2&gt;

&lt;p&gt;The biggest long-term value here is the coordinate system.&lt;/p&gt;

&lt;p&gt;A stable, public standard for Scripture coordinates doesn't currently exist. If enough developers use a shared coordinate system, the verse_id becomes something you can exchange between systems and reference in open datasets.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;The Resolver Playground (No signup required):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://holybible.dev/resolve-playground" rel="noopener noreferrer"&gt;Resolver Playground&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;API Documentation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://holybible.dev/api-docs" rel="noopener noreferrer"&gt;API Docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Built by Derek — creator of &lt;a href="https://holybible.dev" rel="noopener noreferrer"&gt;BibleBridge&lt;/a&gt;, a canonical coordinate system for Scripture APIs.&lt;/p&gt;

</description>
      <category>api</category>
      <category>ai</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
