Rethinking Liturgical Documentation

Oct 1, 2018 min read

Introduction

In the heart of our community’s spiritual life lies the tradition of choral and congregational participation, guided by our cherished liturgy books. However, the physical limitations of these books, assembled with traditional cut-and-paste methods, posed a significant challenge to their adaptation and evolution. Recognizing the need for a more dynamic and accessible approach, we embarked on a transformative project to digitize and streamline the creation and maintenance of our liturgical content.

Leadership Role

As the project manager, I was privileged to lead this innovative venture, acting as a bridge between the vision of our church leaders and the technical execution by our dedicated team. My role encompassed clear communication with our priest and choir director to ensure alignment with their expectations, overseeing the project’s development phases, and spearheading solutions that catered to both technical efficiency and spiritual integrity.

Product Development Journey

The objective was clear: convert our liturgy books into a flexible digital format that could be easily updated, shared, and adapted. This required not just a technological transition but a cultural shift within our community towards embracing digital solutions.

Finding the Right Tools

After thorough research and consideration, we chose an integration of git for version control, LaTeX for document preparation, and LilyPond for music notation as our primary tools. This combination offered us flexibility, precision in formatting text and musical scores alike, and an open-source foundation that ensured accessibility for all project contributors.

Team Collaboration

Our project team was composed of individuals with diverse skills including a reviewer who ensured theological accuracy, an editor who refined content readability, and a secondary developer who supported in scripting complex layouts. My role extended into being both a LaTeX developer crafting the document structure; ensuring it met both aesthetic standards and usability criteria; as well as serving as an IT consultant navigating technical challenges.

Challenges & Solutions

One significant challenge was onboarding team members unfamiliar with git workflows or LaTeX coding. To address this, I organized training sessions focused on collaborative practices in git along with basic LaTeX tutorials tailored to non-technical users. This not only empowered team members but also fostered a culture of learning within our church community.

Another hurdle was integrating textual content with musical notation seamlessly within documents. Through iterative testing and customization in LilyPond scripts alongside LaTeX templates, we achieved a harmonious blend that preserved the beauty of our liturgical music while enhancing readability.

Impact & Reflections

The result was transformative: A digital liturgy book that can be continuously updated without gatekeeping barriers. It has significantly reduced preparation time for services while allowing for real-time updates reflecting liturgical changes or special occasions.

This project underscored the importance of leadership in product development - not just directing tasks but inspiring innovation through finding the right tools for unique challenges. It demonstrated how technology can serve tradition by making it more accessible without compromising its essence.

In retrospect, this journey has been about more than just creating a document; it’s been about nurturing adaptability within our spiritual community. As we move forward, this framework will serve not only as a testament to what we have accomplished but also as a foundation for future innovations in how we share our faith.

Project Structure

The project was structured as a latex document with each section of the liturgy in its own file. The main file was a book class document that included all the sections. The sections were written in latex and lilypond, and the lilypond files were included in the latex files. The lilypond files were compiled into midi files and pdfs. The pdfs were included in the latex document. The latex document was compiled into a pdf. The pdf was then printed and bound into a book for the choir and a booklet for the congregation.

File Structure

Lityrgy.lytex

The main file that includes all the sections. It also includes the cover and the order of the service.

% This document is the main lytex file. To compile, you will need lilypond
% Run the make file (or bat file) to automatically compile the PDF into the output folder
% This file only defines the order of the service. Each section is in its own file

\documentclass[12pt,twoside]{book}
\usepackage[letterpaper,margin=1in,heightrounded]{geometry}
% pull in the file with all the additional packages and custom commands
\usepackage{styles/liturgy}

% start the document
\begin{document}

\pagestyle{headings}

\input{./text/cover.lytex}
\setcounter{page}{1}

\chapterhead{Divine Liturgy}

% each section is its own little file. Include them like this
% \input{./text/name_of_section.lytex}

\input{./text/opening.lytex}

% ... more sections ...

\end{document}

Makefile

The makefile is used to compile the latex and lilypond files into pdfs and midi files. It also includes a docker command to run the makefile in a docker container since the lilypond version on each participant’s computer was not guaranteed to be the same.


