A Grid / List toggle beside the sort and tag filters. List is one compact row per study (small book cover, title with Rename, passage, tags, date, Resume and Delete). The choice is remembered on the device. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Bible Study App
A self-hosted Bible study tool with notes, projects, and user accounts.
Requirements
- Node.js v18 or higher — nodejs.org
- npm (bundled with Node.js)
- GCC / make (only needed for production/server installs — required to build the
better-sqlite3native module)
Quick Start
git clone https://github.com/nmemmert/study-bible-project.git
cd study-bible-project
bash setup.sh
setup.sh installs dependencies, builds the optimized frontend, and runs one
production server (frontend + API) on http://localhost:5173. Set APP_PORT
to use a different port. If the build fails, the previously running server is
left untouched. bash restart.sh pulls the latest code and does the same.
Stop / logs:
kill $(cat .api.pid)
tail -f .api.log
Development mode (hot reload)
bash setup.sh --dev
Starts the API on http://localhost:3001 and the Vite dev server on http://localhost:5173. Dev mode is much slower, so don't use it for real users.
Optional keys (set in .env or the environment)
| Variable | What it turns on |
|---|---|
SESSION_SECRET |
A long random string that signs login cookies. Optional: if unset in production, the server makes one and keeps it in DATA_DIR/.session-secret. |
ADMIN_EMAIL |
The one admin account. |
ESV_API_KEY, API_BIBLE_KEY |
ESV, NLT, CSB and NASB in the Reader. |
IQBIBLE_API_KEY |
IQ Bible: more commentaries, lexicons (BDB, LSJ, Abbott-Smith), places, topics, people, textual notes, Gospel parallels, daily verse and Spurgeon devotional, plan calendar export, more audio narrations, and background for podcast prompts. Hidden when unset. |
IQBIBLE_CACHE_HOURS |
Leave unset unless IQ Bible has given written permission to cache non-verse data; only verse/chapter text is cached by default (24h), as their terms require. |
BACKUP_KEEP, BACKUP_DISABLED=1 |
The server saves a snapshot of the whole database once a day to DATA_DIR/backups (default: keep 7). Restore with scripts/restore-data.sh. |
ALLOW_PRIVATE_NTFY=1 |
Lets reading reminders use an ntfy server on your own network (blocked by default). |
Production Install (Ubuntu / systemd)
Installs the app as a persistent systemd service under /opt/study-app.
# Install Node.js 20 (if not already installed)
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
# Install build tools (required for better-sqlite3)
sudo apt-get install -y build-essential python3
# Clone and install
git clone https://github.com/nmemmert/study-bible-project.git
cd study-bible-project
sudo bash deploy/install.sh
The installer will:
- Install Node.js dependencies and build the frontend
- Create a
study-appsystem user - Register and start a systemd service
Useful commands after install:
systemctl status study-app # Check service status
journalctl -u study-app -f # Stream logs
systemctl restart study-app # Restart after an update
Open the firewall port (if needed):
sudo ufw allow 3001/tcp
sudo ufw reload
The app listens on port 3001 by default. Set the PORT environment variable in the systemd unit to change it.
Updating (Production)
cd /path/to/study-bible-project
git pull
sudo bash deploy/install.sh
The installer preserves the session secret across updates so logged-in users are not signed out.
Migrating to a New Machine
On the old machine — create a backup:
npm run backup
This creates study-app-backup_<timestamp>.zip in the project root.
On the new machine — restore after cloning and installing:
Development:
npm run restore study-app-backup_<timestamp>.zip
Production (after sudo bash deploy/install.sh completes):
sudo bash scripts/restore-data.sh study-app-backup_<timestamp>.zip --production
See scripts/backup-data.sh and scripts/restore-data.sh for details.
Project Structure
├── server/ # Express API + SQLite database
│ └── data/ # projects.db lives here (gitignored)
├── src/ # React frontend (Vite)
├── deploy/ # systemd service unit + install script
├── scripts/ # backup / restore helpers
└── setup.sh # Development quick-start
License
Private / personal use.
Development
npm run test:run # all tests
npm run lint # ESLint (errors fail; warnings are advice)
Forgotten passwords: the sign-in page's "Forgot your password?" sends a one-time code to the account's ntfy topic (the one used for reading reminders). Accounts without a topic still ask the administrator for a temporary password.