Skip to content

How the toolkit works ​

The easiest way to see how the toolkit fits together is to follow one tag from your page to the screen. This page follows <sefaria-source-card sref="Micah 6:8"> and explains, at each step, why the toolkit behaves as it does.

You add a tag ​

You put the tag on your page. Behind it sit three packages. The client (@sefaria/api-client) fetches from Sefaria's API and checks each JSON response against a schema. The text tools (@sefaria/text-transform) clean text strings and know nothing about the client. The components (@sefaria/web-components) use both. The elements are standard web components built with Lit, a small library for building web components.

Importing the script or the package registers the elements but makes no request of its own. Any tag already on the page with an sref then loads as usual. The shared default client is created lazily, the first time an element needs it. Nothing renders on the server. The components run in the browser.

With the tag in place, the element needs text to show. The next step is where that text comes from.

Where the text comes from ​

The element has three possible sources:

  • live loading by sref, through the shared data source or a toolkit client you supply
  • data you supply, on the Text Segment, Bilingual Segment, and Source Card only
  • a custom loader your host provides

If you choose loading disabled, the element makes no request. It shows an error only when it needed to load. Supplied data still renders, and a tag with no input stays empty.

On those three elements, supplied data wins over sref. You already have the text, so asking Sefaria again would waste a request and could disagree with what you gave. For the same reason, invalid data shows an error and does not fall back to sref. A silent fallback would hide your bug and show text you didn't choose.

The Reader and Connections Panel don't take data. To give them local data, your host provides a custom loader. See Give components your own data for supplying data and custom loaders, and the Components reference for exact property shapes.

When the text comes from sref, the element has to ask Sefaria for it.

Asking Sefaria ​

Two elements are composed of other elements. The Source Card shows a heading and draws its text with Text Segments inside it. The Reader shows a Source Card and a Connections Panel. A composed element fetches the text once and hands it to the elements inside it. Nesting them doesn't cost extra loading.

The other elements load their own data when you use them on their own. Those are the Text Segment, Bilingual Segment, and Connections Panel. For how the client handles requests, including its cache, see The client and Sefaria's API.

Once the response arrives, the text still needs preparing.

Preparing the text ​

The text is HTML with Sefaria's own markup, so the component doesn't draw it as it arrives. It runs it through the text tools first. normalizeText keeps a fixed set of safe elements and removes active attributes. That step is where safety comes from. Then the element applies vocalization. Only then does the element show the text. See Clean text and safety.

Once the text is prepared, the element can show it and tell your page how it went.

Reporting back ​

The element reports through its status property, a coarse, element-level summary:

  • empty: no sref or data was given, or the response had nothing to show. An empty-state message may still show.
  • loading: the element is waiting for data or preparing it.
  • ready: something is prepared to show, and it may be partial.
  • error: the request, the preparation, or the supplied data failed. A failed later reload can keep the old content on screen while the status is error.

The Reader's status covers its main passage. Its connections can still be loading or unavailable while it is ready.

An element can finish before your script listens. So it keeps its state in status instead of firing a one-time ready event you could miss.

Each element also has an error event named sefaria-<element>-error for particular failures, such as a failed request. The element may show the same error on the page too. Not every error fires the event.

Some elements send interaction events that your page can listen to. Examples are a Source Card selection or a Connections Panel category change. See Troubleshoot a page, Component events, and Make components respond to each other.

Using the client and text tools without components ​

You can also take all these steps yourself, without components. They are the same steps, now yours.

You fetch with the client. It gives typed, validated data and typed errors. A response that doesn't match the schema raises SefariaContractError.

You prepare with the text tools. normalizeText returns safe bodyHtml plus the footnotes it extracted (notes). applyVocalization and applyVocalizationToHtml change vowel marks but don't sanitize, so normalize first. createTextPreview normalizes itself.

Then you show the text and report status yourself.

When you draw it yourself, you own:

  • layout
  • accessibility and keyboard behavior
  • showing attribution
  • loading states and errors
  • inserting only normalized HTML

For details, see Handle errors in your code and Clean up stored Sefaria text. Sefaria's own texts and tools explains references and editions.

Learn more: Client reference · Text tools reference

Where to go next ​

To change how the components look, see Match your site's look.

Sefaria Frontend ToolkitCommunity-driven with Sefaria backing and support. GitHub Get support

AI-generated documentation.

About this documentation

Like the codebase, this documentation was scaffolded and written with GitHub Copilot. I don't have a background in technical writing, and wanted to get something out there.

Pages that have not undergone any human review are explicitly marked, but the others may also read funny or need work too. Sorry about that.

Please report any issues so they can be prioritized.

Thanks, Avi