Problem
The Studies section infrastructure currently has significant hard-coding in Python that makes it difficult to expand and maintain:
-
PSALM119_STANZAS duplicated — build_studies.py re-declares all 22 stanzas (letter, name, verse range) even though this information already lives in data/studies/psalm-119/psalm-119-text.yaml. Any change to a stanza requires editing both places.
-
Nav structure hard-coded — _build_psalm119_nav() in build_studies.py hard-codes nav entry titles ("Psalm 119:", "Analysis — Word Vocabulary & Themes", "Memorization Exercises:"). Adding a new analysis page or renaming an entry requires editing Python.
-
Exercise set hard-coded — build_psalm119_memorization.py hard-codes which exercise types to generate (cloze-l1, cloze-l2, verse-order, first-word, reference card, two Anki deck types). If a new exercise type is added or one is disabled for a specific study, the script itself must change.
-
Study discovery hard-coded — build_studies.py has no mechanism for discovering new studies under data/studies/. Adding a second study (e.g., data/studies/psalm-23/) requires manually adding nav-building code.
-
Section index content mixed with code — The section overview page (index.md) is generated entirely in Python, making the layout hard to customize per study without touching the generator.
Recommendation
Adopt the same YAML-over-Python pattern already used by the courses system, where course.yml drives everything build_courses.py generates.
Proposed file structure
data/studies/
studies.yaml ← global registry of all studies
psalm-119/
study.yaml ← per-study config (title, nav, exercise config)
psalm-119-text.yaml ← existing verse data (unchanged)
analysis/
index.md ← hand-authored overview
psalm-23/ ← future study, discovered automatically
study.yaml
psalm-23-text.yaml
studies.yaml — global registry
studies:
- slug: psalm-119
title: "Psalm 119"
corpus: ot
description: "Hebrew memorization and thematic analysis of Psalm 119"
- slug: psalm-23
title: "Psalm 23"
corpus: ot
description: "Hebrew memorization of the Shepherd Psalm"
build_studies.py reads this to know which studies exist and in what order to list them in the nav.
study.yaml — per-study config
# data/studies/psalm-119/study.yaml
title: "Psalm 119"
slug: psalm-119
corpus: ot
description: "..."
nav:
- title: "Analysis — Word Vocabulary & Themes"
path: analysis/psalm-119-report.md
- title: "Memorization Exercises"
path: memorization/index.md
generator: psalm119_memorization # which builder to call
memorization:
source: psalm-119-text.yaml # stanzas already here — no duplication
stanza_key: stanzas # the key in the YAML that holds the list
exercises: # which exercise types to generate
- cloze-l1
- cloze-l2
- verse-order
- first-word
anki_decks:
- vocab
- verse
reference_card: true
Effect on Python code
| Current |
After |
PSALM119_STANZAS list in build_studies.py |
Removed — read from psalm-119-text.yaml via study.yaml |
_build_psalm119_nav() hard-codes nav titles |
Nav titles come from study.yaml nav: block |
build_psalm119_memorization.py has fixed exercise list |
Exercise list comes from study.yaml memorization.exercises |
| No auto-discovery of new studies |
build_studies.py reads studies.yaml |
| Section index generated entirely in Python |
Index template driven by study.yaml metadata |
Implementation steps (suggested order)
- Create
data/studies/studies.yaml — one entry for psalm-119 to start.
- Create
data/studies/psalm-119/study.yaml — nav block + memorization config.
- Update
build_studies.py:
- Read
studies.yaml for discovery.
- Read each
study.yaml for nav titles (eliminate hard-coded strings).
- Derive stanza list from
psalm-119-text.yaml (eliminate PSALM119_STANZAS).
- Update
build_psalm119_memorization.py:
- Accept
study.yaml as input.
- Read exercise list from config rather than hard-coding.
- Add a second study (psalm-23 or another) to validate that the system generalises without any Python changes.
Benefits
- Adding a new psalm or scripture passage for memorization = create
data/studies/<slug>/study.yaml + text YAML, no Python changes.
- Renaming a nav entry = edit
study.yaml, not Python.
- Disabling an exercise for a specific study = set
exercises: in study.yaml.
- The Studies overview page (
studies/index.md) can be auto-generated from studies.yaml, keeping it in sync automatically.
Problem
The Studies section infrastructure currently has significant hard-coding in Python that makes it difficult to expand and maintain:
PSALM119_STANZASduplicated —build_studies.pyre-declares all 22 stanzas (letter, name, verse range) even though this information already lives indata/studies/psalm-119/psalm-119-text.yaml. Any change to a stanza requires editing both places.Nav structure hard-coded —
_build_psalm119_nav()inbuild_studies.pyhard-codes nav entry titles ("Psalm 119:","Analysis — Word Vocabulary & Themes","Memorization Exercises:"). Adding a new analysis page or renaming an entry requires editing Python.Exercise set hard-coded —
build_psalm119_memorization.pyhard-codes which exercise types to generate (cloze-l1, cloze-l2, verse-order, first-word, reference card, two Anki deck types). If a new exercise type is added or one is disabled for a specific study, the script itself must change.Study discovery hard-coded —
build_studies.pyhas no mechanism for discovering new studies underdata/studies/. Adding a second study (e.g.,data/studies/psalm-23/) requires manually adding nav-building code.Section index content mixed with code — The section overview page (index.md) is generated entirely in Python, making the layout hard to customize per study without touching the generator.
Recommendation
Adopt the same YAML-over-Python pattern already used by the courses system, where
course.ymldrives everythingbuild_courses.pygenerates.Proposed file structure
studies.yaml— global registrybuild_studies.pyreads this to know which studies exist and in what order to list them in the nav.study.yaml— per-study configEffect on Python code
PSALM119_STANZASlist inbuild_studies.pypsalm-119-text.yamlviastudy.yaml_build_psalm119_nav()hard-codes nav titlesstudy.yaml nav:blockbuild_psalm119_memorization.pyhas fixed exercise liststudy.yaml memorization.exercisesbuild_studies.pyreadsstudies.yamlstudy.yamlmetadataImplementation steps (suggested order)
data/studies/studies.yaml— one entry for psalm-119 to start.data/studies/psalm-119/study.yaml— nav block + memorization config.build_studies.py:studies.yamlfor discovery.study.yamlfor nav titles (eliminate hard-coded strings).psalm-119-text.yaml(eliminatePSALM119_STANZAS).build_psalm119_memorization.py:study.yamlas input.Benefits
data/studies/<slug>/study.yaml+ text YAML, no Python changes.study.yaml, not Python.exercises:instudy.yaml.studies/index.md) can be auto-generated fromstudies.yaml, keeping it in sync automatically.