Overview
The Bible server actions provide functions to interact with the Bible API, including fetching available translations, retrieving books and chapters, and searching for verses.
All functions are created using TanStack Start’s createServerFn() and include automatic validation using Zod schemas.
getBibles
Fetch all available Bible translations.
getBibles (): Promise < BibleSummary [] >
Returns
Array of Bible translation summaries Show BibleSummary properties
Unique identifier for the Bible translation
Short abbreviation (e.g., “KJV”, “NIV”)
Full name of the translation
Description of the translation
Language information object
Array of country objects with id, name, and nameLocal
Type of Bible (e.g., “text”)
ISO 8601 timestamp of last update
Optional array of associated audio Bibles
Usage
Client Component
Server Component
import { getBibles } from '@/actions/bible'
export default function BibleSelector () {
const [ bibles , setBibles ] = useState < BibleSummary []>([])
useEffect (() => {
getBibles (). then ( data => {
setBibles ( data )
})
}, [])
return (
< select >
{ bibles . map ( bible => (
< option key = {bible. id } value = {bible. id } >
{ bible . name } ({bible. abbreviation })
</ option >
))}
</ select >
)
}
Error Handling
If the API request fails, getBibles() returns an empty array [] instead of throwing an error. Errors are logged to the console.
getBooks
Retrieve all books for a specific Bible translation, including chapter information.
getBooks ( params : { bibleId: string }): Promise < Book [] >
Parameters
The unique identifier of the Bible translation (e.g., “de4e12af7f28f599-02”)
Returns
Array of book objects with chapter information Unique identifier for the book (e.g., “GEN”, “MAT”)
The Bible translation ID this book belongs to
Short abbreviation of the book (e.g., “Gen”, “Matt”)
Full name of the book (e.g., “The Book of Genesis”)
Optional array of chapter summaries (included when using include-chapters parameter) Show ChapterSummary properties
Unique chapter identifier
Human-readable reference (e.g., “Genesis 1”)
Usage
Client Component
Server Component
import { getBooks } from '@/actions/bible'
export default function BookList ({ bibleId } : { bibleId : string }) {
const [ books , setBooks ] = useState < Book []>([])
useEffect (() => {
getBooks ({ bibleId }). then ( data => {
setBooks ( data )
})
}, [ bibleId ])
return (
< div >
{ books . map ( book => (
< div key = {book. id } >
< h3 >{book. name } </ h3 >
< p >{book.chapters?.length || 0 } chapters </ p >
</ div >
))}
</ div >
)
}
Error Handling
Returns an empty array [] if the request fails. Errors are logged to the console.
getChapter
Retrieve the full content of a specific chapter, including all verses and metadata.
getChapter ( params : {
bibleId: string
chapterId : string
}): Promise < Chapter | null >
Parameters
The unique identifier of the Bible translation
The unique identifier of the chapter (e.g., “GEN.1”, “JHN.3”)
Returns
Chapter object with full content, or null if not found Unique identifier for the chapter
Human-readable reference (e.g., “John 3”)
HTML content of the entire chapter with all verses
Total number of verses in the chapter
Copyright information for the translation
Information about the next chapter Information about the previous chapter Previous chapter’s book ID
Usage
Client Component
Server Component
import { getChapter } from '@/actions/bible'
import { useEffect , useState } from 'react'
export default function ChapterReader ({
bibleId ,
chapterId
} : {
bibleId : string
chapterId : string
}) {
const [ chapter , setChapter ] = useState < Chapter | null >( null )
const [ loading , setLoading ] = useState ( true )
useEffect (() => {
setLoading ( true )
getChapter ({ bibleId , chapterId })
. then ( data => {
setChapter ( data )
})
. finally (() => setLoading ( false ))
}, [ bibleId , chapterId ])
if ( loading ) return < div > Loading ...</ div >
if ( ! chapter ) return < div > Chapter not found </ div >
return (
< article >
< h1 >{chapter. reference } </ h1 >
< div
className = "chapter-content"
dangerouslySetInnerHTML = {{ __html : chapter . content }}
/>
< footer >
< p >{chapter. copyright } </ p >
< div className = "navigation" >
{ chapter . previous && (
< a href = { `/bible/ ${ bibleId } / ${ chapter . previous . id } ` } >
Previous
</ a >
)}
{ chapter . next && (
< a href = { `/bible/ ${ bibleId } / ${ chapter . next . id } ` } >
Next
</ a >
)}
</ div >
</ footer >
</ article >
)
}
Error Handling
Returns null if the chapter cannot be found or the request fails. Errors are logged to the console.
The content property contains HTML markup. Always use dangerouslySetInnerHTML or a safe HTML sanitizer when rendering.
searchVerse
Search for verses matching a query string within a specific Bible translation.
searchVerse ( params : {
bibleId: string
query : string
offset : number
}): Promise < SearchResponse >
Parameters
The unique identifier of the Bible translation to search within
The search query string. Keywords will be matched against verse text. All keywords must be present in a verse for it to match.
Pagination offset for results. Use 0 for the first page, 10 for the second page (with default limit), etc.
Returns
Search results with matching verses Show SearchResponse properties
The search query that was executed
Maximum number of results per page (API default is 10)
Current pagination offset
Total number of matching verses found
Number of verses in the current page of results
Array of matching verses Show SearchVerse properties
Optional human-readable reference (e.g., “John 3:16”)
Optional array of passage objects
Usage
Client Component
Server Component with Search Params
import { searchVerse } from '@/actions/bible'
import { useState } from 'react'
export default function BibleSearch ({ bibleId } : { bibleId : string }) {
const [ query , setQuery ] = useState ( '' )
const [ results , setResults ] = useState < SearchResponse | null >( null )
const [ loading , setLoading ] = useState ( false )
const [ page , setPage ] = useState ( 0 )
const handleSearch = async ( offset = 0 ) => {
if ( ! query . trim ()) return
setLoading ( true )
const data = await searchVerse ({
bibleId ,
query: query . trim (),
offset
})
setResults ( data )
setLoading ( false )
}
const loadMore = () => {
const nextOffset = ( page + 1 ) * 10
setPage ( page + 1 )
handleSearch ( nextOffset )
}
return (
< div >
< input
type = "text"
value = { query }
onChange = {(e) => setQuery (e.target.value)}
placeholder = "Search verses..."
/>
< button onClick = {() => handleSearch (0)} disabled = { loading } >
Search
</ button >
{ results && (
< div >
< p > Found { results . total } verses </ p >
{ results . verses . map ( verse => (
< div key = {verse. id } >
< strong >{verse. reference } </ strong >
< p >{verse. text } </ p >
</ div >
))}
{ results . verseCount > 0 && results . total > ( page + 1) * 10 && (
< button onClick = { loadMore } > Load More </ button >
)}
</ div >
)}
</ div >
)
}
Error Handling
Returns an empty SearchResponse object with the following default values if the request fails:
{
query : '<original query>' ,
limit : 0 ,
offset : 0 ,
total : 0 ,
verseCount : 0 ,
verses : []
}
Errors are logged to the console.
Search Tips
All keywords in the query must be present in a verse for it to match
Order of keywords does not matter
Use wildcards: * for any character sequence, ? for single characters
The API default limit is 10 results per page
Use the offset parameter to paginate through results
Type Definitions
All server actions use types imported from @/types/responses. Key types include:
BibleSummary - Summary information about a Bible translation
Book - Book information with optional chapters
Chapter - Full chapter content with verses
SearchResponse - Search results with matching verses
SearchVerse - Individual verse in search results
Language - Language information
ChapterSummary - Basic chapter metadata
For complete type definitions, refer to /home/daytona/workspace/source/src/types/responses.ts:1.