Skip to content

feat(siddur): customize the Koren siddur by hiding sections (POC) - #3824

Draft
mickeysefaria wants to merge 4 commits into
masterfrom
customsiddur
Draft

mickeysefaria wants to merge 4 commits into
masterfrom
customsiddur

Conversation

@mickeysefaria

@mickeysefaria mickeysefaria commented Oct 18, 2026 •

Copy link
Copy Markdown
Collaborator

Description

POC, deployed to the customsiddur cauldron only.

The book TOC of The Koren Shalem Siddur; Ashkenaz gets a Customize button. It opens a modal with a checkbox tree of the whole siddur, all checked. Unchecking a section (e.g. Weekdays › Tallit) or a root (e.g. Shabbat) hides it:

  • dropped from the book TOC (full page and reader sidebar);
  • skipped by the reader's infinite scroll, both directions;
  • skipped by Start Reading.

Weekday sub-sections: the Weekdays nodes also list sub-sections, collapsed by default. Examples: On Waking › Tzitzit, Minha › The Amida › Kedusha, Aleinu. Unchecking one hides just those paragraphs inside the section. Unchecking every sub-section of a node hides the whole node.

Display options at the top of the modal:

  • Show instructions (on by default). Off removes the text's <i class="instruction"> elements, and paragraphs that held only instructions disappear.
  • Show a note where sections are hidden (off by default). On puts Not showing “Tzitzit”. Customize where hidden paragraphs or skipped sections were. Customize opens the modal right in the reader.

Everything is saved in localStorage (siddur.hiddenSections, siddur.displayOptions), per device, with no account needed. Direct links to a hidden section still open it.

Code Changes

  • static/js/sefaria/siddurCustomization.js (new, pure):
    • book allowlist; storage for hidden refs and display options; subscribeCustomization (same tab and cross-tab);
    • schema → tree, plus buildCustomizeTree for sub-sections;
    • resolveHidden, which splits stored refs into whole sections and named paragraph ranges;
    • pruneSchema, isRefHidden, skipHidden, firstVisibleSectionRef;
    • helpers for instructions and notes: stripInstructions, visibleSegments, hintGroups, interleaveHints, hiddenRun, namesFor.
  • static/js/sefaria/siddurSubsections.json (new, ~3 KB gzipped): a curated map of the 13 Koren weekday nodes that have sub-sections.
    • It was built from the text's bold heading paragraphs, with nesting (the Amida blessings) and unheaded parts (Ashrei, Aleinu, Elokai Netzor) added.
    • Within each node, the children cover its whole paragraph range.
  • static/js/SiddurCustomizeModal.jsx (new): the display toggles; tri-state, collapsible tree; Show All / Cancel / Save.
  • static/js/SiddurHiddenHint.jsx (new): the inline note.
  • BookPage.jsx: Customize button (shows "N hidden"), the modal, a pruned schema in TextTableOfContents, and the first visible section for Start Reading.
  • TextColumn.jsx:
    • neighborRef() replaces raw next/prev for infinite scroll;
    • adds notes between sections for skipped hidden sections;
    • passes the display props to each TextRange;
    • hosts the modal.
  • TextRange.jsx: optional hiddenSegments, hideInstructions, showHiddenHints and onSiddurCustomize props.
  • common/modal.jsx: optional className.
  • s2.css, i18n siddur_customize.* (en/he).
  • Jest: siddurCustomization.test.js and siddurCustomizeModal.test.js. The tests include a check that every node's sub-sections cover all of its paragraphs, plus cases for instruction stripping taken from the Koren text.

Notes

  • Customization is read after mount only, so SSR output and hydration are unchanged. As a result, on a direct page load, hidden content shows briefly until the client mounts.
  • Hidden items are stored as refs: section refs, or paragraph ranges such as …, Weekdays, On Waking 8-12. A ref saved for a section that has since gained sub-sections stands for all of them.
  • Full Jest suite passes (41 suites, 636 tests); client and SSR webpack builds pass.

🤖 Generated with Claude Code

https://claude.ai/code/session_01G4XFnHB38fPvuMVpc35cMd

A Customize button on the book TOC of The Koren Shalem Siddur; Ashkenaz opens
a checkbox tree of every section. Unchecked sections (leaves, or whole roots
like Shabbat) are saved in localStorage, dropped from the book TOC, skipped by
the reader's infinite scroll, and skipped by Start Reading. No account needed.

- sefaria/siddurCustomization.js: pure storage, tree, prune and skip helpers
- SiddurCustomizeModal.jsx: the tree modal (tri-state parents, collapsible)
- BookPage / TextTableOfContents / TextColumn: read state after mount only,
  so SSR output is unchanged
- common/modal.jsx: optional className

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G4XFnHB38fPvuMVpc35cMd
The weekday nodes of the Koren siddur gain sub-sections (e.g. On Waking ›
Tzitzit, Minha › The Amida › Kedusha, Aleinu) that the Customize tree lists
under their node, collapsed by default. A partially hidden node stays in the
TOC and in the reader; its hidden paragraphs are filtered out of the
TextRange. Hiding every sub-section of a node hides the node as before.

- sefaria/siddurSubsections.json: curated map built from the text's bold
  headings, with nesting (Amida blessings) and unheaded parts (Ashrei,
  Aleinu, Elokai Netzor) added; children cover each node's whole range
- siddurCustomization.js: buildCustomizeTree, normalizeHiddenRefs,
  resolveHidden (whole leaves vs paragraph ranges), hiddenSegmentsFor
- TextRange: optional hiddenSegments prop

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G4XFnHB38fPvuMVpc35cMd
Two display options at the top of the Customize modal, saved per device
with the hidden sections:

- Show instructions (default on): off strips the text's
  <i class="instruction"> elements; paragraphs that were only
  instructions drop out.
- Show a note where sections are hidden (default off): on puts an inline
  "Not showing “Tzitzit”. Customize" note where hidden paragraphs or
  skipped sections were; Customize opens the modal from the reader.

- siddurCustomization.js: display options storage, subscribeCustomization
  (replaces subscribeHiddenRefs), stripInstructions, visibleSegments,
  hintGroups, interleaveHints, hiddenRun, namesFor; resolveHidden ranges
  now carry their names
- SiddurHiddenHint.jsx: the inline note
- TextRange / TextColumn: apply the options; TextColumn hosts the modal

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G4XFnHB38fPvuMVpc35cMd
Hiding a section from the reader left it on screen if infinite scroll had
already loaded it, right under the note saying it was hidden. On a change,
TextColumn now drops loaded sections that are hidden (except the one in
view, which stays where it was on screen).

Notes for skipped sections now render inside the neighbouring TextRange
(hiddenBefore / hiddenAfter), so they share the text's width instead of
spanning the whole panel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G4XFnHB38fPvuMVpc35cMd

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants