| name | reading-plan-designer |
| description | Design and implement Bible reading plans for the KR92 Bible Voice project.
Use for: creating reading plans (7-day/30-day/yearly), adding daily readings,
generating reading-plan SQL migrations, the reading-plan data model,
designing sequences (chronological/topical/book-based), and validating
reading reference formats.
Triggers: "reading plan", "lukusuunnitelma", "daily readings", "create plan", "add readings"
|
Reading Plan Designer
Design Bible reading plans with proper data structure and daily reading assignments.
CRITICAL: bible_schema Usage
All reading plan tables and RPC functions reside in bible_schema, NOT public.
Supabase Client Queries
const { data } = await supabase.rpc("get_user_reading_plans", { ... });
const { data } = await (supabase as any)
.schema("bible_schema")
.rpc("get_user_reading_plans", { ... });
const { data } = await supabase.from("reading_plans").select("*");
const { data } = await (supabase as any)
.schema("bible_schema")
.from("reading_plans")
.select("*");
SQL Migrations
Always prefix table names with bible_schema. in migrations:
INSERT INTO reading_plans ...
INSERT INTO bible_schema.reading_plans ...
Context Files (Read First)
Docs/context/db-schema-short.md - Database tables overview
Docs/context/supabase-map.md - RPC functions for reading plans
Quick Start: Generate a Plan
Use the bundled script to auto-generate plans with SQL migrations:
python scripts/fetch_reading_plan.py --generate --book John --days 21 --sql -o john.json
python scripts/fetch_reading_plan.py --generate --sections NT --days 90 --sql -o nt90.json
python scripts/fetch_reading_plan.py --generate --sections OT+NT --days 365 --sql -o yearly.json
python scripts/fetch_reading_plan.py --generate --book Psalms --days 30 --sql -o psalms30.json
The script outputs:
- JSON file with plan structure
- SQL migration file (with
--sql flag)
- Summary with day count and reading blocks
Database Schema
reading_plans (bible_schema)
id UUID PRIMARY KEY
slug TEXT UNIQUE
name_fi TEXT NOT NULL
name_en TEXT
description_fi TEXT
duration_days INTEGER
is_active BOOLEAN
sort_order INTEGER
copyright TEXT
reading_plan_days (bible_schema)
id UUID PRIMARY KEY
plan_id UUID REFERENCES reading_plans(id)
day_number INTEGER
title TEXT
readings JSONB
devotional TEXT
ReadingReference Format (JSONB)
interface ReadingReference {
book: string;
chapter_start: number;
chapter_end?: number;
verse_start?: number;
verse_end?: number;
}
Manual Plan Creation
Step 1: Create Plan
INSERT INTO bible_schema.reading_plans (
id, slug, name_fi, name_en, description_fi, duration_days, is_active, sort_order
) VALUES (
gen_random_uuid(),
'gospel-of-john',
'Johanneksen evankeliumi',
'Gospel of John',
'Lue Johanneksen evankeliumi 21 päivässä',
21,
true,
10
);
Step 2: Add Daily Readings
WITH plan AS (
SELECT id FROM bible_schema.reading_plans WHERE slug = 'gospel-of-john'
)
INSERT INTO bible_schema.reading_plan_days (id, plan_id, day_number, title, readings)
SELECT gen_random_uuid(), plan.id, day_num, title, readings::jsonb
FROM plan, (VALUES
(1, 'Sana tuli lihaksi', '[{"book": "Joh", "chapter_start": 1}]'),
(2, 'Kaanan häät', '[{"book": "Joh", "chapter_start": 2}]'),
(3, 'Nikodemos', '[{"book": "Joh", "chapter_start": 3}]')
) AS days(day_num, title, readings);
Reading Reference Examples
| Type | JSON | Result |
|---|
| Single verse | {"book": "Joh", "chapter_start": 3, "verse_start": 16, "verse_end": 16} | John 3:16 |
| Verse range | {"book": "Matt", "chapter_start": 5, "verse_start": 3, "verse_end": 12} | Matthew 5:3-12 |
| Full chapter | {"book": "Ps", "chapter_start": 23} | Psalm 23 |
| Chapter range | {"book": "1. Moos", "chapter_start": 1, "chapter_end": 3} | Genesis 1-3 |
Book Abbreviations
Common Finnish abbreviations:
| Book | Abbrev | | Book | Abbrev |
|---|
| Genesis | 1. Moos | | Matthew | Matt |
| Exodus | 2. Moos | | Mark | Mark |
| Psalms | Ps | | Luke | Luuk |
| Proverbs | Sananl | | John | Joh |
| Isaiah | Jes | | Acts | Ap. t. |
| Jeremiah | Jer | | Romans | Room |
| Daniel | Dan | | Revelation | Ilm |
Query all: SELECT abbreviation_fi, name_fi FROM bible_schema.books
Reading Plan Patterns
| Pattern | Days | Focus | Example |
|---|
| Topical Week | 7 | Theme passages | "Armon viikko" |
| Book Study | 21-30 | Single book | "Johanneksen evankeliumi" |
| Section | 90 | NT or OT | "Uusi testamentti" |
| Full Bible | 365 | Complete | "Raamattu vuodessa" |
Frontend Integration
Pages & Components
| Component | Location | Purpose |
|---|
ReadingPlansPage | pages/ReadingPlansPage.tsx | Browse and join plans, tabs for active/completed |
ReadingPlanCard | components/reading-plans/ | Plan card with today's readings, quit button |
DailyReadingView | components/reading-plans/ | Day view with verses, nav, mark-as-read |
VerseSetReader | components/reader/ | Inline verse display with audio |
Key Features (Jan 2026)
- Verses shown by default - No need to click "Näytä teksti"
- Top navigation bar -
[<] [Merkitse luetuksi] [>] for easy day navigation
- Verse badges - Click to open day view (stays in reading plan context)
- Quit button - X button on active plans
- Activity tracking - Events logged to
user_activity_log
Hooks
| Hook | Purpose |
|---|
useReadingPlans | Data fetching, mutations (join, quit, mark complete) |
useReadingPlanDay | Fetch specific day's readings |
useVerseSetFetcher | Fetch verses for inline display |
Utility Files
| File | Purpose |
|---|
chapterVerseCounts.ts | Static verse counts for accurate range calculations |
activityLogger.ts | Logging reading plan events |
RPC Functions
| Function | Purpose |
|---|
get_user_reading_plans | Get user's plans with progress |
join_reading_plan | Join a plan |
get_reading_plan_day | Get day's readings (includes devotional) |
mark_reading_day_complete | Mark day complete |
create_plan_from_summary | Create plan from AI summary (premium feature) |
create_plan_from_summary RPC
Creates a reading plan from an existing AI summary. Premium-only (feature key: plan-from-summary).
bible_schema.create_plan_from_summary(
p_summary_id uuid,
p_plan_name text,
p_description text,
p_mode text,
p_language text
)
Modes:
per_item: Each Bible reference in the summary becomes one day. Devotional text = item notes or group text_content.
per_group: Each summary group becomes one day. Devotional text = group text_content.
Error codes: feature_locked (need premium), limit_reached (3/6h quota exceeded), ownership validation.
Admin "Luo koosteesta" button in AdminReadingPlansPage links to /summaries to create plans from summaries.
External Resources
For inspiration on reading plan structures:
Validation Checklist
Related Skills
| Situation | Delegate To |
|---|
| Database migrations | supabase-migration-writer |
| Bible verse lookups | bible-lookup-helper |
| Admin panel for plans | admin-panel-builder |
| Test the feature | test-writer |
Learnings
See references/learnings.md for accumulated gotchas and cross-cutting pointers.