{#if key}
·
{/if}
{#if me}{me} on Soulseek{:else}not signed in to Soulseek{/if}
{online ? "online" : "offline"}
{#if ownLinkCurrent}linked{/if}
{#if profile}
{profile.from_ledger ? "profile published" : `profile synced as of ${fmtClock(community.profileAt)}`} · rev {profile.sequence}
{:else if key}
nothing published yet
{:else if freenetOn}
{status.text}
{:else}
SoulStream identity off
{/if}
{friendCount()} friends · {slsk.buddies.length} contacts · {joinedNames.length} rooms · {convos.length} conversations
{#if hubOpen}
{:else if community.section === "inbox"}
{#if pendingIn().length}
{#each pendingIn() as f (f.id)}
{f.username ? display(f.username) : community.remoteProfiles[f.persona_key]?.display_name || `SoulStream ID ${fpShort(f.persona_key)}`} wants to be friends
SoulStream{f.carry === "inbox" ? "sealed · via your encrypted inbox · signed by their key" : "signed request · their ID proven over Soulseek"}·open until {fmtWhen(f.expires_at * 1000)}
friends are two signed answers — yours goes back to them over Soulseek
{/each}
{/if}
{#if community.shares.length}
{#each community.shares as c (c.id)}
{@const pv = community.sharePreviews[c.id]}
{c.name}
{c.entry_count} {c.entry_count === 1 ? "track" : "tracks"} · playlist · shared by {#if c.from_username}{:else}SoulStream ID {fpShort(c.from_key)}{/if} {fmtWhen(c.received_at * 1000)}
SoulStreamsigned by {fpShort(c.owner_key)}
{#if c.carry === "inbox"}· sealed · via your encrypted inbox{/if}
{#if pv && !pv.pending && !pv.error && !pv.withdrawn}·verified · revision {pv.revision_seq}{/if}
{#if pv?.withdrawn}·withdrawn by the owner{/if}
{#if pv?.error}·{pv.error}{/if}
tracks resolve against your library first; the rest become Soulseek streams
{#if p.presence === "online"}onlineSoulseek, now
{:else if p.presence === "away"}awaySoulseek, now
{:else if p.st.exists === false}unknown userSoulseek has no such name
{:else if fmtSeen(community.lastSeen[p.u])}{fmtSeen(community.lastSeen[p.u])}last seen by this device
{:else}offlinenot seen by this device yet{/if}
{/snippet}
{#if peopleOnline.length}
Online {peopleOnline.length}
{#each peopleOnline as p (p.u)}{@render personRow(p, false)}{/each}
{/if}
{#if peopleAway.length}
Away {peopleAway.length}
{#each peopleAway as p (p.u)}{@render personRow(p, false)}{/each}
{/if}
{#if peopleOff.length}
Offline or unknown {peopleOff.length}
{#each peopleOff as p (p.u)}{@render personRow(p, true)}{/each}
{/if}
Contacts are yours and stay on this device. "Trusted" is a permission you granted, not a verified identity. Petnames,
groups and notes live in the profile drawer — click a name.
{/if}
{:else if community.section === "discover"}
{slsk.activeRoom ? `In #${slsk.activeRoom} right now` : "In a room right now"}
from the room roster{#if activeRoom} · {fmtCount(activeRoom.users.length)} here{/if}
{#if roomPeople.length}
{#each roomPeople as u (u.username)}
{/each}
{:else}
{activeRoom ? "Everyone in this room is already a contact." : "Join a room and the people in it show up here, with the room as their provenance."}
{#if !activeRoom}{/if}
{/if}
Recent peers
from your transfers this session
{#if recentPeers.length}
{#each recentPeers as p (p.u)}
{/each}
{:else}
Nobody yet. People who send you files, or take files from you, appear here for the session.
{/if}
Similar Soulseek interests
the server's match on declared likes · not follows
{#if community.similar?.users?.length}
{#each community.similar.users.slice(0, 24) as su (su.username)}
{/each}
{:else if community.busy.similar}
Asking the server…
{:else}
{community.similar?.error ? "The server did not answer." : online ? "The server matches people on the likes you declare on Soulseek — SoulStream has none set for you yet, so this shelf is empty." : "Sign in to Soulseek to ask the server."}
{#if online}{/if}
{/if}
Library overlap
computed on this device, after an explicit browse
Nothing computed yet. Browse a person's shares and SoulStream compares them with your library locally — nothing is uploaded to do it. The comparison itself is the next piece of this shelf.
There is no global directory here and no "people you may know". Every shelf says where its people came from. Freenet
discovery indexes are opt-in, curator-run, and currently off.
{:else if community.section === "spaces"}
No Spaces yet
A Space is a persistent SoulStream community on Freenet with its own member keys — invitation only, encrypted
when private, and never a Soulseek Room in disguise. The research behind it is done; the Space contract itself
is the next piece of the Freenet track, so nothing here is live yet.
beta · not live
{:else if community.section === "you"}
{#if key}
Your public profile SoulStream
Anyone who has your SoulStream ID can fetch this. It is signed by your persona key and replicated —
publishing is not something that can be fully undone.
{#if avatarUrl}{/if}
{#if community.busy.avatar}
Preparing your photo and publishing it — a few seconds normally; the first publication can take longer.
{:else if profile?.avatar_note && profile.avatar_note !== "none published"}
{profile.avatar_note}
{/if}
Display names are not unique. People you meet may give you a private petname; you cannot see it.
{#if community.busy.publish}
pending publication
{:else if community.busy.profile}
reading from the network — up to a minute
{:else if profile}
{profile.from_ledger ? "published from this device" : `synced as of ${fmtClock(community.profileAt)}`} · revision {profile.sequence}
{:else}
nothing published yet
{/if}
{#if community.profileError}{community.profileError}{/if}
{:else}
Your SoulStream identity SoulStream
{#if !freenetOn}
A SoulStream identity is a key pair held by your local Freenet node. Turn the Freenet layer on
(right) and the node will hold it; nothing is published until you say so.
{:else if !nodeUp}
Waiting for the node — {status.text}. Identity needs a connected node.
{:else}
Create a fresh key here, or bring one back from a recovery file. Creating one publishes nothing;
your profile is a separate button, later.
{/if}
{#if community.error}
{community.error}
{/if}
{/if}
{#if key}
Your public playlists {community.published.filter((p) => !p.withdrawn).length}
{#if !community.published.length}
Nothing published yet. Open a playlist and choose Share on SoulStream: a signed manifest goes to the network under your ID — titles, artists, albums, durations, your notes; never a file, never a path.
{:else}
{#each community.published as p (p.playlist_id)}
Withdrawing stops your pointer; copies others already fetched stay with them.
{/if}
Your SoulStream ID
The fingerprint of your persona key. It is the stable you — names change, this does not. Share it as
text; nothing else identifies you across networks.
{#each fpGroups(key) as g, i (i)}{#if i}·{/if}{g}{/each}
profile today; playlists, friend links, Soulseek link and Space links as those land
Delegate
{fpShort(community.persona?.delegate_key)}
Recovery
Your identity lives in the node's key custody on this machine. Export a recovery file — encrypted
with a passphrase you choose — and keep it somewhere that is not this disk.
{#if exportDone}
Written: {exportDone.path} ({exportDone.bytes} bytes). Test it on another machine before you need it.
{/if}
{#if confirmRotate}
Rotating signs a transition with the old key; friends re-verify on their next fetch.
{:else if confirmRemove}
This deletes the key from this node. Without a recovery file, this identity ends.
{:else}
{/if}
{#if community.error}
{community.error}
{/if}
{/if}
Networks
Soulseek {online ? "online" : "offline"}
{#if me}Signed in as {me} · {fmtCount(network.shareFiles)} files shared.{:else}Not signed in — see Settings.{/if}
{#if !key}
Create a SoulStream identity to link this account to it.
{:else if !me}
Sign in to Soulseek to link this account to your identity.
{:else if ownLinkCurrent}
Linked to this identity — proof verified {new Date(ownLink.verified_at * 1000).toLocaleString()} through a Soulseek message to yourself. Other SoulStream users who ask over Soulseek now get your signed ID; nothing is published.
{:else}
Not linked to your identity. Linking sends one message to yourself over Soulseek and verifies the signed answer — nothing is published, and from then on other SoulStream users who ask get your signed ID.
{/if}
{#if key && me}
{#if ownLinkCurrent}
{:else}
{#if !nodeUp}needs the node connected{/if}
{/if}
{/if}
Freenet experimental
{#if freenetOn}
Local node on 127.0.0.1:{community.freenet?.ws_port ?? 7509} · {status.text}
{#if statusKind(community.freenet?.status) === "node-absent"}
{#if community.nodeInfo?.binary}
runs the installed peer{#if community.nodeInfo.version} ({community.nodeInfo.version}){/if} in the background · telemetry pinned off · data in the app folder
{:else}
No Freenet peer found on this machine — install it (cargo install freenet) and check again.
{/if}
{:else if community.nodeInfo?.started_by_app}
started by SoulStream · keeps running when the app closes; this button stops it
{/if}
{:else}
Off. Carries your identity and profile; later playlists, friend links and Spaces. Turning it on publishes nothing. Turning it off is instant and touches nothing else in the app.
{/if}
Before you rely on it — seven things that are true
A desktop background peer must run; it uses network, disk, memory and CPU.
The network is alpha. Things you publish are replicated and cannot be guaranteed erased.
Freenet is not an anonymity service.
The node's own diagnostics are a node setting SoulStream pins off; verify after upgrades.
Nothing is published when you enable this. Publishing is always a button.
Nothing here ever says "online" — a successful fetch is not presence.
Phones and TVs cannot run the same peer today.
{#if freenetOn}
{#if key}
{#if community.inbox?.published}
encrypted inbox · key {community.inbox.box_key_id}{community.inbox.last_check ? `checked ${fmtWhen(community.inbox.last_check * 1000)} · ` : ""}friend requests and shares arrive sealed to a key kept on this device; a persona restored elsewhere publishes a new one
{:else}
lets other SoulStream users send you friend requests and shares sealed, without Soulseek in between
{/if}
{/if}
{/if}
Devices later
A paired device gets its own key and a signed grant — it never receives your root key or Soulseek password. Comes after the profile work settles.