{"id":"a94075479bcbc17a24d415aaa4ea89d43fb953564bef96fb92e7b2a57847c53e","pubkey":"f6150173b5d6f079b43540d84a8a95d50cf01a48c9d6037984e3d9600d5522af","created_at":1783913851,"kind":30817,"tags":[["d","typing-indicator-nip29-group-chat"],["title","Typing Indicator - NIP29 Group Chat"],["alt","Nostr Implementation Possibility: Typing Indicator - NIP29 Group Chat"],["k","23311","Typing Indicator"],["client","NostrHub"]],"content":"## Summary\n\nDefine a lightweight typing indicator for NIP-29 groups as an ephemeral Nostr event scoped to a group with the existing `h` tag.\n\nThis is intentionally not stored state. It is a short-lived presence signal for clients that are watching the same group relay.\n\n## Event\n\n```json\n{\n  \"kind\": 23311,\n  \"content\": \"\",\n  \"tags\": [\n    [\"h\", \"<group-id>\"]\n  ]\n}\n```\n\nOptional tags:\n\n```json\n[\"client\", \"<client-name>\"]\n```\n\n## Semantics\n\n- `kind:23311` means the author is currently typing in the group identified by the `h` tag.\n- `kind:23311` falls in the ephemeral range defined by NIP-01 (`20000 <= kind < 30000`). Relays are not expected to store it, and clients MUST NOT treat it as durable group history.\n- The event MUST be published to the group's host relay, not broadcast to unrelated relays.\n- The event MUST include exactly one `h` tag with the NIP-29 group id.\n- `content` SHOULD be an empty string. Clients MUST ignore any content they do not understand and treat every valid event of this kind as a plain typing signal. Future revisions may define explicit state values, such as `recording` or `uploading`, without breaking this fallback.\n\n## Sender Behavior\n\nClients SHOULD publish a typing event when the local user starts or continues typing a non-empty draft.\n\nRecommended rate limits:\n\n- Send immediately when typing starts.\n- Send at most once every 4 seconds while typing continues.\n- Stop sending when the draft is empty or after the message is sent.\n\nTyping events SHOULD NOT include the NIP-29 `previous` tag. They are live signals, not part of the group timeline, and referencing them from other events is meaningless.\n\nClients SHOULD NOT send typing events for users who cannot write to the group.\n\n## Receiver Behavior\n\nClients SHOULD show a user as typing for a short window after receiving the latest valid event from that user.\n\nRecommended expiry:\n\n- 8 seconds after the newest typing event from the same pubkey and group.\n\nClients SHOULD:\n\n- Ignore typing events authored by the logged-in user.\n- Ignore typing events without a matching `h` tag.\n- Ignore typing events from non-members when the group member list is known.\n- Collapse multiple typing users into a compact label, for example `Alice and Bob are typing`.\n\nClients MUST NOT add typing events to the visible message timeline or unread counters.\n\n## Relay Behavior\n\n- Normal NIP-29 write rules apply unchanged: the group must exist, and in restricted groups only members can publish.\n- Relays SHOULD NOT require `previous` timeline references for ephemeral kinds. The reference implementation, relay29, already validates the `previous` tag only when it is present.\n- Groups that advertise a `supported_kinds` list in their `kind:39000` metadata SHOULD include `23311` when typing indicators are supported. Clients MAY treat its absence from an advertised list as a signal to not send typing events to that group.\n\n## Rationale\n\nNIP-29 already scopes group user events with the `h` tag and explicitly allows groups to accept any event kind carrying it. NIP-01 defines ephemeral event kinds in the `20000 <= kind < 30000` range. A typing indicator naturally fits this model because it is live presence, not history.\n\nThe kind `23311` was picked as a free number in the ephemeral range: at the time of writing it has no claim in the public registry of kinds and no known conflicting public usage. It also matches a number already used internally as a typing signal by at least one existing client stack before wrapping and encrypting it, which gives implementers a convergence point.\n\nThis event is implemented and working in a production NIP-29 client.\n\n## Compatibility\n\nClients that do not understand `kind:23311` will ignore it.\n\nExisting clients using encrypted or wrapped typing schemes are not automatically compatible with this plain NIP-29 event. They may choose to additionally publish or consume this event for public, interoperable group typing.\n\n## Example Filter\n\n```json\n{\n  \"kinds\": [23311],\n  \"#h\": [\"<group-id>\"]\n}\n```","sig":"d0771db3bd2990512c66bf01c0d00edf1cfeae84fc904af22848706c5581b98425473211aff647a3e1b2a01f5c1568d4f91979c0749ac2dab91602daeac8ee20"}