What is TJC Service?
TJC Service is a locally-hosted projection system for True Jesus Church services. It displays sermon titles, Bible verses, and hymn lyrics on a projector screen during services. It is based on the open-source Sporeas project and extended with Google Sheets integration for automatic sermon data.
The system runs entirely on your church's local network on a Proxmox VM (CT102). It works offline — all hymns and Bible data are cached locally.
Who is it for?
| Role | Access | What they do |
|---|---|---|
| AV Members | service.tjc.org.au | Select church, control hymns, Bible verses during service |
| Projector screen | /projector.html | Displayed on the projector — no interaction needed |
| Admins | /admin (PIN) | Configure Google Sheets, colour profiles, church list |
Key Features
- 📖 Display sermon titles (English + Chinese) from Google Sheets automatically
- 🎵 Hymn lyrics in English and Chinese with verse-by-verse display
- 📖 Bible verses (NASB + CUVT) with chapter/verse selection
- 🎨 Colour profiles per church (Melbourne warm brown, dark, navy, white)
- ⛪ Per-device church selection — each AV computer remembers its own church
- 🔒 Google Sheets access via Service Account — sheet stays private
- 🌐 Accessible at
service.tjc.org.aufrom any device on the internet
Access URLs
| URL | Purpose | Who |
|---|---|---|
service.tjc.org.au | Main app (control panel) | AV members |
service.tjc.org.au/projector.html | Projector display | Projector screen |
service.tjc.org.au/select-church | Church selection | AV members (first use) |
service.tjc.org.au/admin | Admin panel (PIN required) | Admins only |
service.tjc.org.au/docs | This documentation | Everyone |
service.tjc.org.au/api/sermon | Sermon data API | SermonTitles integration |
First time setup (AV member)
- Open service.tjc.org.au/select-church
- Select your church from the dropdown (e.g. Melbourne)
- Click Continue — your choice is saved on this computer
- You're taken to the main app — sermon data loads automatically
You only need to select your church once per computer. It's saved locally and remembered each visit.
Service day workflow
- Open
service.tjc.org.auon the control laptop - Open
service.tjc.org.au/projector.htmlon the projector display - Verify today's sermon title appears in the Sermon tab
- During service — use Hymns tab for hymn lyrics, Bible tab for verses
- Slides tab for announcements and special slides
Changing your church selection
- Go to service.tjc.org.au/select-church
- Click Clear saved church selection
- Select a different church and click Continue
System Overview
Internet
│
▼
service.tjc.org.au (Cloudflare DNS / Synology reverse proxy)
│
▼
Proxmox CT102 — Ubuntu LXC
├── Python HTTP Server (port 9000)
│ ├── Serves React SPA (index.html + assets)
│ ├── Serves projector.html
│ ├── GET /api/sermon → Google Sheets API
│ ├── GET /api/churches → church list
│ └── POST /api/set-title → localStorage push
│
├── config.json (Sheet ID, column mapping, churches)
├── service-account.json (Google auth — admin only)
└── assets/ (cached JS/CSS/hymn data from CloudFront)
Data Flow — Sermon Auto-fetch
AV computer browser
→ GET /api/sermon?church=Melbourne
→ CT102 server reads config.json (Sheet ID, columns)
→ Server uses service-account.json to get Google OAuth token
→ Calls Google Sheets API v4 (private, authenticated)
→ Finds today's row by date/time
→ Returns: { title, ch_title, speaker, interpreter, hymns }
→ Browser displays in Sermon tab
Offline Capability
All hymn JSON files (1–500) and Bible data are cached locally in /assets/data/ on first load. Once cached, hymns and Bible work without internet. Only sermon data requires internet (Google Sheets API).
Before service
- Turn on projector and set input to the AV computer's HDMI
- Open Chrome/Edge on the AV computer
- Navigate to
service.tjc.org.au - Click Hymns tab — verify hymn numbers match the service sheet
- Click the Projector button — a popup opens showing what displays
- Drag the popup window to the projector screen and maximise it
Always open the projector popup BEFORE moving it to the projector screen. Some browsers block popups — allow them for service.tjc.org.au in browser settings.
During service
| What to display | Where to go |
|---|---|
| Hymn lyrics | Hymns tab → select hymn → click verse |
| Bible verse | Bible tab → select book/chapter/verse |
| Sermon title | Sermon tab → shows automatically |
| Announcements | Slides tab |
| Clear screen | Click the X / blank button |
How church selection works
Each AV computer selects its church independently. The selection is saved in the browser's local storage — it persists between visits and browser restarts, but is specific to that computer and browser.
If you use Chrome on one computer and Edge on another, each browser needs its own church selection.
To select / change your church
- Go to service.tjc.org.au/select-church
- Pick your church from the list
- Click Continue
To clear selection
- Go to service.tjc.org.au/select-church
- Click Clear saved church selection at the bottom
This only clears the church selection — no other data is affected.
Opening the projector
In the app, click the Projector/Output button. A separate popup window opens — this is what goes on the projector. Move it to the second screen and press F11 or maximise it.
If the projector popup closes unexpectedly
- Click the Projector button again in the main app
- If Chrome is blocking popups: click the popup icon in the address bar → Allow
Direct URL option
You can also open the projector directly by navigating to service.tjc.org.au/projector.html in a separate browser window — useful if you want to use a separate device as the projector display.
Accessing the Admin Panel
- Go to
service.tjc.org.au/admin - Enter the Admin PIN (default:
1234— change this immediately)
The PIN is stored per browser. Each admin device needs to set its own PIN. Change the default immediately via Admin → Security tab.
Adding churches
- Admin → Server tab → Churches
- Add each church name exactly as it appears in the Google Sheet tab
- Save — the church appears in the AV member dropdown at
/select-church
Configuring Google Sheets
See the Google Sheets guide.
Uploading service-account.json
- Open Filebrowser at
192.168.178.169:8080(LAN only) - Drag
service-account.jsoninto the app folder - Restart:
systemctl restart tjc-service
Required Google Cloud setup
- Go to Google Cloud Console
- Create a project → Enable Google Sheets API
- IAM → Service Accounts → Create → name it
tjc-service-reader - Keys tab → Add Key → JSON → download the file
- Copy the service account email (ends in
@...iam.gserviceaccount.com) - Share the SermonTitles sheet with that email as Viewer
- Upload
service-account.jsonvia Filebrowser
Sheet column layout
| Column | Field | Example |
|---|---|---|
| A | Date | 27/03/2026 |
| B | Day | Friday |
| C | Time | 8:00 PM-9:00 PM |
| D | Sermon Speaker | Bro. Ferry Teja |
| E | Interpreter | Sis. Yvonne Lim |
| F | Sermon Title (English) | Waiting for God's Timing |
| G | Sermon Title (Chinese) | 等候神的时间 |
| H | Starting Hymn | 3 |
| I | Ending Hymn | 144 |
How sermon matching works
The server reads all rows and finds the one closest to now that is either upcoming or within 3 hours in the past (covers services in progress). If no upcoming service is found, it returns the most recent past service.
Available profiles
| Profile | Global BG | Accent | Panel BG | Used by |
|---|---|---|---|---|
| Melbourne | #534948 (warm brown) | #c7694c (orange) | #d9d9d9 (grey) | Melbourne TJC |
| Dark | #000000 | — | #000000 | Generic dark |
| Navy Blue | #1a2744 | #c9a84c (gold) | #f0f0f0 | — |
| Clean White | #ffffff | #0066cc | #ffffff | — |
Applying a profile
- Go to
/admin→ Display tab - Select a profile card
- Click Apply Profile to App
- The projector screen updates immediately (refresh if needed)
Import your own settings
Export settings from the live service.tjc.org app using their export function, then import the JSON file in Admin → Display → Import.
GET /api/sermon
Returns today's sermon data for a given church.
Query Parameters
| Param | Required | Description |
|---|---|---|
church | No | Church tab name. Falls back to server default if not provided. |
Example Request
GET /api/sermon?church=Melbourne
Example Response
{
"date": "03/04/2026",
"time": "8:00 PM-9:00 PM",
"title": "Waiting for God's Timing",
"ch_title": "等候神的时间",
"speaker": "Bro. Ferry Teja",
"interpreter": "Sis. Yvonne Lim",
"hymns": "3, 144",
"church": "Melbourne"
}
GET /api/churches
Returns the list of configured churches.
{
"churches": ["Melbourne", "Sydney", "Brisbane"]
}
POST /api/set-title
Push sermon data directly to the projection screen.
POST /api/set-title
Content-Type: application/json
{
"title": "Grace of God",
"ch_title": "神的恩典",
"hymns": "123, 456"
}
GET /api/settings
Returns current server configuration (API key masked).
POST /api/settings
Save server configuration.
| Problem | Cause | Fix |
|---|---|---|
| Sermon data not loading | service-account.json missing or wrong | Check Admin → Server tab. Re-upload JSON via Filebrowser. |
| Title is blank | Speaker hasn't entered title in sheet yet | Normal — title shows once entered in the spreadsheet |
| Wrong church loaded | Church selection mismatch | Go to /select-church → Clear → re-select |
| Projector popup closes | Browser blocking popups | Allow popups for service.tjc.org.au in browser settings |
| Hymn not found | Data not cached yet | Need internet for first load. Once cached, works offline. |
| Site not loading | CT102 or Synology offline | Check Proxmox — systemctl status tjc-service |
| Caller does not have permission | Sheet not shared with service account | Share sheet with service account email as Viewer |
Restarting the service
systemctl restart tjc-service
systemctl status tjc-service
Viewing live logs
journalctl -u tjc-service -f
- Added Admin panel at
/adminwith PIN lock - Added Per-device church selection saved to localStorage
- Added Church selector page at
/select-church - Added
GET /api/churchesendpoint for church list - Added
?church=parameter on/api/sermon - Added Colour profiles — Melbourne, Dark, Navy, White
- Added Import/Export settings JSON in admin
- Added This documentation page at
/docs - Changed Settings page renamed to
/admin— hidden from AV members - Changed Google Sheets config now admin-only
- Added Google Sheets API integration via Service Account
- Added
GET /api/sermon— auto-fetch today's sermon by date/time - Added Settings page with Test Connection for Google Sheets
- Added Hymn numbers H and I columns from sheet
- Fixed HTML footer column leaking into hymns field
- Fixed Chinese characters displaying correctly in API response
- Changed
col-hymn-endcorrected to column I (was J)
- Added
projector.htmlserved correctly with own JS bundle - Added CloudFront asset proxy with local caching
- Added Auto-download missing JS chunks on first request
- Added
data/intl/language pack proxy - Fixed Projector popup showing admin panel instead of lyrics
- Fixed
popup-BMzUajQO.jsbundle downloaded and served locally
- Added Initial deployment — service.tjc.org/v1 cloned via HTTrack
- Added Proxmox CT102 LXC container running Ubuntu 22.04
- Added Python HTTP server serving the React SPA locally
- Added Systemd service — auto-starts on boot
- Added
service.tjc.org.auDNS via Cloudflare + Synology reverse proxy - Added Filebrowser at port 8080 (LAN only) for file management
- Added
POST /api/set-titlefor SermonTitles integration