|
1 | 1 | # Prayer Collection Development Guide |
2 | 2 |
|
3 | 3 | ## Project Overview |
4 | | -This is an NPM package providing structured Catholic prayers as JSON files with multilingual support. The project follows a category-based architecture with strict data validation and TypeScript definitions. |
| 4 | +NPM package providing traditional Catholic prayers as structured JSON files with multilingual support and static data compilation for universal compatibility (Node.js + browsers). |
5 | 5 |
|
6 | | -## Core Architecture |
| 6 | +## Critical Architecture Patterns |
7 | 7 |
|
8 | | -### Data Structure |
9 | | -- **Flat File Structure**: All prayers in single `prayers/` directory as `prayer-name.json` |
10 | | -- **Multi-Label Classification**: Rich metadata with primary category + multiple labels |
11 | | - - `primary_category`: Main theological focus ("marian", "christological", "saints") |
12 | | - - `labels`: Array of classifications (["core", "essential", "rosary", "daily"]) |
13 | | - - `importance`: Liturgical significance ("essential", "common", "devotional") |
14 | | -- **Multilingual**: Each prayer supports 8 languages (la, en, es, fr, de, it, pt, pl) with required translations |
15 | | -- **Metadata-driven**: Rich metadata includes origin dates, usage contexts, feast days, and devotions |
| 8 | +### Static Data Compilation (Universal Compatibility) |
| 9 | +**WHY**: Enables browser usage without filesystem operations - critical differentiator from typical JSON packages |
16 | 10 |
|
17 | | -### Static Data Compilation |
18 | | -- **Universal Compatibility**: Pre-compiled static data for Node.js + browser environments |
19 | | -- **No Runtime File I/O**: All JSON files compiled into `lib/prayer-data.js` during build |
20 | | -- **Bundler Friendly**: Works with Webpack, Vite, Rollup, Parcel without special configuration |
| 11 | +**Build Flow**: |
| 12 | +1. `scripts/generate-static-data.js` → Imports all JSON files, generates `lib/prayer-data.js` module |
| 13 | +2. `scripts/build.js` → Validates structure, creates `lib/prayer-index.json` + `lib/build-report.json` |
| 14 | +3. `index.js` → Imports from `lib/prayer-data.js` (NOT directly from `prayers/` directory) |
| 15 | + |
| 16 | +**Implication**: Never use `require('./prayers/some-prayer.json')` in runtime code. All prayer data MUST flow through the build pipeline. |
| 17 | + |
| 18 | +### Flat File Structure with Multi-Label Classification |
| 19 | +**Structure**: All prayers in single `prayers/` directory as `prayers/prayer-id.json` (no subdirectories) |
| 20 | + |
| 21 | +**Classification System** (see `prayers/our-father.json` example): |
| 22 | +- `primary_category`: Fixed theological enum ("marian", "christological", "saints", etc.) |
| 23 | +- `labels`: Free-form array (kebab-case) - MUST include `primary_category` |
| 24 | +- `importance`: Liturgical weight ("essential", "common", "devotional") |
| 25 | + |
| 26 | +**Example**: `prayers/chaplet-of-divine-mercy.json` has `primary_category: "devotional"` and `labels: ["devotional", "mercy", "chaplet", "common"]` |
| 27 | + |
| 28 | +### Content Structure for Complex Prayers |
| 29 | +**Simple prayers** use `text` field: `{ "la": { "text": "Pater noster..." } }` |
| 30 | + |
| 31 | +**Complex prayers** (chaplets, rosaries) use `content` array to reference other prayers: |
| 32 | +```json |
| 33 | +{ |
| 34 | + "content": [ |
| 35 | + { "type": "instructions", "value": "Opening prayers:" }, |
| 36 | + { "type": "prayer-reference", "value": "our-father" }, |
| 37 | + { "type": "prayer-reference", "value": "hail-mary", "count": 3 }, |
| 38 | + { "type": "text", "value": "Glory be to the Father..." } |
| 39 | + ] |
| 40 | +} |
| 41 | +``` |
| 42 | + |
| 43 | +**getPrayerText()** function (lines 120-160 in `index.js`) recursively resolves references and assembles full text. |
21 | 44 |
|
22 | 45 | ## Development Workflows |
23 | 46 |
|
24 | 47 | ### Adding New Prayers |
25 | | -1. **JSON Structure**: Copy existing prayer JSON, ensure `id` matches filename (kebab-case) |
26 | | -2. **Label Classification**: Set `primary_category` and add appropriate `labels` array |
27 | | -3. **Required Fields**: All metadata fields are mandatory, especially `origin_date` (use ISO 8601 ranges like "0030/0033") |
28 | | -4. **Language Coverage**: Include all 8 supported languages; partial translations trigger warnings |
29 | | - |
30 | | -### Build System Commands |
| 48 | +1. **Create JSON**: `prayers/new-prayer-id.json` (filename MUST match `metadata.id`) |
| 49 | +2. **Copy Template**: Use `prayers/our-father.json` as base structure |
| 50 | +3. **Required Metadata**: All 14 metadata fields mandatory (see `prayer-schema.json` lines 11-29) |
| 51 | +4. **Origin Dates**: ISO 8601 format - use ranges for uncertainty ("1050/1150"), prefix "~" for approximation ("~1200") |
| 52 | +5. **Translations**: 8 languages required (la, en, es, fr, de, it, pt, pl) - missing translations generate warnings, not errors |
| 53 | +6. **Validate**: Run `npm run build` - must pass to publish |
| 54 | + |
| 55 | +### Validation Chain |
| 56 | +**Two validation modes**: |
| 57 | +- `npm run validate` - Custom validation (zero dependencies, always available) |
| 58 | +- `npm run validate:schema` - JSON Schema validation (requires `ajv` dev dependency, more detailed errors) |
| 59 | + |
| 60 | +**Critical Rules** (enforced in `scripts/validate.js` lines 47-69): |
| 61 | +- Filename matches `metadata.id` exactly |
| 62 | +- `primary_category` appears in `labels` array (warning if missing) |
| 63 | +- `labels` array not empty |
| 64 | +- Required languages (la, en) must have `text` OR `content` field |
| 65 | +- No duplicate prayer IDs across all files |
| 66 | + |
| 67 | +### Build Commands Critical Path |
31 | 68 | ```bash |
32 | | -npm run build # Generates static data + validates JSONs, creates lib/build-report.json |
33 | | -npm run validate # Comprehensive validation with detailed error reporting |
34 | | -npm test # Runs API function tests |
35 | | -npm run test:browser # Tests browser compatibility |
36 | | -npm run prepublishOnly # Auto-runs build + validate before publishing |
| 69 | +npm run build # 1. Generate static data 2. Validate 3. Create build-report.json |
| 70 | +npm run validate # Standalone validation (run after any JSON edit) |
| 71 | +npm test # API function tests (uses lib/prayer-data.js) |
| 72 | +npm run test:browser # Browser compatibility tests |
| 73 | +npm run prepublishOnly # AUTO-RUNS on `npm publish` - build + validate MUST pass |
37 | 74 | ``` |
38 | 75 |
|
39 | | -### Git Workflow |
40 | | -To maintain code quality and minimize risk: |
| 76 | +**Pre-publish Hook**: `package.json` line 19 - `npm publish` blocked if validation fails |
41 | 77 |
|
42 | | -1. **Branching**: Always create a feature branch for new work (`git checkout -b feature/add-new-prayer`) |
43 | | -2. **Incremental Commits**: Make frequent, small commits during development to capture progress and enable easy rollbacks |
44 | | -3. **Validation**: Run `npm run validate` and `npm test` before each commit |
45 | | -4. **Merge Strategy**: When work is complete, merge back to main with squash commits if the branch has many small commits |
46 | | -5. **Push**: Push feature branches to origin for backup and collaboration |
| 78 | +## API Patterns |
47 | 79 |
|
48 | | -## Code Patterns |
| 80 | +### Functional API Design (index.js) |
| 81 | +**Immutability**: All functions return copies (`[...ALL_PRAYERS]`, `{ ...PRAYERS[id] }`) - prevent mutations |
| 82 | +**Graceful Degradation**: Returns `null` for missing data, never throws on valid input |
| 83 | +**Pre-indexed Data**: Static lookups via `PRAYERS_BY_CATEGORY`, `PRAYERS_BY_LABEL` (built at compile time) |
49 | 84 |
|
50 | | -### API Design Philosophy |
51 | | -- **Functional API**: All exports are pure functions (`getPrayerById`, `getPrayersByCategory`) |
52 | | -- **Graceful Degradation**: Returns `null` for missing prayers, throws errors only for invalid categories |
53 | | -- **Type Safety**: Full TypeScript definitions in `index.d.ts` with `Prayer`, `PrayerMetadata` interfaces |
54 | | - |
55 | | -### Data Validation Rules |
56 | | -- **Filename Convention**: JSON filename must match `metadata.id` exactly |
57 | | -- **Label Validation**: `primary_category` should match one label in `labels` array |
58 | | -- **Date Formats**: Use ISO 8601, ranges for uncertain dates ("1050/1150"), approximate with "~" prefix |
59 | | -- **Language Codes**: ISO 639-1 standard (la, en, es, fr, de, it, pt, pl) |
| 85 | +**Example**: |
| 86 | +```javascript |
| 87 | +getPrayersByLabel('rosary') // Returns pre-indexed array from PRAYERS_BY_LABEL |
| 88 | +getPrayerById('invalid-id') // Returns null, not error |
| 89 | +getPrayerText('hail-mary', 'en', true) // skipOptional=true for nested references |
| 90 | +``` |
60 | 91 |
|
61 | | -### Common Gotchas |
62 | | -- **Label Consistency**: Ensure `primary_category` appears in `labels` array |
63 | | -- **Missing Translations**: Warnings (not errors) for incomplete language coverage |
64 | | -- **ID Conflicts**: Build fails if multiple prayers share same ID |
65 | | -- **JSON Syntax**: Any malformed JSON breaks validation |
| 92 | +### TypeScript Integration |
| 93 | +`index.d.ts` defines `Prayer`, `PrayerMetadata`, `Translation`, `LanguageCode` types |
| 94 | +No runtime overhead - pure type hints for consumers |
66 | 95 |
|
67 | | -## Integration Points |
| 96 | +## Common Gotchas |
68 | 97 |
|
69 | | -### NPM Package Structure |
70 | | -- **Entry Point**: `index.js` provides runtime API, `index.d.ts` for TypeScript |
71 | | -- **Distribution**: Only `prayers/`, `lib/`, `index.*` files included via `package.json` files field |
72 | | -- **Pre-publish**: `prepublishOnly` hook runs build + validation automatically |
| 98 | +1. **Label Consistency**: Forgetting to include `primary_category` in `labels` array triggers warning |
| 99 | +2. **Content vs Text**: Complex prayers need `content` array with `prayer-reference` types - can't use simple `text` |
| 100 | +3. **Date Ranges**: Uncertain dates require forward slash separator ("1050/1150"), not dash |
| 101 | +4. **Build Before Test**: Tests import from `lib/prayer-data.js` - must run `npm run build` after JSON changes |
| 102 | +5. **ID Filename Mismatch**: `prayers/hail-mary.json` with `"id": "hail-mary-prayer"` fails validation |
73 | 103 |
|
74 | | -### External Dependencies |
75 | | -- **Zero Runtime Dependencies**: Pure Node.js fs/path modules only |
76 | | -- **Build Dependencies**: Node.js >=12.0.0 required for scripts |
77 | | -- **Validation Logic**: Custom validation in `scripts/validate.js`, not using external schema validators |
| 104 | +## Sacred Content Guidelines |
| 105 | +These are liturgical Catholic prayers - maintain theological accuracy and use established translations. See `CONTRIBUTING.md` for full guidelines on respectful contribution. |
78 | 106 |
|
79 | | -When working on this codebase, always run `npm run validate` after JSON changes and understand that the build system is central to data integrity - all prayers must pass validation to publish. |
| 107 | +## File Dependencies |
| 108 | +- **Runtime**: `index.js` → `lib/prayer-data.js` (generated) |
| 109 | +- **Build**: `scripts/build.js` → calls `scripts/generate-static-data.js` |
| 110 | +- **Validation**: `scripts/validate.js` (standalone) OR `scripts/validate-with-schema.js` (uses `prayer-schema.json`) |
| 111 | +- **Distribution**: Only `prayers/`, `lib/`, `index.js`, `index.d.ts` published (see `package.json` files field) |
0 commit comments