Skip to content
Nicolás Amorosi

Personal project, for churches

WorshipApp

During a service, one person runs the screen: lyrics, a Bible passage, the sermon slides, a video. WorshipApp is the desktop app for that job, with a control window for the operator and a projection window for everyone else.

The problem

WorshipApp was built to replace EasyWorship. It is the third attempt at it: an earlier project, now archived, and a plain-JavaScript version came first.

Constraints

  • Targets Windows; developed on a Mac.
  • Live use: if the projection window closes, it must come back exactly as it was.
  • Offline: everything local, including the Bible text and its search.
  • Sermon slides arrive as PowerPoint files.

What I built

An Electron app with a strict split: the main process owns state and the database, the operator works in a control window, and the projection window is a pure function of the last output it received. Reopen it and the main process replays that output — the screen comes back exactly as it was.

Secure defaults kept on — sandboxed renderers, web security enabled — with local media served through a custom worship:// protocol instead of file:// URLs.

SQLite with Drizzle for songs, service programmes and the RV1960 Bible, with FTS5 full-text search that ignores accents, so typing “senor” finds “Señor”.

The hard parts

Control window

The operator queues songs, passages, slides

Typed IPC contract

Main process

Owns state and SQLite; replays the last output

ProjectionOutput

Projection window

A pure function of the last output

Slides pipeline

  1. .pptx
  2. LibreOffice
  3. PDF
  4. pdf.js
  5. WebP
  6. (Cached by content)
The projection window only renders the last output it received, so it can always be rebuilt. Slides take a detour through LibreOffice and pdf.js.

One typed IPC contract

Every message between processes is declared once, in a single contract type. A missing or mistyped handler doesn’t compile, and errors travel back as a typed result instead of exceptions crossing process boundaries.

PowerPoint without PowerPoint

Automating PowerPoint over COM tied the app to Office. The current pipeline converts .pptx to PDF with headless LibreOffice, renders each page to WebP with pdf.js and caches the result by content — sidestepping the fact that LibreOffice exports only the first slide to PNG. Slide timings and audio are read straight from the presentation’s XML.

Result

  • Version 2.1 in beta, with a Windows installer cross-built from macOS.
  • About 320 automated tests across 24 test files.

The code belongs to the client and stays private. Figures are illustrations with sample data; no real records appear on this page.