Simple BibleGateway Verse Component in React & NextJS

Simple BibleGateway Verse Component in React & NextJS

I recently wanted / needed to speed up how I prepare for teaching lessons on Sundays. What I realized quickly was that I was going to need to build something custom. As part of that build process, I wanted to make sure I was sharing what I built for others to use, in case they find it helpful.

Some Background

I've been teaching intermittently on Sundays for a little over a year now. Over about 17 lessons, I've figured out, out least for myself, it takes about 3-4 hours to prep a lesson.

Here's what my process typically looks like. I've bolded the items that are purely clerical.

  • Open a Google Doc
  • Copy some basic formatting from a previous lesson
  • Intro study of the Scripture I'm covering
  • Starting breaking Scripture into sections. I was generally entering in the OSIS to BibleGateway, then copying the text into my doc
  • Write an engaging, researched Q&A for each section of Scripture
  • Save the Google Doc as a PDF on Google Drive
  • Make the PDF public
  • Save the PDF to my Remarkable
  • Use a free QR code generator to create a QR code that points to the public PDF
  • Validate the QR Code with my phone
  • Open a new Google Doc
  • Paste the QR Code into the Doc
  • Save as a PDF
  • Save the PDF to my Remarkable
  • Print the QR Code

The number of clerical steps seemed to be a bit ridiculous to me, so I decided to see if I could eliminate them.

What I eventually ended up doing was creating the lessons section of this site, which uses:

  • NextJS to statically render MDX
  • A <Verse /> component
  • A <Question /> component
  • Dynamically generated QR codes

This structure gives me a lot of flexibility, which I'll probably go into in another post, but today, I just want to share the <Verse /> React component.

The <Verse /> Component

To keep it simple, I'll show you the usage.

Usage

<Verse verse="Genesis 1:1-3" />

This will output...


No verse yet...

No lookup, copying, pasting, formatting... it just works. Nice.

The Component Code

src/components/Verse.js
import React, { useState, useEffect } from 'react';


export function Verse({ verse = '1 Thessalonians 1:5-6' }) {
  const [content, setContent] = useState(null);

  useEffect(() => {
    (async function fetchVerse() {
      const res = await fetch(`/api/verses?verse=${verse}`,{
        method: 'GET',
      })

      const json = await res.json();

      const { content } = json;

      const slice = /^[0-9]{1}/.test(content[5]) ? 5 : 6;
      const clean = content.slice(slice, content.length - 2).join(' ').replace(/\([a-zA-Z0-9]+\)/gi, '').replace(/\[[a-z]+\]/gi, '').replace(
        'Sign Up For Weekly Updates Sign up now for the latest news and deals from Bible Gateway!',
        ''
      );

      setContent(clean);
    })();
  }, []);

  if (!content) {
    return <>No verse yet...</>
  }

  // This uses Tailwind CSS for the styling
  return (
    <div className="my-4">
      <h2 className="font-semibold tracking-tight">Read {verse}</h2>
      <div className="text-zinc-800 font-light text-sm mt-4 dark:text-zinc-300">
        {content}
      </div>
    </div>
  );
}

export default Verse;

As you can see, it does connect to my local NextJS api, so here is the code for that...

The API Code

To fetch the verse from BibleGateway, I'm using the bible-gateway-api package.

$ yarn add bible-gateway-api

There is some risk with this library, because under the hood, it's really just scraping the HTML from BibleGateway. However, it's been working well for me so far, and since this is a pet project that I only use for teaching classes, I'm not too worried about it.

src/api/verse.js

import { BibleGatewayAPI } from "bible-gateway-api";
 
let bgw = new BibleGatewayAPI();

export default async function handler(req, res) {
  const { verse: verseParam } = req.query;

  if (!verseParam) {
    res.status(400).json({ error: 'No verse provided' });
    return;
  }

  const { verse, content } = await bgw.search(verseParam, 'CSB');

  res.status(200).json({ verse, content })
}

Pretty straight-forward, eh?

Pitfalls

The major pitfalls of this component are:

  1. It doesn't yet support SSG. I will likely be adding that soon, and will post on it when I do. This was a quick fix for teaching lessons, and not a true SEO play.
  2. BibleGateway API changes. Obviously I don't control that codebase, so there's always some chance that my component (or API route, rather) will muck up at some point.
  3. It should probably reference BibleGateway with some link credit. Again, this was a rapid prototype, and I'll probably add that soon.

Still, it's been a huge time-saver so far, and helps me write nice clean lessons in MDX. Here's an excerpt from a recent lesson on John 4:

example.mdx

<Verse verse="John 4:1-7" />
<Question>Traditionally, all of the women in a town or village would go to draw water together early in the morning.  John tells us that the woman was by herself, and that it was mid-day (or about noon).  Why do you think this was?</Question>
<Question>It sounds like Jesus is barking an order a bit.  If we examine more closely, what has John established that helps us paint a clearer picture?  What picture is that?</Question>

<Verse verse="John 4:9" />
<Question>What is the woman’s posture right here?  What do you think she might be thinking, especially given her life circumstances, and how her community probably views her?</Question>

<Verse verse="John 4:10" />
<Question>What is Jesus saying here?  What is the gift of God?  Why doesn’t the Samaritan woman know it?</Question>
<Question>What are Jesus’ implications with the phrase “he would give you”?</Question>

Stay tuned for more posts on how I put this together!

If you enjoyed this article, please consider following me on Twitter

Subscribe to the Newsletter

Subscribe for exclusive tips, strategies, and resources to launch, grow, & build your SaaS team.

Share this article on: