[{"data":1,"prerenderedAt":1094},["ShallowReactive",2],{"navigation":3,"\u002Fv0\u002Fplayground\u002Fbuilding-tutorials":489,"\u002Fv0\u002Fplayground\u002Fbuilding-tutorials-surround":1089},[4,287],{"title":5,"path":6,"stem":7,"children":8,"icon":286},"v1 · in progress","\u002Fv1","1.v1\u002F01.index",[9,11,46],{"title":10,"path":6,"stem":7},"The current guide",{"title":12,"path":13,"stem":14,"children":15,"icon":45},"Communities","\u002Fv1\u002Fcommunities","1.v1\u002F03.communities\u002F1.index",[16,17,21,25,29,33,37,41],{"title":12,"path":13,"stem":14},{"title":18,"path":19,"stem":20},"Decide together","\u002Fv1\u002Fcommunities\u002Fdecide-together","1.v1\u002F03.communities\u002F2.decide-together",{"title":22,"path":23,"stem":24},"Protocols","\u002Fv1\u002Fcommunities\u002Fprotocols","1.v1\u002F03.communities\u002F3.protocols",{"title":26,"path":27,"stem":28},"Features and settings","\u002Fv1\u002Fcommunities\u002Ffeatures","1.v1\u002F03.communities\u002F4.features",{"title":30,"path":31,"stem":32},"Custodians and the community key","\u002Fv1\u002Fcommunities\u002Fcustodians","1.v1\u002F03.communities\u002F5.custodians",{"title":34,"path":35,"stem":36},"Projects","\u002Fv1\u002Fcommunities\u002Fprojects","1.v1\u002F03.communities\u002F6.projects",{"title":38,"path":39,"stem":40},"Between communities","\u002Fv1\u002Fcommunities\u002Fbetween-communities","1.v1\u002F03.communities\u002F7.between-communities",{"title":42,"path":43,"stem":44},"Messages, relays and storage","\u002Fv1\u002Fcommunities\u002Fmessages-and-storage","1.v1\u002F03.communities\u002F8.messages-and-storage","i-lucide-users",{"title":47,"path":48,"stem":49,"children":50,"icon":285},"Technical reference","\u002Fv1\u002Freference","1.v1\u002F12.reference\u002F1.index",[51,52,274,278,282],{"title":47,"path":48,"stem":49},{"title":53,"path":54,"stem":55,"children":56},"Packages","\u002Fv1\u002Freference\u002Fpackages","1.v1\u002F12.reference\u002F2.packages\u002F1.index",[57,58,62,66,70,74,78,82,86,90,94,98,102,106,110,114,118,122,126,130,134,138,142,146,150,154,158,162,166,170,174,178,182,186,190,194,198,202,206,210,214,218,222,226,230,234,238,242,246,250,254,258,262,266,270],{"title":53,"path":54,"stem":55},{"title":59,"path":60,"stem":61},"aes-gcm","\u002Fv1\u002Freference\u002Fpackages\u002Faes-gcm","1.v1\u002F12.reference\u002F2.packages\u002Faes-gcm",{"title":63,"path":64,"stem":65},"agreements","\u002Fv1\u002Freference\u002Fpackages\u002Fagreements","1.v1\u002F12.reference\u002F2.packages\u002Fagreements",{"title":67,"path":68,"stem":69},"auth-sdk","\u002Fv1\u002Freference\u002Fpackages\u002Fauth-sdk","1.v1\u002F12.reference\u002F2.packages\u002Fauth-sdk",{"title":71,"path":72,"stem":73},"blind-tokens","\u002Fv1\u002Freference\u002Fpackages\u002Fblind-tokens","1.v1\u002F12.reference\u002F2.packages\u002Fblind-tokens",{"title":75,"path":76,"stem":77},"blob-store","\u002Fv1\u002Freference\u002Fpackages\u002Fblob-store","1.v1\u002F12.reference\u002F2.packages\u002Fblob-store",{"title":79,"path":80,"stem":81},"broadcast-medium","\u002Fv1\u002Freference\u002Fpackages\u002Fbroadcast-medium","1.v1\u002F12.reference\u002F2.packages\u002Fbroadcast-medium",{"title":83,"path":84,"stem":85},"capacitor-keystore","\u002Fv1\u002Freference\u002Fpackages\u002Fcapacitor-keystore","1.v1\u002F12.reference\u002F2.packages\u002Fcapacitor-keystore",{"title":87,"path":88,"stem":89},"capacitor-tor","\u002Fv1\u002Freference\u002Fpackages\u002Fcapacitor-tor","1.v1\u002F12.reference\u002F2.packages\u002Fcapacitor-tor",{"title":91,"path":92,"stem":93},"capacitor-unifiedpush","\u002Fv1\u002Freference\u002Fpackages\u002Fcapacitor-unifiedpush","1.v1\u002F12.reference\u002F2.packages\u002Fcapacitor-unifiedpush",{"title":95,"path":96,"stem":97},"capture-inbox","\u002Fv1\u002Freference\u002Fpackages\u002Fcapture-inbox","1.v1\u002F12.reference\u002F2.packages\u002Fcapture-inbox",{"title":99,"path":100,"stem":101},"clan","\u002Fv1\u002Freference\u002Fpackages\u002Fclan","1.v1\u002F12.reference\u002F2.packages\u002Fclan",{"title":103,"path":104,"stem":105},"community-core","\u002Fv1\u002Freference\u002Fpackages\u002Fcommunity-core","1.v1\u002F12.reference\u002F2.packages\u002Fcommunity-core",{"title":107,"path":108,"stem":109},"community-identity","\u002Fv1\u002Freference\u002Fpackages\u002Fcommunity-identity","1.v1\u002F12.reference\u002F2.packages\u002Fcommunity-identity",{"title":111,"path":112,"stem":113},"community-log","\u002Fv1\u002Freference\u002Fpackages\u002Fcommunity-log","1.v1\u002F12.reference\u002F2.packages\u002Fcommunity-log",{"title":115,"path":116,"stem":117},"community-plugin-api","\u002Fv1\u002Freference\u002Fpackages\u002Fcommunity-plugin-api","1.v1\u002F12.reference\u002F2.packages\u002Fcommunity-plugin-api",{"title":119,"path":120,"stem":121},"corroboration","\u002Fv1\u002Freference\u002Fpackages\u002Fcorroboration","1.v1\u002F12.reference\u002F2.packages\u002Fcorroboration",{"title":123,"path":124,"stem":125},"cover-traffic-scheduler","\u002Fv1\u002Freference\u002Fpackages\u002Fcover-traffic-scheduler","1.v1\u002F12.reference\u002F2.packages\u002Fcover-traffic-scheduler",{"title":127,"path":128,"stem":129},"demo-family-tree","\u002Fv1\u002Freference\u002Fpackages\u002Fdemo-family-tree","1.v1\u002F12.reference\u002F2.packages\u002Fdemo-family-tree",{"title":131,"path":132,"stem":133},"device-link","\u002Fv1\u002Freference\u002Fpackages\u002Fdevice-link","1.v1\u002F12.reference\u002F2.packages\u002Fdevice-link",{"title":135,"path":136,"stem":137},"device-scanner","\u002Fv1\u002Freference\u002Fpackages\u002Fdevice-scanner","1.v1\u002F12.reference\u002F2.packages\u002Fdevice-scanner",{"title":139,"path":140,"stem":141},"did-e2e","\u002Fv1\u002Freference\u002Fpackages\u002Fdid-e2e","1.v1\u002F12.reference\u002F2.packages\u002Fdid-e2e",{"title":143,"path":144,"stem":145},"directory-listings","\u002Fv1\u002Freference\u002Fpackages\u002Fdirectory-listings","1.v1\u002F12.reference\u002F2.packages\u002Fdirectory-listings",{"title":147,"path":148,"stem":149},"ecosystem-cli","\u002Fv1\u002Freference\u002Fpackages\u002Fecosystem-cli","1.v1\u002F12.reference\u002F2.packages\u002Fecosystem-cli",{"title":151,"path":152,"stem":153},"endscroll","\u002Fv1\u002Freference\u002Fpackages\u002Fendscroll","1.v1\u002F12.reference\u002F2.packages\u002Fendscroll",{"title":155,"path":156,"stem":157},"ephemeral-share","\u002Fv1\u002Freference\u002Fpackages\u002Fephemeral-share","1.v1\u002F12.reference\u002F2.packages\u002Fephemeral-share",{"title":159,"path":160,"stem":161},"example-community-plugin","\u002Fv1\u002Freference\u002Fpackages\u002Fexample-community-plugin","1.v1\u002F12.reference\u002F2.packages\u002Fexample-community-plugin",{"title":163,"path":164,"stem":165},"family","\u002Fv1\u002Freference\u002Fpackages\u002Ffamily","1.v1\u002F12.reference\u002F2.packages\u002Ffamily",{"title":167,"path":168,"stem":169},"geo","\u002Fv1\u002Freference\u002Fpackages\u002Fgeo","1.v1\u002F12.reference\u002F2.packages\u002Fgeo",{"title":171,"path":172,"stem":173},"geo-claims","\u002Fv1\u002Freference\u002Fpackages\u002Fgeo-claims","1.v1\u002F12.reference\u002F2.packages\u002Fgeo-claims",{"title":175,"path":176,"stem":177},"geo-packs","\u002Fv1\u002Freference\u002Fpackages\u002Fgeo-packs","1.v1\u002F12.reference\u002F2.packages\u002Fgeo-packs",{"title":179,"path":180,"stem":181},"geo-vue","\u002Fv1\u002Freference\u002Fpackages\u002Fgeo-vue","1.v1\u002F12.reference\u002F2.packages\u002Fgeo-vue",{"title":183,"path":184,"stem":185},"historical-date","\u002Fv1\u002Freference\u002Fpackages\u002Fhistorical-date","1.v1\u002F12.reference\u002F2.packages\u002Fhistorical-date",{"title":187,"path":188,"stem":189},"identity","\u002Fv1\u002Freference\u002Fpackages\u002Fidentity","1.v1\u002F12.reference\u002F2.packages\u002Fidentity",{"title":191,"path":192,"stem":193},"identity-scope","\u002Fv1\u002Freference\u002Fpackages\u002Fidentity-scope","1.v1\u002F12.reference\u002F2.packages\u002Fidentity-scope",{"title":195,"path":196,"stem":197},"inquiry-board","\u002Fv1\u002Freference\u002Fpackages\u002Finquiry-board","1.v1\u002F12.reference\u002F2.packages\u002Finquiry-board",{"title":199,"path":200,"stem":201},"inzira","\u002Fv1\u002Freference\u002Fpackages\u002Finzira","1.v1\u002F12.reference\u002F2.packages\u002Finzira",{"title":203,"path":204,"stem":205},"isoko-client","\u002Fv1\u002Freference\u002Fpackages\u002Fisoko-client","1.v1\u002F12.reference\u002F2.packages\u002Fisoko-client",{"title":207,"path":208,"stem":209},"link-room","\u002Fv1\u002Freference\u002Fpackages\u002Flink-room","1.v1\u002F12.reference\u002F2.packages\u002Flink-room",{"title":211,"path":212,"stem":213},"notices","\u002Fv1\u002Freference\u002Fpackages\u002Fnotices","1.v1\u002F12.reference\u002F2.packages\u002Fnotices",{"title":215,"path":216,"stem":217},"one-time-mailbox","\u002Fv1\u002Freference\u002Fpackages\u002Fone-time-mailbox","1.v1\u002F12.reference\u002F2.packages\u002Fone-time-mailbox",{"title":219,"path":220,"stem":221},"portable-entitlements","\u002Fv1\u002Freference\u002Fpackages\u002Fportable-entitlements","1.v1\u002F12.reference\u002F2.packages\u002Fportable-entitlements",{"title":223,"path":224,"stem":225},"protocol-catalog","\u002Fv1\u002Freference\u002Fpackages\u002Fprotocol-catalog","1.v1\u002F12.reference\u002F2.packages\u002Fprotocol-catalog",{"title":227,"path":228,"stem":229},"protocol-core","\u002Fv1\u002Freference\u002Fpackages\u002Fprotocol-core","1.v1\u002F12.reference\u002F2.packages\u002Fprotocol-core",{"title":231,"path":232,"stem":233},"redact","\u002Fv1\u002Freference\u002Fpackages\u002Fredact","1.v1\u002F12.reference\u002F2.packages\u002Fredact",{"title":235,"path":236,"stem":237},"relay-envelope","\u002Fv1\u002Freference\u002Fpackages\u002Frelay-envelope","1.v1\u002F12.reference\u002F2.packages\u002Frelay-envelope",{"title":239,"path":240,"stem":241},"requirements","\u002Fv1\u002Freference\u002Fpackages\u002Frequirements","1.v1\u002F12.reference\u002F2.packages\u002Frequirements",{"title":243,"path":244,"stem":245},"signed-request","\u002Fv1\u002Freference\u002Fpackages\u002Fsigned-request","1.v1\u002F12.reference\u002F2.packages\u002Fsigned-request",{"title":247,"path":248,"stem":249},"storage","\u002Fv1\u002Freference\u002Fpackages\u002Fstorage","1.v1\u002F12.reference\u002F2.packages\u002Fstorage",{"title":251,"path":252,"stem":253},"suite-identity","\u002Fv1\u002Freference\u002Fpackages\u002Fsuite-identity","1.v1\u002F12.reference\u002F2.packages\u002Fsuite-identity",{"title":255,"path":256,"stem":257},"testimony","\u002Fv1\u002Freference\u002Fpackages\u002Ftestimony","1.v1\u002F12.reference\u002F2.packages\u002Ftestimony",{"title":259,"path":260,"stem":261},"testimony-qa","\u002Fv1\u002Freference\u002Fpackages\u002Ftestimony-qa","1.v1\u002F12.reference\u002F2.packages\u002Ftestimony-qa",{"title":263,"path":264,"stem":265},"trust-graph","\u002Fv1\u002Freference\u002Fpackages\u002Ftrust-graph","1.v1\u002F12.reference\u002F2.packages\u002Ftrust-graph",{"title":267,"path":268,"stem":269},"web-session","\u002Fv1\u002Freference\u002Fpackages\u002Fweb-session","1.v1\u002F12.reference\u002F2.packages\u002Fweb-session",{"title":271,"path":272,"stem":273},"webauthn-lock","\u002Fv1\u002Freference\u002Fpackages\u002Fwebauthn-lock","1.v1\u002F12.reference\u002F2.packages\u002Fwebauthn-lock",{"title":275,"path":276,"stem":277},"Apps","\u002Fv1\u002Freference\u002Fapps","1.v1\u002F12.reference\u002F3.apps",{"title":279,"path":280,"stem":281},"Services","\u002Fv1\u002Freference\u002Fservices","1.v1\u002F12.reference\u002F4.services",{"title":22,"path":283,"stem":284},"\u002Fv1\u002Freference\u002Fprotocols","1.v1\u002F12.reference\u002F5.protocols","i-lucide-library","i-lucide-book-open",{"title":288,"icon":289,"path":290,"stem":291,"children":292,"page":470},"v0 · summer 2026","i-lucide-archive","\u002Fv0","2.v0",[293,329,365,401,436,452,471],{"title":294,"path":295,"stem":296,"children":297,"icon":328},"Getting Started","\u002Fv0\u002Fgetting-started","2.v0\u002F1.getting-started\u002F1.index",[298,300,304,308,312,316,320,324],{"title":299,"path":295,"stem":296},"What is this?",{"title":301,"path":302,"stem":303},"Web, Desktop, or Mobile","\u002Fv0\u002Fgetting-started\u002Faccess-methods","2.v0\u002F1.getting-started\u002F2.access-methods",{"title":305,"path":306,"stem":307},"Before You Begin","\u002Fv0\u002Fgetting-started\u002Fbefore-you-begin","2.v0\u002F1.getting-started\u002F3.before-you-begin",{"title":309,"path":310,"stem":311},"Install the Apps","\u002Fv0\u002Fgetting-started\u002Finstall","2.v0\u002F1.getting-started\u002F4.install",{"title":313,"path":314,"stem":315},"F-Droid, Explained","\u002Fv0\u002Fgetting-started\u002Ffdroid","2.v0\u002F1.getting-started\u002F5.fdroid",{"title":317,"path":318,"stem":319},"Your First Family Tree","\u002Fv0\u002Fgetting-started\u002Fyour-first-tree","2.v0\u002F1.getting-started\u002F6.your-first-tree",{"title":321,"path":322,"stem":323},"Invite Family Members","\u002Fv0\u002Fgetting-started\u002Finvite-family","2.v0\u002F1.getting-started\u002F7.invite-family",{"title":325,"path":326,"stem":327},"Connect Family Branches","\u002Fv0\u002Fgetting-started\u002Fconnect-branches","2.v0\u002F1.getting-started\u002F8.connect-branches","i-lucide-footprints",{"title":330,"path":331,"stem":332,"children":333,"icon":45},"Abantu","\u002Fv0\u002Fabantu","2.v0\u002F2.abantu\u002F1.index",[334,336,339,342,345,349,353,357,361],{"title":335,"path":331,"stem":332},"Abantu — Community Governance",{"title":12,"path":337,"stem":338},"\u002Fv0\u002Fabantu\u002Fcommunities","2.v0\u002F2.abantu\u002F2.communities",{"title":22,"path":340,"stem":341},"\u002Fv0\u002Fabantu\u002Fprotocols","2.v0\u002F2.abantu\u002F3.protocols",{"title":34,"path":343,"stem":344},"\u002Fv0\u002Fabantu\u002Fprojects","2.v0\u002F2.abantu\u002F4.projects",{"title":346,"path":347,"stem":348},"Proposals and Roles","\u002Fv0\u002Fabantu\u002Fproposals-and-roles","2.v0\u002F2.abantu\u002F5.proposals-and-roles",{"title":350,"path":351,"stem":352},"Sync and Relay","\u002Fv0\u002Fabantu\u002Fsync-and-relay","2.v0\u002F2.abantu\u002F6.sync-and-relay",{"title":354,"path":355,"stem":356},"Identity and Devices","\u002Fv0\u002Fabantu\u002Fidentity-and-devices","2.v0\u002F2.abantu\u002F7.identity-and-devices",{"title":358,"path":359,"stem":360},"Data and Privacy","\u002Fv0\u002Fabantu\u002Fprivacy","2.v0\u002F2.abantu\u002F8.privacy",{"title":362,"path":363,"stem":364},"Plugins and Extensibility","\u002Fv0\u002Fabantu\u002Fplugins-and-extensibility","2.v0\u002F2.abantu\u002F9.plugins-and-extensibility",{"title":366,"path":367,"stem":368,"children":369,"icon":400},"Iwacu","\u002Fv0\u002Fiwacu","2.v0\u002F3.iwacu\u002F1.index",[370,372,376,380,384,388,392,396],{"title":371,"path":367,"stem":368},"Iwacu — Family Tree",{"title":373,"path":374,"stem":375},"Terminal Commands","\u002Fv0\u002Fiwacu\u002Fterminal-commands","2.v0\u002F3.iwacu\u002F2.terminal-commands",{"title":377,"path":378,"stem":379},"Manage Page and Sync","\u002Fv0\u002Fiwacu\u002Fmanage-and-sync","2.v0\u002F3.iwacu\u002F3.manage-and-sync",{"title":381,"path":382,"stem":383},"Family History and the Atlas","\u002Fv0\u002Fiwacu\u002Fhistory-and-atlas","2.v0\u002F3.iwacu\u002F4.history-and-atlas",{"title":385,"path":386,"stem":387},"Script Editor","\u002Fv0\u002Fiwacu\u002Fscript-editor","2.v0\u002F3.iwacu\u002F5.script-editor",{"title":389,"path":390,"stem":391},"Inviting and Connecting","\u002Fv0\u002Fiwacu\u002Finviting-and-connecting","2.v0\u002F3.iwacu\u002F6.inviting-and-connecting",{"title":393,"path":394,"stem":395},"Desktop App and Devices","\u002Fv0\u002Fiwacu\u002Fdesktop-and-devices","2.v0\u002F3.iwacu\u002F7.desktop-and-devices",{"title":397,"path":398,"stem":399},"Reference","\u002Fv0\u002Fiwacu\u002Freference","2.v0\u002F3.iwacu\u002F8.reference","i-lucide-trees",{"title":402,"path":403,"stem":404,"children":405,"icon":435},"Isoko","\u002Fv0\u002Fisoko","2.v0\u002F4.isoko\u002F1.index",[406,408,411,415,419,423,427,431],{"title":407,"path":403,"stem":404},"Isoko — Local Marketplace",{"title":22,"path":409,"stem":410},"\u002Fv0\u002Fisoko\u002Fprotocols","2.v0\u002F4.isoko\u002F2.protocols",{"title":412,"path":413,"stem":414},"Listings and Messaging","\u002Fv0\u002Fisoko\u002Flistings-and-messaging","2.v0\u002F4.isoko\u002F3.listings-and-messaging",{"title":416,"path":417,"stem":418},"Tracked Deliveries","\u002Fv0\u002Fisoko\u002Fdeliveries","2.v0\u002F4.isoko\u002F4.deliveries",{"title":420,"path":421,"stem":422},"Wallet and Reputation","\u002Fv0\u002Fisoko\u002Fwallet-and-reputation","2.v0\u002F4.isoko\u002F5.wallet-and-reputation",{"title":424,"path":425,"stem":426},"Market Cells","\u002Fv0\u002Fisoko\u002Fcells","2.v0\u002F4.isoko\u002F6.cells",{"title":428,"path":429,"stem":430},"Safety Scanner","\u002Fv0\u002Fisoko\u002Fsafety","2.v0\u002F4.isoko\u002F7.safety",{"title":432,"path":433,"stem":434},"Web Version, Privacy, and Limitations","\u002Fv0\u002Fisoko\u002Fweb-and-privacy","2.v0\u002F4.isoko\u002F8.web-and-privacy","i-lucide-store",{"title":437,"path":438,"stem":439,"children":440,"icon":451},"Playground","\u002Fv0\u002Fplayground","2.v0\u002F5.playground\u002F1.index",[441,443,447],{"title":442,"path":438,"stem":439},"Playground — Try It in the Browser",{"title":444,"path":445,"stem":446},"Using the Tutorials","\u002Fv0\u002Fplayground\u002Fusing-tutorials","2.v0\u002F5.playground\u002F2.using-tutorials",{"title":448,"path":449,"stem":450},"How Tutorials Are Made","\u002Fv0\u002Fplayground\u002Fbuilding-tutorials","2.v0\u002F5.playground\u002F3.building-tutorials","i-lucide-flask-conical",{"title":453,"icon":454,"path":455,"stem":456,"children":457,"page":470},"Relays","i-lucide-server","\u002Fv0\u002Frelays","2.v0\u002F6.relays",[458,462,466],{"title":459,"path":460,"stem":461},"Relays Overview","\u002Fv0\u002Frelays\u002Foverview","2.v0\u002F6.relays\u002F1.overview",{"title":463,"path":464,"stem":465},"Deploy a Relay Node","\u002Fv0\u002Frelays\u002Frelay","2.v0\u002F6.relays\u002F2.relay",{"title":467,"path":468,"stem":469},"Configure Tor Hidden Service","\u002Fv0\u002Frelays\u002Ftor","2.v0\u002F6.relays\u002F3.tor",false,{"title":472,"icon":473,"path":474,"stem":475,"children":476,"page":470},"Privacy & Security","i-lucide-shield","\u002Fv0\u002Fprivacy","2.v0\u002F7.privacy",[477,481,485],{"title":478,"path":479,"stem":480},"How Privacy Works Here","\u002Fv0\u002Fprivacy\u002Fhow-it-works","2.v0\u002F7.privacy\u002F1.how-it-works",{"title":482,"path":483,"stem":484},"Device Security","\u002Fv0\u002Fprivacy\u002Fdevice","2.v0\u002F7.privacy\u002F2.device",{"title":486,"path":487,"stem":488},"Under Pressure","\u002Fv0\u002Fprivacy\u002Fcoercion","2.v0\u002F7.privacy\u002F3.coercion",{"id":490,"title":448,"body":491,"description":1082,"extension":1083,"links":1084,"meta":1085,"navigation":1086,"path":449,"seo":1087,"stem":450,"__hash__":1088},"docs\u002F2.v0\u002F5.playground\u002F3.building-tutorials.md",{"type":492,"value":493,"toc":1075},"minimark",[494,498,507,519,524,552,568,572,826,839,843,850,959,977,980,984,1043,1049,1053,1060,1063,1071],[495,496,448],"h1",{"id":497},"how-tutorials-are-made",[499,500,501,502,506],"p",{},"This page is for anyone editing or adding a tutorial, not for someone just taking one — see ",[503,504,505],"a",{"href":445},"Using the tutorials"," for that.",[499,508,509,510,514,515,518],{},"Every tutorial is a plain YAML file under the playground app's ",[511,512,513],"code",{},"app\u002Ftutorials\u002F"," directory. There's an editor for them, but it only exists for local development — the deployed playground.paramira.org is a static build with no server behind it, so ",[511,516,517],{},"\u002Fdev\u002Ftutorials"," is structurally unreachable there. You edit tutorials by running the playground locally.",[520,521,523],"h2",{"id":522},"the-editor","The editor",[499,525,526,527,530,531,534,535,538,539,543,544,547,548,551],{},"With the playground running locally (",[511,528,529],{},"pnpm dev"," in ",[511,532,533],{},"apps\u002Fplayground","), open ",[511,536,537],{},"http:\u002F\u002Flocalhost:3000\u002Fdev\u002Ftutorials",". It lists every tutorial with ",[540,541,542],"strong",{},"Preview",", ",[540,545,546],{},"Edit",", and ",[540,549,550],{},"Delete",", and a form for creating or editing one — every field below has a matching input there, so you rarely need to hand-edit the YAML directly.",[553,554,557],"callout",{"color":555,"icon":556},"sky","i-lucide-info",[499,558,559,560,563,564,567],{},"The embedded panes only render locally if abantu and iwacu are actually built (",[511,561,562],{},"build-abantu.sh"," \u002F ",[511,565,566],{},"build-iwacu.sh"," in the playground app) — otherwise the preview iframe has nothing real to show.",[520,569,571],{"id":570},"the-shape-of-a-tutorial","The shape of a tutorial",[573,574,579],"pre",{"className":575,"code":576,"language":577,"meta":578,"style":578},"language-yaml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","id: discover-tree\ntitle: Explore the family tree canvas\nsummary: A short description shown on the tutorials list.\napp: iwacu              # top-level menu\ncategory: Features      # second-level menu\ndirectory: Tree         # third-level menu\norder: 3                # lower shows first within its menu\ndepends: [community-and-protocols]   # soft gate — a warning, not enforced\nsetup: seed-tree         # optional \"step 0\" button\nteardown: clear-tree     # optional, enabled once complete\nsteps:\n  - title: Create a tree\n    body: What the learner reads for this step.\n    pane: iwacu           # shell | abantu | iwacu\n    route: \u002F               # the pane's own route, app-relative\n    check: tree-exists      # see \"Checks\" below\n    actions:\n      - text: Start with Demo Tree   # spotlighted, in order\n","yaml","",[511,580,581,598,609,620,635,649,663,678,698,712,726,735,749,760,773,787,801,809],{"__ignoreMap":578},[582,583,586,590,594],"span",{"class":584,"line":585},"line",1,[582,587,589],{"class":588},"swJcz","id",[582,591,593],{"class":592},"sMK4o",":",[582,595,597],{"class":596},"sfazB"," discover-tree\n",[582,599,601,604,606],{"class":584,"line":600},2,[582,602,603],{"class":588},"title",[582,605,593],{"class":592},[582,607,608],{"class":596}," Explore the family tree canvas\n",[582,610,612,615,617],{"class":584,"line":611},3,[582,613,614],{"class":588},"summary",[582,616,593],{"class":592},[582,618,619],{"class":596}," A short description shown on the tutorials list.\n",[582,621,623,626,628,631],{"class":584,"line":622},4,[582,624,625],{"class":588},"app",[582,627,593],{"class":592},[582,629,630],{"class":596}," iwacu",[582,632,634],{"class":633},"sHwdD","              # top-level menu\n",[582,636,638,641,643,646],{"class":584,"line":637},5,[582,639,640],{"class":588},"category",[582,642,593],{"class":592},[582,644,645],{"class":596}," Features",[582,647,648],{"class":633},"      # second-level menu\n",[582,650,652,655,657,660],{"class":584,"line":651},6,[582,653,654],{"class":588},"directory",[582,656,593],{"class":592},[582,658,659],{"class":596}," Tree",[582,661,662],{"class":633},"         # third-level menu\n",[582,664,666,669,671,675],{"class":584,"line":665},7,[582,667,668],{"class":588},"order",[582,670,593],{"class":592},[582,672,674],{"class":673},"sbssI"," 3",[582,676,677],{"class":633},"                # lower shows first within its menu\n",[582,679,681,684,686,689,692,695],{"class":584,"line":680},8,[582,682,683],{"class":588},"depends",[582,685,593],{"class":592},[582,687,688],{"class":592}," [",[582,690,691],{"class":596},"community-and-protocols",[582,693,694],{"class":592},"]",[582,696,697],{"class":633},"   # soft gate — a warning, not enforced\n",[582,699,701,704,706,709],{"class":584,"line":700},9,[582,702,703],{"class":588},"setup",[582,705,593],{"class":592},[582,707,708],{"class":596}," seed-tree",[582,710,711],{"class":633},"         # optional \"step 0\" button\n",[582,713,715,718,720,723],{"class":584,"line":714},10,[582,716,717],{"class":588},"teardown",[582,719,593],{"class":592},[582,721,722],{"class":596}," clear-tree",[582,724,725],{"class":633},"     # optional, enabled once complete\n",[582,727,729,732],{"class":584,"line":728},11,[582,730,731],{"class":588},"steps",[582,733,734],{"class":592},":\n",[582,736,738,741,744,746],{"class":584,"line":737},12,[582,739,740],{"class":592},"  -",[582,742,743],{"class":588}," title",[582,745,593],{"class":592},[582,747,748],{"class":596}," Create a tree\n",[582,750,752,755,757],{"class":584,"line":751},13,[582,753,754],{"class":588},"    body",[582,756,593],{"class":592},[582,758,759],{"class":596}," What the learner reads for this step.\n",[582,761,763,766,768,770],{"class":584,"line":762},14,[582,764,765],{"class":588},"    pane",[582,767,593],{"class":592},[582,769,630],{"class":596},[582,771,772],{"class":633},"           # shell | abantu | iwacu\n",[582,774,776,779,781,784],{"class":584,"line":775},15,[582,777,778],{"class":588},"    route",[582,780,593],{"class":592},[582,782,783],{"class":596}," \u002F",[582,785,786],{"class":633},"               # the pane's own route, app-relative\n",[582,788,790,793,795,798],{"class":584,"line":789},16,[582,791,792],{"class":588},"    check",[582,794,593],{"class":592},[582,796,797],{"class":596}," tree-exists",[582,799,800],{"class":633},"      # see \"Checks\" below\n",[582,802,804,807],{"class":584,"line":803},17,[582,805,806],{"class":588},"    actions",[582,808,734],{"class":592},[582,810,812,815,818,820,823],{"class":584,"line":811},18,[582,813,814],{"class":592},"      -",[582,816,817],{"class":588}," text",[582,819,593],{"class":592},[582,821,822],{"class":596}," Start with Demo Tree",[582,824,825],{"class":633},"   # spotlighted, in order\n",[499,827,828,563,830,563,832,834,835,838],{},[511,829,625],{},[511,831,640],{},[511,833,654],{}," are free text — they only have to agree with what other tutorials already use, so the three-level menu on ",[511,836,837],{},"\u002Ftutorials"," stays coherent. The editor's own fields autocomplete from what's already out there.",[520,840,842],{"id":841},"checks","Checks",[499,844,845,846,849],{},"A ",[511,847,848],{},"check"," is a name from a small, fixed list — not a scripting language, deliberately. Each one is a real function that reads the embedded app's actual state and returns yes or no:",[851,852,853,866],"table",{},[854,855,856],"thead",{},[857,858,859,863],"tr",{},[860,861,862],"th",{},"Check",[860,864,865],{},"What it reads",[867,868,869,880,890,900,910,923,939,949],"tbody",{},[857,870,871,877],{},[872,873,874],"td",{},[511,875,876],{},"manual",[872,878,879],{},"Nothing — always passes on a button click",[857,881,882,887],{},[872,883,884],{},[511,885,886],{},"identity-exists",[872,888,889],{},"Whether the shell itself has an identity",[857,891,892,897],{},[872,893,894],{},[511,895,896],{},"protocol-adopted",[872,898,899],{},"The directory's record of your adopted protocols",[857,901,902,907],{},[872,903,904],{},[511,905,906],{},"community-joined",[872,908,909],{},"abantu's own local list of joined communities",[857,911,912,920],{},[872,913,914,563,917],{},[511,915,916],{},"tree-exists",[511,918,919],{},"tree-connected",[872,921,922],{},"iwacu's local tree state",[857,924,925,936],{},[872,926,927,563,930,563,933],{},[511,928,929],{},"moment-added",[511,931,932],{},"article-saved",[511,934,935],{},"script-saved",[872,937,938],{},"iwacu's local history\u002Fscript storage",[857,940,941,946],{},[872,942,943],{},[511,944,945],{},"url-path",[872,947,948],{},"The embedded pane's current route — app-agnostic, works for any app",[857,950,951,956],{},[872,952,953],{},[511,954,955],{},"ui-text",[872,957,958],{},"Whether some text is currently visible in the pane — also app-agnostic",[499,960,961,962,965,966,968,969,971,972,976],{},"Most of these work because the embedded apps are ",[540,963,964],{},"same-origin"," with the playground shell — the same trick that lets your identity carry across abantu, iwacu, and isoko in the real apps carries over here too, so a check can read an app's IndexedDB or its current URL directly, with no special hook built into that app for it. ",[511,967,945],{}," and ",[511,970,955],{}," don't even need that: they just look at what's on screen, so they work for a step in ",[973,974,975],"em",{},"any"," app without touching its internals at all.",[499,978,979],{},"Adding a genuinely new kind of check means adding one function to the shared list — after that, any tutorial can use it by name.",[520,981,983],{"id":982},"actions-the-spotlight","Actions — the spotlight",[573,985,987],{"className":575,"code":986,"language":577,"meta":578,"style":578},"actions:\n  - text: Start with Demo Tree     # matched against visible button\u002Flink text\n  - selector: '[title=\"Save\"]'      # or a CSS selector, for icon-only controls\n    label: Save your script          # optional tooltip; defaults to text\u002Fselector\n",[511,988,989,996,1009,1030],{"__ignoreMap":578},[582,990,991,994],{"class":584,"line":585},[582,992,993],{"class":588},"actions",[582,995,734],{"class":592},[582,997,998,1000,1002,1004,1006],{"class":584,"line":600},[582,999,740],{"class":592},[582,1001,817],{"class":588},[582,1003,593],{"class":592},[582,1005,822],{"class":596},[582,1007,1008],{"class":633},"     # matched against visible button\u002Flink text\n",[582,1010,1011,1013,1016,1018,1021,1024,1027],{"class":584,"line":611},[582,1012,740],{"class":592},[582,1014,1015],{"class":588}," selector",[582,1017,593],{"class":592},[582,1019,1020],{"class":592}," '",[582,1022,1023],{"class":596},"[title=\"Save\"]",[582,1025,1026],{"class":592},"'",[582,1028,1029],{"class":633},"      # or a CSS selector, for icon-only controls\n",[582,1031,1032,1035,1037,1040],{"class":584,"line":622},[582,1033,1034],{"class":588},"    label",[582,1036,593],{"class":592},[582,1038,1039],{"class":596}," Save your script",[582,1041,1042],{"class":633},"          # optional tooltip; defaults to text\u002Fselector\n",[499,1044,1045,1046,1048],{},"Multiple entries are spotlighted one at a time — the learner clicks the first for real, and the highlight moves itself to the next. It's a visual aid layered on top of ",[511,1047,848],{},", never a substitute for it: nothing about clicking through a spotlight marks a step complete on its own.",[520,1050,1052],{"id":1051},"setup-and-teardown","Setup and teardown",[499,1054,1055,968,1057,1059],{},[511,1056,703],{},[511,1058,717],{}," are also names from a small fixed list, matching the same idea as checks but in reverse — instead of reading state, they write it, so a learner can jump into a tutorial without redoing every prerequisite by hand.",[499,1061,1062],{},"Where a real signed action is what the tutorial actually needs — joining a test community, adopting a protocol — setup performs the real thing, the same way the app itself would, rather than faking the end state. Local-only state (a tree, a saved script) is written directly. Teardown is the same idea in reverse: it undoes what setup or the tutorial's own steps left behind, and its button only becomes clickable once the tutorial is actually complete.",[1064,1065,1068],"u-button",{"color":1066,"to":438,"trailing-icon":451,"variant":1067},"neutral","outline",[499,1069,1070],{},"Back to the playground",[1072,1073,1074],"style",{},"html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":578,"searchDepth":585,"depth":600,"links":1076},[1077,1078,1079,1080,1081],{"id":522,"depth":600,"text":523},{"id":570,"depth":600,"text":571},{"id":841,"depth":600,"text":842},{"id":982,"depth":600,"text":983},{"id":1051,"depth":600,"text":1052},"The local-only tutorial editor, the YAML schema behind every tutorial, and how a \"Check\" actually verifies something.","md",null,{},true,{"title":448,"description":1082},"g6dq2qzBowLZFpFDXJDuk5HEbNaSSbAFey6VL1-Ax34",[1090,1092],{"title":444,"path":445,"stem":446,"description":1091,"children":-1},"How to find a tutorial, what the guided \"where to click\" spotlight does, and how a step knows you actually did it.",{"title":459,"path":460,"stem":461,"description":1093,"children":-1},"What it means to run your own relay server, why you might want to, and what is required.",1791986798937]