Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src-docs/shared_state/conflicts.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,13 @@ both a Total Order of messages and a "single source of truth" can not be assumed
Many webxdc applications are incapable of producing conflicts,
either because they do not use the network communication APIs,
or because any given data structure can only have one writer.
Alternatively, an application can designate a "central" authority
by checking [`webxdc.isAppSender`](../spec/selfAddr_and_selfName.html#isappsender)
to identify whether it is running for the user who shared the app.
This peer could then authoritatively resolve conflicts or coordinate state updates.
However, developers should be aware that if the app depends entirely on the sender being online,
the app's availability will be limited when the sender is offline.

For example, many of the available [webxdc games](https://webxdc.org/apps/) offer a high-score table
and how users scored will typically be reported back to the chat.
Such a gaming app will simply post their user's highscore
Expand Down
2 changes: 2 additions & 0 deletions src-docs/shared_state/crdts.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ While this behaviour can be very helpful for application developers,
it may not free you entirely from having to think about network conditions.
_Eventually-consistent_ application state should generally be treated as
subjective, which can be a significant shift if you are used to having a server acting as an authority.
While you can use [`webxdc.isAppSender`](../spec/selfAddr_and_selfName.html#isappsender) to nominate a peer
(the app sender) to act as a kind of server, this introduces a dependency on that peer being online.
That means that conditional behaviour that you'd usually treat as _yes_ and _no_,
may instead behave more like _currently_ and _not yet_.

Expand Down
19 changes: 19 additions & 0 deletions src-docs/shared_state/practical.md
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,25 @@ As for the matter of duplicate ids in the `order` array,
the rendering code which constructs the app's UI from this data
could ignore repeated elements when iterating over them.

## Centralized coordination

While CRDTs are designed for peer-to-peer operation,
you may sometimes want to designate one client as a "coordinator".
By checking [`webxdc.isAppSender`](../spec/selfAddr_and_selfName.html#isappsender),
an app can identify whether it is running for the peer
that initially shared the app.
This "sender" instance can then take on special roles,
such as authoritatively resolving state conflicts,
for example by letting the app sender's updates always win.

However, use this model with care:
if your app logic requires the sender to be online to function,
it will be unusable whenever the sender is offline or has left the chat.
One further complication occurs if the app sender
has multiple devices running the app simultaneously,
with each device possibly regarding itself as the central coordinator
and producing conflicting application states.

## Learning more

Many more examples can be found throughout
Expand Down
7 changes: 7 additions & 0 deletions src-docs/spec/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## [1.4] - 2026-04-16

### New APIs

- add `webxdc.isAppSender` and `webxdc.isBroadcast` to allow apps to determine
their role and if they are in a broadcast chat

## [1.3] - 2026-02-11

### Other changes
Expand Down
3 changes: 3 additions & 0 deletions src-docs/spec/messenger.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ When starting a web view for a webxdc app to run, messenger implementors

- MUST support `<meta name="viewport" ...>` is useful especially as webviews from different platforms have different defaults

- MUST support `window.webxdc.isAppSender` and `window.webxdc.isBroadcast`
to allow apps to determine their role and if they are in a broadcast chat.

- MUST support `<input type="file">` to allow importing of files;
see [`sendToChat()`](../spec/sendToChat.md) for a way to export files.

Expand Down
28 changes: 28 additions & 0 deletions src-docs/spec/selfAddr_and_selfName.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,34 @@ Note that `selfAddr`
- should not be shown in the user interface of the webxdc application
(use `selfName` instead).

## isAppSender

```js
window.webxdc.isAppSender
```

`isAppSender` is a boolean value that is `true` if the local user is the one
who initially shared the webxdc application in the chat.
If it is `false`, the user is a receiver.

This supports a common development model where a "central" app instance
(the sender's) processes all updates and distributes the resulting state
back to all peers.

## isBroadcast

```js
window.webxdc.isBroadcast
```

`isBroadcast` is a boolean value that is `true` if the webxdc
application is shared in a broadcast chat context.

On some platforms, such as "broadcast channels," it is technically impossible
for subscribers to discover or send updates to each other directly.
In those cases, [updates](./sendUpdate.md) sent by a non-sender
will only be seen by the app sender,
who alone can distribute updates globally.


## Example using selfAddr and selfName
Expand Down
7 changes: 5 additions & 2 deletions src-docs/spec/sendUpdate.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
window.webxdc.sendUpdate(update, descr);
```

Send an update to all peers.
Send an update to peers.
If `webxdc.isBroadcast` is false, the update is sent to all peers.
If `webxdc.isBroadcast` is true and `webxdc.isAppSender` is false,
the update is only sent to the app sender.

All peers, including the sending one,
All receiving peers, including the sending one,
will receive the update by the callback given to [`setUpdateListener()`](./setUpdateListener.html).

There are situations where the user cannot send messages to a chat,
Expand Down
4 changes: 4 additions & 0 deletions src-docs/webxdc.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ interface Webxdc<T> {
selfAddr: string;
/** Returns the peer's own name. This is name chosen by the user in their settings, if there is nothing set, that defaults to the peer's address. */
selfName: string;
/** True if the current user is the sender of this webxdc app. */
isAppSender: boolean;
/** True if the current user is in a broadcast chat. */
isBroadcast: boolean;
/**
* set a listener for new status updates.
* The "serial" specifies the last serial that you know about (defaults to 0).
Expand Down
Loading