FILEBASE="liturgy"
PATH := /Library/TeX/texbin/:/Applications/LilyPond.app/Contents/Resources/bin/:$(PATH)
SHELL := /bin/bash
WORKDIR=$(dir $(realpath $(firstword $(MAKEFILE_LIST))))
OUTDIR=$(WORKDIR)/output
LATEX=xelatex
TEMPDIR="$(WORKDIR)/LilyPondTemp"
MIDIZIP=$(OUTDIR)/$(FILEBASE)-midi.zip
CHOIR_FILE="$(FILEBASE)-choir"
CONGREGATION_FILE="$(FILEBASE)-congregation"
CONGREGATION_BOOKLET="print_congregation_booklet"
KLIORS_BOOKLET="print_kliros_booklet"
DOCKERIMAGE="tsunaminoai/lilypond"
MUSICFILE?=*.ly

VARFILE="vars.tex"

.PHONY: midi clean

all: check choir congregation midi booklet

pdf: check choir congregation booklet

music: check midi

dockerpull:
	docker pull $(DOCKERIMAGE)

docker: dockerpull
	docker run -it --rm -v "$(WORKDIR)":/srv/build $(DOCKERIMAGE) make pdf

dockermusic: dockerpull
	docker run -it --rm -v "$(WORKDIR)":/srv/build $(DOCKERIMAGE) make MUSICFILE="$(MUSICFILE)" music 

check:
	chktex -W
	chktex -q -n 6 *.lytex 2>/dev/null| tee lint.out
	chktex -q -n 6 text/*.lytex 2>/dev/null | tee -a lint.out
	test ! -s lint.out || (echo 'LaTeX did not pass lint. Check lint.out: '; cat lint.out; exit 1)


congregation:
	@echo "Building congregation version with LilyPond in $(WORKDIR)";
	echo "\setboolean{congregation}{true} \setboolean{kliros}{false}" > "$(WORKDIR)/$(VARFILE)";
	lilypond-book --pdf --format=latex --output "$(TEMPDIR)" "$(FILEBASE).lytex" ;
	@echo "Moving to temp environment";
	mkdir -p "$(TEMPDIR)/styles/";
	cp "$(WORKDIR)/styles/liturgy.sty" "$(TEMPDIR)/styles/";
	cp "$(WORKDIR)/$(VARFILE)" "$(TEMPDIR)/$(VARFILE)"

	@echo "Running LaTeX on LilyPond output";
	#runs twice to resolve references
	#dont remove this non-linebreak n stuff and things
	cd "$(TEMPDIR)";\
	$(LATEX) "$(FILEBASE).tex" ;\
	$(LATEX) "$(FILEBASE).tex" ;
	mkdir -p "$(OUTDIR)";
	cp "$(TEMPDIR)/$(FILEBASE).pdf" "$(OUTDIR)/$(CONGREGATION_FILE).pdf";
	rm $(VARFILE)
	@echo "Build complete. Final PDF located at $(OUTDIR)/$(CONGREGATION_FILE).pdf";

choir:

	@echo "Building choir version with LilyPond in $(WORKDIR)";
	echo "\setboolean{congregation}{false} \setboolean{kliros}{true}" > "$(WORKDIR)/$(VARFILE)";
	lilypond-book --pdf --format=latex --output "$(TEMPDIR)" "$(FILEBASE).lytex" ;
	@echo "Moving to temp environment";
	mkdir -p "$(TEMPDIR)/styles/";
	cp "$(WORKDIR)/styles/liturgy.sty" "$(TEMPDIR)/styles/";
	cp "$(WORKDIR)/$(VARFILE)" "$(TEMPDIR)/$(VARFILE)"

	@echo "Running LaTeX on LilyPond output";
	#runs twice to resolve references
	#dont remove this non-linebreak n stuff and things
	cd "$(TEMPDIR)";\
	$(LATEX) "$(FILEBASE).tex" ;\
	$(LATEX) "$(FILEBASE).tex" ;
	mkdir -p "$(OUTDIR)";
	cp "$(TEMPDIR)/$(FILEBASE).pdf" "$(OUTDIR)/$(CHOIR_FILE).pdf";
	rm $(VARFILE)
	@echo "Build complete. Final PDF located at $(OUTDIR)/$(CHOIR_FILE).pdf";


midi:
	@echo "Building MIDI output";
	mkdir -p "$(OUTDIR)/midi";
	declare -a types=(" " "soprano" "alto" "tenor" "bass"); 
	ls hymns/$(MUSICFILE) | grep -vE "preamble|single-staff|one-staff|two-staves|defines" | \
	while read i; do \
		filename=$${i##*/}; \
		songname=$${filename%.ly}; \
		lilypond -dmidi-extension="mid" "$$i"; \
		mkdir -p "$(OUTDIR)/midi/$$songname"; \
		for x in $$(seq 1 4); do\
			mv -f "$$songname-$$x.mid" "$(OUTDIR)/midi/$$songname/$$songname-$${types[$$x]}.mid";\
		done;\
		mv -f "$$songname.mid" "$(OUTDIR)/midi/$$songname/"; \
		rm -f *.mid *.pdf; \
	done ;

	zip -rj "$(MIDIZIP)" "$(OUTDIR)/midi"

