<!DOCTYPE html>
<html lang="en-US" dir="ltr">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Applesauce</title>
    <meta name="description" content="Functional Nostr SDK for building reactive web apps">
    <meta name="generator" content="VitePress v1.6.4">
    <link rel="preload stylesheet" href="/assets/style.DA1fP4ny.css" as="style">
    <link rel="preload stylesheet" href="/vp-icons.css" as="style">
    
    <script type="module" src="/assets/app.Ce7Prvgu.js"></script>
    <link rel="preload" href="/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
    <link rel="modulepreload" href="/assets/chunks/theme.DKjKb3ph.js">
    <link rel="modulepreload" href="/assets/chunks/framework.CUV7wxKp.js">
    <link rel="modulepreload" href="/assets/index.md.CRt7MZ2I.lean.js">
    <script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"auto",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
    <script id="check-mac-os">document.documentElement.classList.toggle("mac",/Mac|iPhone|iPod|iPad/i.test(navigator.platform));</script>
  </head>
  <body>
    <div id="app"><div class="Layout" data-v-a92598ea><!--[--><!--]--><!--[--><span tabindex="-1" data-v-93dbf1d2></span><a href="#VPContent" class="VPSkipLink visually-hidden" data-v-93dbf1d2>Skip to content</a><!--]--><!----><header class="VPNav" data-v-a92598ea data-v-e0f02960><div class="VPNavBar" data-v-e0f02960 data-v-88b86f48><div class="wrapper" data-v-88b86f48><div class="container" data-v-88b86f48><div class="title" data-v-88b86f48><div class="VPNavBarTitle" data-v-88b86f48 data-v-d64343c1><a class="title" href="/" data-v-d64343c1><!--[--><!--]--><!--[--><img class="VPImage logo" src="/logo.png" alt data-v-b94c4269><!--]--><span data-v-d64343c1>Applesauce</span><!--[--><!--]--></a></div></div><div class="content" data-v-88b86f48><div class="content-body" data-v-88b86f48><!--[--><!--]--><div class="VPNavBarSearch search" data-v-88b86f48><!--[--><!----><div id="local-search"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><span class="DocSearch-Button-Container"><span class="vp-icon DocSearch-Search-Icon"></span><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"><kbd class="DocSearch-Button-Key"></kbd><kbd class="DocSearch-Button-Key">K</kbd></span></button></div><!--]--></div><nav aria-labelledby="main-nav-aria-label" class="VPNavBarMenu menu" data-v-88b86f48 data-v-3551ada0><span id="main-nav-aria-label" class="visually-hidden" data-v-3551ada0> Main Navigation </span><!--[--><!--[--><a class="VPLink link VPNavBarMenuLink active" href="/" tabindex="0" data-v-3551ada0 data-v-d3ed3fcb><!--[--><span data-v-d3ed3fcb>Home</span><!--]--></a><!--]--><!--[--><a class="VPLink link vp-external-link-icon VPNavBarMenuLink" href="https://applesauce.build/examples" target="_blank" rel="noreferrer" tabindex="0" data-v-3551ada0 data-v-d3ed3fcb><!--[--><span data-v-d3ed3fcb>Examples</span><!--]--></a><!--]--><!--[--><a class="VPLink link vp-external-link-icon VPNavBarMenuLink" href="https://applesauce.build/snippets" target="_blank" rel="noreferrer" tabindex="0" data-v-3551ada0 data-v-d3ed3fcb><!--[--><span data-v-d3ed3fcb>Snippets</span><!--]--></a><!--]--><!--[--><a class="VPLink link vp-external-link-icon VPNavBarMenuLink" href="https://applesauce.build/typedoc/index.html" target="_blank" rel="noreferrer" tabindex="0" data-v-3551ada0 data-v-d3ed3fcb><!--[--><span data-v-d3ed3fcb>Reference</span><!--]--></a><!--]--><!--]--></nav><!----><div class="VPNavBarAppearance appearance" data-v-88b86f48 data-v-d01e7b00><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" title aria-checked="false" data-v-d01e7b00 data-v-bf68cb63 data-v-cfaa5508><span class="check" data-v-cfaa5508><span class="icon" data-v-cfaa5508><!--[--><span class="vpi-sun sun" data-v-bf68cb63></span><span class="vpi-moon moon" data-v-bf68cb63></span><!--]--></span></span></button></div><div class="VPSocialLinks VPNavBarSocialLinks social-links" data-v-88b86f48 data-v-1b1e608b data-v-e07db5b8><!--[--><a class="VPSocialLink no-icon" href="https://github.com/hzrd149/applesauce" aria-label="github" target="_blank" rel="noopener" data-v-e07db5b8 data-v-768aaa40><span class="vpi-social-github"></span></a><!--]--></div><div class="VPFlyout VPNavBarExtra extra" data-v-88b86f48 data-v-785f11ea data-v-45048d01><button type="button" class="button" aria-haspopup="true" aria-expanded="false" aria-label="extra navigation" data-v-45048d01><span class="vpi-more-horizontal icon" data-v-45048d01></span></button><div class="menu" data-v-45048d01><div class="VPMenu" data-v-45048d01 data-v-c2b561c9><!----><!--[--><!--[--><!----><div class="group" data-v-785f11ea><div class="item appearance" data-v-785f11ea><p class="label" data-v-785f11ea>Appearance</p><div class="appearance-action" data-v-785f11ea><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" title aria-checked="false" data-v-785f11ea data-v-bf68cb63 data-v-cfaa5508><span class="check" data-v-cfaa5508><span class="icon" data-v-cfaa5508><!--[--><span class="vpi-sun sun" data-v-bf68cb63></span><span class="vpi-moon moon" data-v-bf68cb63></span><!--]--></span></span></button></div></div></div><div class="group" data-v-785f11ea><div class="item social-links" data-v-785f11ea><div class="VPSocialLinks social-links-list" data-v-785f11ea data-v-e07db5b8><!--[--><a class="VPSocialLink no-icon" href="https://github.com/hzrd149/applesauce" aria-label="github" target="_blank" rel="noopener" data-v-e07db5b8 data-v-768aaa40><span class="vpi-social-github"></span></a><!--]--></div></div></div><!--]--><!--]--></div></div></div><!--[--><!--]--><button type="button" class="VPNavBarHamburger hamburger" aria-label="mobile navigation" aria-expanded="false" aria-controls="VPNavScreen" data-v-88b86f48 data-v-14dd5933><span class="container" data-v-14dd5933><span class="top" data-v-14dd5933></span><span class="middle" data-v-14dd5933></span><span class="bottom" data-v-14dd5933></span></span></button></div></div></div></div><div class="divider" data-v-88b86f48><div class="divider-line" data-v-88b86f48></div></div></div><!----></header><!----><!----><div class="VPContent is-home" id="VPContent" data-v-a92598ea data-v-e7aeca77><div class="VPHome" data-v-e7aeca77 data-v-51b9b439><!--[--><!--]--><div class="VPHero VPHomeHero" data-v-51b9b439 data-v-f90e9320><div class="container" data-v-f90e9320><div class="main" data-v-f90e9320><!--[--><!--]--><!--[--><h1 class="heading" data-v-f90e9320><span class="name clip" data-v-f90e9320>Applesauce</span><span class="text" data-v-f90e9320>Modular SDK for Nostr</span></h1><p class="tagline" data-v-f90e9320>Build reactive nostr UI with less code</p><!--]--><!--[--><!--]--><div class="actions" data-v-f90e9320><!--[--><div class="action" data-v-f90e9320><a class="VPButton medium brand" href="/introduction/getting-started.html" data-v-f90e9320 data-v-c3fd87b5>Getting Started</a></div><div class="action" data-v-f90e9320><a class="VPButton medium alt" href="https://applesauce.build/typedoc/index.html" target="_blank" rel="noreferrer" data-v-f90e9320 data-v-c3fd87b5>Reference</a></div><div class="action" data-v-f90e9320><a class="VPButton medium alt" href="https://applesauce.build/examples/" target="_blank" rel="noreferrer" data-v-f90e9320 data-v-c3fd87b5>Examples</a></div><div class="action" data-v-f90e9320><a class="VPButton medium alt" href="/introduction/mcp-server.html" data-v-f90e9320 data-v-c3fd87b5>MCP Server</a></div><div class="action" data-v-f90e9320><a class="VPButton medium alt" href="/migration/v1-v2.html" data-v-f90e9320 data-v-c3fd87b5>Migrations</a></div><!--]--></div><!--[--><!--]--></div><!----></div></div><!--[--><!--]--><!--[--><!--]--><div class="VPFeatures VPHomeFeatures" data-v-51b9b439 data-v-4a96fe0c><div class="container" data-v-4a96fe0c><div class="items" data-v-4a96fe0c><!--[--><div class="grid-3 item" data-v-4a96fe0c><div class="VPLink no-icon VPFeature" data-v-4a96fe0c data-v-26126cb0><!--[--><article class="box" data-v-26126cb0><!----><h2 class="title" data-v-26126cb0>Reactive</h2><p class="details" data-v-26126cb0>Applesauce is built using RxJS observables, which makes subscribing to events simple and reactive and avoids messy state management.</p><!----></article><!--]--></div></div><div class="grid-3 item" data-v-4a96fe0c><div class="VPLink no-icon VPFeature" data-v-4a96fe0c data-v-26126cb0><!--[--><article class="box" data-v-26126cb0><!----><h2 class="title" data-v-26126cb0>No Lock-in</h2><p class="details" data-v-26126cb0>All the packages are designed to work with generic interfaces so its possible to use any other nostr libraries.</p><!----></article><!--]--></div></div><div class="grid-3 item" data-v-4a96fe0c><div class="VPLink no-icon VPFeature" data-v-4a96fe0c data-v-26126cb0><!--[--><article class="box" data-v-26126cb0><!----><h2 class="title" data-v-26126cb0>Modular</h2><p class="details" data-v-26126cb0>All the packages support tree shaking so you can only include the parts you need.</p><!----></article><!--]--></div></div><!--]--></div></div></div><!--[--><!--]--><div class="vp-doc container" style="" data-v-51b9b439 data-v-849a4d58><!--[--><div style="position:relative;" data-v-51b9b439><div><h2 id="core-packages" tabindex="-1">Core Packages <a class="header-anchor" href="#core-packages" aria-label="Permalink to &quot;Core Packages&quot;">​</a></h2><p>Applesauce is built on top of <a href="https://rxjs.dev" target="_blank" rel="noreferrer">RxJS</a> and uses the observable pattern to provide a reactive, event-driven architecture for Nostr applications.</p><ul><li><strong>applesauce-core</strong> - Core protocol primitives and utilities</li><li><strong>applesauce-common</strong> - Helpers, models, and blueprints for common nostr application patterns</li><li><strong>applesauce-relay</strong> - Simple relay connection management with automatic reconnection</li><li><strong>applesauce-signers</strong> - Flexible signing interfaces supporting multiple providers</li><li><strong>applesauce-loaders</strong> - High-level data loaders for common Nostr patterns</li></ul><h2 id="quick-examples" tabindex="-1">Quick Examples <a class="header-anchor" href="#quick-examples" aria-label="Permalink to &quot;Quick Examples&quot;">​</a></h2><h3 id="subscribe-to-events-and-updating-the-ui" tabindex="-1">Subscribe to Events and updating the UI <a class="header-anchor" href="#subscribe-to-events-and-updating-the-ui" aria-label="Permalink to &quot;Subscribe to Events and updating the UI&quot;">​</a></h3><p>The event store makes it easy to query and subscribe to events reactively:</p><div class="language-typescript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">typescript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { EventStore } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;applesauce-core/event-store&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Create an event store</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> store</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> EventStore</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Subscribe to a timeline of kind:1 events (notes)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">store.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">timeline</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ kinds: [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">], limit: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">10</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">subscribe</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">events</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">`Timeline updated: ${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">events</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">} notes`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">  renderTimeline</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(events);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Add events to the store - timeline updates automatically</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">store.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">add</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(event);</span></span></code></pre></div><h3 id="fetch-events-from-relays" tabindex="-1">Fetch Events from Relays <a class="header-anchor" href="#fetch-events-from-relays" aria-label="Permalink to &quot;Fetch Events from Relays&quot;">​</a></h3><p>Connect to relays and fetch events with minimal code:</p><div class="language-typescript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">typescript</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { RelayPool, onlyEvents } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;applesauce-relay&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { createEventLoaderForStore } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;applesauce-loaders/loaders&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { EventStore } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;applesauce-core&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Create an event store to hold state (events)</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> store</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> EventStore</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Create a relay connection</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> pool</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> RelayPool</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Create an event store for the UI</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> eventStore</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> EventStore</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Connect the event store to the relay pool</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">createEventLoaderForStore</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(eventStore, pool);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Subscribe to events from the relay</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">pool</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">subscription</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">([</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;wss://relay.damus.io&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;wss://nos.lol&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;wss://relay.nostr.band&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">], { kinds: [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">], limit: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">20</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> })</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">pipe</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">onlyEvents</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">())</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">subscribe</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">event</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> store.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">add</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(event));</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Subscribe to the timeline from the event store</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">store.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">timeline</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ kinds: [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">] }).</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">subscribe</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">events</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">`Timeline updated: ${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">events</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">length</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">} notes`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Subscribe and automatically load profiles from event store</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> profile</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> eventStore</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">profile</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    pubkey: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    relays: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;wss://relay.damus.io&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;wss://nos.lol&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">],</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  })</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">subscribe</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">profile</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    console.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">log</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;Profile:&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, profile);</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  });</span></span></code></pre></div><h3 id="react-relay-timeline" tabindex="-1">React relay timeline <a class="header-anchor" href="#react-relay-timeline" aria-label="Permalink to &quot;React relay timeline&quot;">​</a></h3><p>Casts make it incredibly easy to subscribe to user profiles and other metadata around events. Here&#39;s a complete React example:</p><div class="language-tsx vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">tsx</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { castEvent, Note } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;applesauce-common/casts&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { castTimelineStream } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;applesauce-common/observable&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { EventStore, mapEventsToStore, mapEventsToTimeline } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;applesauce-core&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { createEventLoaderForStore } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;applesauce-loaders/loaders&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { use$ } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;applesauce-react/hooks&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { onlyEvents, RelayPool } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;applesauce-relay&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { useState } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &quot;react&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Create an event store for storing events</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> eventStore</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> EventStore</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// And a relay pool for managing connections</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> pool</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> new</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> RelayPool</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// Connect the event store to the relay pool for automatic event loading</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">createEventLoaderForStore</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(eventStore, pool, {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">  // Fallback relays to find profiles and NIP-65 events</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  lookupRelays: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;wss://purplepag.es/&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;wss://index.hzrd149.com/&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">],</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">});</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> ReplyingTo</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">note</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">note</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Note</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">  // Subscribe to the profile of the note being replied to</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">  const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> profile</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> use$</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(note.author.profile$);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">  return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    &lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> className</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;reply-context&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">      &lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">p</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;Replying to {profile.displayName}&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">p</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">      &lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">p</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> className</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;reply-content&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;{note.event.content}&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">p</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    &lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  );</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> NoteComponent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">note</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">note</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Note</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) {</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">  // Subscribe to the author&#39;s profile - automatically loads and updates reactively</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">  const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> profile</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> use$</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(note.author.profile$);</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">  // Subscribe to fetch the event this note is replying to</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">  const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> replyingTo</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> use$</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(note.replyingTo$);</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">  // Cast the replying-to event to a Note if it exists</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">  const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> replyingToNote</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> replyingTo </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">?</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> castEvent</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(replyingTo, Note, note.store) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> null</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">  return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    &lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> className</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;note&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">      {replyingToNote </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">&amp;&amp;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> &lt;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">ReplyingTo</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> note</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">{replyingToNote} /&gt;}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">      &lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> className</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;note-header&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">        &lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">img</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> className</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;avatar&quot;</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> src</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">{profile?.picture </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">??</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> `https://robohash.org/${</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">note</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">author</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">.</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">pubkey</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">}.png`</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">} /&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">        &lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">h3</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> className</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;author-name&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;{profile.displayName}&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">h3</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">      &lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">      &lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">p</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> className</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;note-content&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;{note.event.content}&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">p</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    &lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  );</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">export</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> default</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> function</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> Timeline</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() {</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">  const</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">relay</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">setRelay</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">] </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> useState</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;wss://relay.damus.io/&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">);</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">  // Subscribe to a timeline of notes from a relay</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">  // The castTimelineStream automatically transforms events into Note objects</span></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">  const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> notes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> use$</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">      pool</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">        .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">relay</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(relay)</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">        .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">subscription</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({ kinds: [</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">] })</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">        .</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">pipe</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">          // Ignore EOSE messages</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">          onlyEvents</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">          // Add all events to the store</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">          mapEventsToStore</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(eventStore),</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">          // Sort events into an array</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">          mapEventsToTimeline</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(),</span></span>
<span class="line"><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">          // Cast events to Note objects</span></span>
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">          castTimelineStream</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(Note),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">        ),</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    [relay],</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  );</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">  return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    &lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> className</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;timeline&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">      {notes?.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">map</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">((</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">note</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=&gt;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> (</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">        &lt;</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">NoteComponent</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> key</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">{note.id} </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">note</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">{note} /&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">      ))}</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">    &lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">div</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">  );</span></span>
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div></div></div><!--]--></div></div></div><!----><!--[--><!--]--></div></div>
    <script>window.__VP_HASH_MAP__=JSON.parse("{\"apps_accounts_accounts.md\":\"Bzylio7n\",\"apps_accounts_index.md\":\"r2OVOvBI\",\"apps_accounts_manager.md\":\"D9MtaJgV\",\"apps_actions_action-runner.md\":\"CCtBz3mt\",\"apps_actions_actions.md\":\"C9J5fVAD\",\"apps_actions_index.md\":\"B-ywGNjB\",\"apps_casting_events.md\":\"DkIU621e\",\"apps_casting_users.md\":\"Dc8Wtv5M\",\"apps_content_index.md\":\"B7JhqTn0\",\"apps_content_markdown.md\":\"CFUazR7A\",\"apps_content_react.md\":\"BiXFQlgY\",\"apps_content_text.md\":\"B2lqIUuB\",\"apps_encryption_caching.md\":\"B3U0eYk9\",\"apps_react_index.md\":\"DyftK_9u\",\"apps_react_use-observable.md\":\"gDq1Pbiz\",\"core_casting.md\":\"CfzFpltU\",\"core_event-memory.md\":\"DGIQic10\",\"core_event-store.md\":\"BetPzFg-\",\"core_helpers.md\":\"DlRZ0j_G\",\"core_models.md\":\"5a_SgreP\",\"creating_factory_blueprints.md\":\"BAWnNxXB\",\"creating_factory_event-factory.md\":\"wOUgptyZ\",\"creating_factory_event-operations.md\":\"CQDzuxJI\",\"creating_factory_index.md\":\"CD3pQ1v9\",\"creating_factory_tag-operations.md\":\"CpY7ylcm\",\"creating_signers_bunker-provider.md\":\"U17KW7Ra\",\"creating_signers_index.md\":\"CRXhL1a1\",\"creating_signers_nostr-connect.md\":\"Z_5qDYBn\",\"creating_signers_signers.md\":\"D_xK759U\",\"index.md\":\"CRt7MZ2I\",\"introduction_getting-started.md\":\"3uzp38Rl\",\"introduction_glossary.md\":\"DvRz4FOu\",\"introduction_mcp-server.md\":\"EH0K2-id\",\"introduction_packages.md\":\"C4CKmmHL\",\"loading_loaders_address-loader.md\":\"CcO5-_b0\",\"loading_loaders_event-loader.md\":\"Igt9-kNb\",\"loading_loaders_package.md\":\"YTQiyvne\",\"loading_loaders_reactions-loader.md\":\"D9Uqv3VW\",\"loading_loaders_tag-value-loader.md\":\"Cjh6U0HS\",\"loading_loaders_timeline-loader.md\":\"B6ZInUzX\",\"loading_loaders_unified-loader.md\":\"Clg_Dzqs\",\"loading_loaders_upstream-pool.md\":\"BHUHyYYH\",\"loading_loaders_zaps-loader.md\":\"CSrPhyyQ\",\"loading_relays_liveness.md\":\"DgfCX2Mz\",\"loading_relays_negentropy.md\":\"DwQ64gog\",\"loading_relays_operators.md\":\"BlcwBe5l\",\"loading_relays_package.md\":\"Cr5pMhYn\",\"loading_relays_pool.md\":\"Bgr0iDxQ\",\"loading_relays_relays.md\":\"B5wBIwnq\",\"migration_v1-v2.md\":\"DASYDeon\",\"migration_v2-v3.md\":\"CHo4Ugo_\",\"migration_v4-v5.md\":\"Dxxs2a0c\",\"money_wallet-connect_package.md\":\"-4m_jnpj\",\"money_wallet-connect_wallet-connect.md\":\"BQF9SSCA\",\"money_wallet-connect_wallet-service.md\":\"BMBIYm10\",\"money_wallet_actions.md\":\"Dkg1j6BY\",\"money_wallet_casts.md\":\"ksCDayRq\",\"money_wallet_models.md\":\"CxVr9y_j\",\"money_wallet_package.md\":\"rAG8pIGU\",\"storage_caching_index.md\":\"0YaRMflX\",\"storage_caching_nostr-idb.md\":\"BNtFfVdC\",\"storage_caching_window.nostrdb.md\":\"B18QvNpf\",\"storage_databases_better-sqlite3.md\":\"BG3z7b9U\",\"storage_databases_bun.md\":\"C4RpM4DS\",\"storage_databases_index.md\":\"DHtWwv9Y\",\"storage_databases_libsql.md\":\"fVLZ_qeo\",\"storage_databases_native.md\":\"AZ_OrCa2\",\"storage_databases_turso-wasm.md\":\"CLdW0g1U\",\"storage_databases_turso.md\":\"BHq6eTdm\",\"storage_index.md\":\"LXulJJsg\"}");window.__VP_SITE_DATA__=JSON.parse("{\"lang\":\"en-US\",\"dir\":\"ltr\",\"title\":\"Applesauce\",\"description\":\"Functional Nostr SDK for building reactive web apps\",\"base\":\"/\",\"head\":[],\"router\":{\"prefetchLinks\":true},\"appearance\":true,\"themeConfig\":{\"logo\":\"/logo.png\",\"editLink\":{\"pattern\":\"https://github.com/hzrd149/applesauce/edit/master/apps/docs/:path\"},\"search\":{\"provider\":\"local\"},\"outline\":{\"level\":[2,3]},\"nav\":[{\"text\":\"Home\",\"link\":\"/\"},{\"text\":\"Examples\",\"link\":\"https://applesauce.build/examples\"},{\"text\":\"Snippets\",\"link\":\"https://applesauce.build/snippets\"},{\"text\":\"Reference\",\"link\":\"https://applesauce.build/typedoc/index.html\"}],\"sidebar\":[{\"text\":\"Introduction\",\"collapsed\":false,\"items\":[{\"text\":\"Getting Started\",\"link\":\"/introduction/getting-started\"},{\"text\":\"Packages\",\"link\":\"/introduction/packages\"},{\"text\":\"MCP Server\",\"link\":\"/introduction/mcp-server\"},{\"text\":\"Glossary\",\"link\":\"/introduction/glossary\"}]},{\"text\":\"Reading events\",\"collapsed\":false,\"items\":[{\"text\":\"Event Store\",\"link\":\"/core/event-store\"},{\"text\":\"Event Memory\",\"link\":\"/core/event-memory\"},{\"text\":\"Models\",\"link\":\"/core/models\"},{\"text\":\"Casting\",\"link\":\"/core/casting\"},{\"text\":\"Helpers\",\"link\":\"/core/helpers\"}]},{\"text\":\"Loading events\",\"collapsed\":false,\"items\":[{\"text\":\"Relays\",\"link\":\"/loading/relays/package\",\"items\":[{\"text\":\"Relays\",\"link\":\"/loading/relays/relays\"},{\"text\":\"Relay Pool\",\"link\":\"/loading/relays/pool\"},{\"text\":\"Liveness\",\"link\":\"/loading/relays/liveness\"},{\"text\":\"Negentropy\",\"link\":\"/loading/relays/negentropy\"},{\"text\":\"Operators\",\"link\":\"/loading/relays/operators\"}]},{\"text\":\"Loaders\",\"link\":\"/loading/loaders/package\",\"items\":[{\"text\":\"Upstream Pool\",\"link\":\"/loading/loaders/upstream-pool\"},{\"text\":\"Event Loader\",\"link\":\"/loading/loaders/event-loader\"},{\"text\":\"Address Loader\",\"link\":\"/loading/loaders/address-loader\"},{\"text\":\"Unified Loader\",\"link\":\"/loading/loaders/unified-loader\"},{\"text\":\"Timeline Loader\",\"link\":\"/loading/loaders/timeline-loader\"},{\"text\":\"Zaps Loader\",\"link\":\"/loading/loaders/zaps-loader\"},{\"text\":\"Reactions Loader\",\"link\":\"/loading/loaders/reactions-loader\"},{\"text\":\"Tag Value Loader\",\"link\":\"/loading/loaders/tag-value-loader\"}]}]},{\"text\":\"Creating events\",\"collapsed\":false,\"items\":[{\"text\":\"Signers\",\"link\":\"/creating/signers\",\"items\":[{\"text\":\"Signers\",\"link\":\"/creating/signers/signers\"},{\"text\":\"Nostr Connect\",\"link\":\"/creating/signers/nostr-connect\"},{\"text\":\"Bunker Provider\",\"link\":\"/creating/signers/bunker-provider\"}]},{\"text\":\"Factory\",\"link\":\"/creating/factory\",\"items\":[{\"text\":\"Event Factory\",\"link\":\"/creating/factory/event-factory\"},{\"text\":\"Blueprints\",\"link\":\"/creating/factory/blueprints\"},{\"text\":\"Event Operations\",\"link\":\"/creating/factory/event-operations\"},{\"text\":\"Tag Operations\",\"link\":\"/creating/factory/tag-operations\"}]}]},{\"text\":\"Building apps\",\"collapsed\":false,\"items\":[{\"text\":\"Accounts\",\"link\":\"/apps/accounts\",\"items\":[{\"text\":\"Manager\",\"link\":\"/apps/accounts/manager\"},{\"text\":\"Accounts\",\"link\":\"/apps/accounts/accounts\"}]},{\"text\":\"Actions\",\"link\":\"/apps/actions\",\"items\":[{\"text\":\"Action Runner\",\"link\":\"/apps/actions/action-runner\"},{\"text\":\"Actions\",\"link\":\"/apps/actions/actions\"}]},{\"text\":\"React\",\"link\":\"/apps/react\",\"items\":[{\"text\":\"use$\",\"link\":\"/apps/react/use-observable\"}]},{\"text\":\"Casting\",\"items\":[{\"text\":\"Events\",\"link\":\"/apps/casting/events\"},{\"text\":\"Users\",\"link\":\"/apps/casting/users\"}]},{\"text\":\"Content\",\"link\":\"/apps/content\",\"items\":[{\"text\":\"Text\",\"link\":\"/apps/content/text\"},{\"text\":\"Markdown\",\"link\":\"/apps/content/markdown\"},{\"text\":\"React\",\"link\":\"/apps/content/react\"}]},{\"text\":\"Encryption\",\"items\":[{\"text\":\"Caching\",\"link\":\"/apps/encryption/caching\"}]}]},{\"text\":\"Connecting bitcoin\",\"collapsed\":false,\"items\":[{\"text\":\"Wallet Connect\",\"link\":\"/money/wallet-connect/package\",\"items\":[{\"text\":\"Connect\",\"link\":\"/money/wallet-connect/wallet-connect\"},{\"text\":\"Service\",\"link\":\"/money/wallet-connect/wallet-service\"}]},{\"text\":\"Wallet\",\"link\":\"/money/wallet/package\",\"items\":[{\"text\":\"Actions\",\"link\":\"/money/wallet/actions\"},{\"text\":\"Casts\",\"link\":\"/money/wallet/casts\"},{\"text\":\"Models\",\"link\":\"/money/wallet/models\"}]}]},{\"text\":\"Storing events\",\"collapsed\":false,\"link\":\"/storage\",\"items\":[{\"text\":\"Caching\",\"link\":\"/storage/caching\",\"items\":[{\"text\":\"nostr-idb\",\"link\":\"/storage/caching/nostr-idb\"},{\"text\":\"window.nostrdb.js\",\"link\":\"/storage/caching/window.nostrdb\"}]},{\"text\":\"Databases\",\"link\":\"/storage/databases\",\"items\":[{\"text\":\"Better SQLite3\",\"link\":\"/storage/databases/better-sqlite3\"},{\"text\":\"Native SQLite\",\"link\":\"/storage/databases/native\"},{\"text\":\"Bun SQLite\",\"link\":\"/storage/databases/bun\"},{\"text\":\"LibSQL\",\"link\":\"/storage/databases/libsql\"},{\"text\":\"Turso\",\"link\":\"/storage/databases/turso\"},{\"text\":\"Turso Wasm\",\"link\":\"/storage/databases/turso-wasm\"}]}]},{\"text\":\"Migrations\",\"collapsed\":true,\"items\":[{\"text\":\"v4 to v5\",\"link\":\"/migration/v4-v5\"},{\"text\":\"v2 to v3\",\"link\":\"/migration/v2-v3\"},{\"text\":\"v1 to v2\",\"link\":\"/migration/v1-v2\"}]}],\"socialLinks\":[{\"icon\":\"github\",\"link\":\"https://github.com/hzrd149/applesauce\"}]},\"locales\":{},\"scrollOffset\":134,\"cleanUrls\":false}");</script>
    
  </body>
</html>