booklet: check congregation
	cp "$(WORKDIR)/$(CONGREGATION_BOOKLET).lytex" "$(TEMPDIR)"
	cd "$(TEMPDIR)";\
	$(LATEX) "$(CONGREGATION_BOOKLET).lytex" ;
	cp "$(TEMPDIR)/$(CONGREGATION_BOOKLET).pdf" "$(OUTDIR)";


clean:
	rm -rf "$(WORKDIR)/LilyPondTemp"
	rm -f lint.out
	rm -rf "$(OUTDIR)/midi"
	rm -f "$(OUTDIR)"/*
\documentclass{scrartcl}
\usepackage{pdfpages}
\usepackage[paperheight=14in,paperwidth=8.5in,margin=1in,heightrounded]{geometry}
\begin{document}
\includepdf[pages=-,booklet,turn=false,landscape]{../output/liturgy-congregation.pdf}
\end{document}

Liturgy.sty

The file with all the additional packages and custom commands for styling the document according to the church’s requirements.

% chktex-file 1
\nonstopmode %die on error

\usepackage{ucs}
\usepackage[utf8x]{inputenc} \usepackage{palatino}
\usepackage{hyperref}
\usepackage[T1]{fontenc}
\usepackage{subfiles}
\usepackage{pifont}
\usepackage{fontawesome}
\usepackage{marvosym}
\usepackage{geometry}
\usepackage{marginnote}
\usepackage[usenames, dvipsnames]{xcolor}
\usepackage{ifthen}
\usepackage[object=vectorian]{pgfornament}
\usetikzlibrary{calc}
\usepackage{fancyhdr}
\usepackage{tabularx} %for tables
\usepackage{etoolbox}

\newlength\tindent
\setlength{\tindent}{\parindent}

\raggedbottom
\vfuzz          2pt
\headheight     0.1in
\headsep        0.4in
\textheight     9.2in
\oddsidemargin  0.2in
\evensidemargin -0.2in
\leftmargini    0.5in % For quote sections
\textwidth      6.5in
\parindent      0.0in
\pagestyle{empty}

\def\prayer{\list{}{\rightmargin1in\leftmargin1in}\item[]}
\let\endprayer=\endlist

\renewcommand{\indent}{\hspace*{\tindent}}

\fancypagestyle{plain}{%
  \fancyhf{} % clear all header and footer fields
  \fancyhead[RO,RE]{\thepage} %RO=right odd, RE=right even
  \renewcommand{\headrulewidth}{0pt}
  \renewcommand{\footrulewidth}{0pt}
}

\makeatletter
\patchcmd{\@mn@margintest}{\@tempswafalse}{\@tempswatrue}{}{}
\patchcmd{\@mn@margintest}{\@tempswafalse}{\@tempswatrue}{}{}
\reversemarginpar
\makeatother

\newboolean{kliros}
\newboolean{congregation}
\InputIfFileExists{vars}{}{}

\newcommand\klirosbreak{%
  \ifthenelse{\boolean{kliros}}{\newpage}{}%
}

\newcommand\congbreak{%
  \ifthenelse{\boolean{congregation}}{\newpage}{}%
}

\newcommand\congnote[1]{%
  \ifthenelse{\boolean{congregation}}{%
  \begin{center}\small{\textit{\color{Red}#1}}\end{center}%
  }{}%
}

\newcommand\topalign[1]{%
  \setbox0\hbox{#1}%
  \raisebox{\dimexpr-\ht0+\dp0\relax}{\usebox0}}

\newcommand{\betweenLilyPondSystem}[1]{\\[3mm]}

\newcommand{\chapterhead}[1]{\par\penalty-700
  \begin{center}{\Huge \bf #1}\end{center}\nopagebreak[0]
}

\newcommand{\sectionhead}[1]{\par\penalty-700
  \begin{center}{\Large \bf #1}\end{center}\nopagebreak[0]
}

\newcommand{\parahead}[1]{\begin{center}{\large \bf #1}\end{center}}

\newcommand{\priest}[2][normal]{
  \par\penalty-700%
  \strut\reversemarginpar\marginnote{\bf\color{red}{\ding{62}}}%
  \nopagebreak[0]%
  \ifthenelse{\equal{\detokenize{#1}}{\detokenize{quiet}}}
  {\textit{\color{Gray}{(Quietly) #2}} \\ }
  {\color{Black}{#2}   \\  }
}

\newcommand{\deacon}[2][normal]{
  \par\penalty-700%
  \strut\reversemarginpar \marginnote{\bf\color{red}{\ding{61}}}%
  \nopagebreak[0]%
  \ifthenelse{\equal{\detokenize{#1}}{\detokenize{quiet}}}
  {\textit{\color{Gray}{(Quietly) #2}} \\ }
  {\color{Black}{#2}   \\  }
}

\newcommand{\choir}[1]{
  \par\penalty-999%
  \reversemarginpar\marginnote{\bf\color{red}{\ding{64}}}\nopagebreak[0] #1  \\ }

\newcommand{\reader}[1]{\strut\reversemarginpar\marginnote{\bf\color{red}{\footnotesize\faBook}} #1  \\ }

\newcommand{\instruction}[1]{\textit{#1}  \\ }

\newcommand{\litverse}[1]{\vspace*{-3mm}\begin{verse}\small
\textit{\textbf{v.} #1}
\end{verse}
%\vspace*{3mm}
}

\newcommand{\signofthecross}{\ding{64}}

\newcommand{\separator}{%
  {\par\noindent
  \begin{tikzpicture}\def\mylen{3cm}
    \coordinate (A) at (0,0);
    \coordinate (C) at (\mylen,0);
    \coordinate (B) at (\textwidth,0);
    \coordinate (D) at ($(\textwidth,0)-(\mylen,0)$);
    \draw[line width=1.75pt,line cap=rect] ($(A)+.5*(1.15pt,0)$) -- (C) (D) -- ($(B)-.5*(1.15pt,0)$);
    \path (C) to[ornament=88, options/.append style={yshift=.9pt}] (D);
    \end{tikzpicture}}
  }

Text Files

Each section of the liturgy was in its own file. The files were written in latex and lilypond. The lilypond files were included in the latex files.

\sectionhead{The Epistle}

\deacon{Wisdom!}

\reader{The reading is from \textit{(the title of the prescribed Epistle is chanted by the Cantor or Reader)}}

\deacon{Let us attend!}

\instruction{The Epistle is chanted.}

\priest{Peace be to you that read.}

\reader{And to your spirit. Alleluia! Alleluia! Alleluia!}

\instruction{The people stand. The reader chants the two Alleluia Verses. After each one, the choir repeats the Alleluia. The deacon censes the people, then stands next to the priest.}

\choir{\lilypondfile{hymns/alleluia_alleluia_alleluia.ly}}

Hymns

The hymns were written in lilypond and included in the latex files.

\version "2.12.0"
\include "hymns/defines.ly"
#(define myNoteSpacing 5.0)
\include "hymns/preamble.ly"

global = {
  \globalPreamble
  \key f \major
  \override Staff.TimeSignature #'stencil = #ly:text-interface::print
  \override Staff.TimeSignature #'text = ""
}

womenWords = \lyricmode {
  Al -- le -- lu -- i -- a! 
  Al -- le -- lu -- i -- a! 
  Al -- le -- lu -- i -- a! 
}


sopMusic =  \relative {
  \cadenzaOn
  f'4 g a2 (g8 [f]) e ([g]) f2 \bar "|"
  a4 bes c2 (bes8 [a]) g ([bes]) a2 \bar "|"
  f4 g a8 ([bes a g f e]) d ([e]) f1 \bar "|."
}

altoMusic = \relative {

}


\include "hymns/one-staff.ly"
\version "2.12.0"
\include "hymns/defines.ly"
#(define myNoteSpacing 5.0)
\include "hymns/preamble.ly"

global = {
  \globalPreamble
  \key f \major
  \override Staff.TimeSignature #'stencil = #ly:text-interface::print
  \override Staff.TimeSignature #'text = ""
}

womenWords = \lyricmode {
    A -- men
}

menWords = {}

sopMusic =  \relative {
  \cadenzaOn
    a'2 a1 \bar "|."
}

altoMusic = \relative {
    f'2 f1
}

tenorMusic = \relative {
    c'2 c1
}

bassMusic = \relative {
    f2 f1
}

\include "hymns/two-staves.ly"

Output

The output was a pdf that was printed and bound into a book for the choir and a booklet for the congregation.

Example of the output for the choir

Example of the output for the choir

Example of the output for the congregation

Example of the output for the congregation