Un cliente Nostr web integrado en el framework ExtFW. Resumen de funcionalidades, soporte de NIPs y comparativa con otros clientes.
Cliente Web · Arquitectura Abierta · Self-hostedNoxtr es un cliente Nostr web integrado en el framework ExtFW. Funciona como un módulo dentro de un sitio web auto-alojado, combinando el acceso al protocolo Nostr con funcionalidades del servidor como cuentas de usuario, hosting de direcciones Lightning y verificación de identidad NIP-05.
Está diseñado como una aplicación de página única sin frameworks JavaScript externos — vanilla JS con un helper DOM ligero (wquery).
Se ejecuta en tu propio servidor (Apache/nginx, PHP, MySQL/SQLite). Tú controlas tus datos, tu lista de relays y tus endpoints Lightning.
Sin React, sin Vue, sin npm, sin paso de compilación. JavaScript vanilla organizado en unos pocos ficheros por área (core, Mostro, on-chain). Criptografía vía noble-secp256k1 y noble-ciphers, incluidas en el repositorio (sin CDN).
La verificación NIP-05 y las direcciones Lightning LNURL-pay se auto-configuran desde las cuentas de usuario del servidor.
Soporta extensiones de navegador NIP-07, clave privada nsec, NIP-46 Nostr Connect (firma remota con QR, p.ej. con signer.noxtr.net) y modo sólo lectura con npub. Si el firmador remoto no responde, la petición se reenvía automáticamente durante 90s con aviso en pantalla.
Compra y vende Bitcoin directamente con otras personas, sin inter/mediarios: por Lightning vía el protocolo Mostro, o on-chain con escrow Taproot 2-de-3 (NostrEscrow). Order book, chat cifrado, disputas con arbitraje y notificaciones, todo dentro del cliente.
Registro 100% anónimo con Nostr: sin email, sin contraseña, sin datos personales. En los trades P2P, modo privacidad total por defecto (claves efímeras por operación, sin rastro entre trades) y reputación opcional.
Posibilidades de Implementación de Nostr (NIPs) soportadas por Noxtr:
| Kind | Descripción | Uso |
|---|---|---|
| 0 | Metadatos de perfil | Nombre, avatar, banner, bio, nip05, lud16 |
| 1 | Nota de texto | Contenido principal del feed, hashtags, menciones |
| 3 | Lista de contactos | Seguir/dejar de seguir, petnames, hints de relay |
| 4 | DM cifrado (NIP-04) | AES-CBC con IV, descifrado vía NIP-07, NIP-46 o privkey |
| 5 | Eliminación | Borrar notas propias y mensajes de canal propios (kind 42) |
| 6 | Repost | Compartir notas |
| 7 | Reacción | Like/unlike en notas |
| 13 | Seal (NIP-17) | Capa inter/media del gift wrap para DMs privados |
| 14 | Rumor (NIP-17) / Transporte Mostro v2 | En DMs: mensaje plano que se envuelve en el seal. En Mostro: mensaje directo firmado con la trade key y cifrado NIP-44 al robot |
| 40 | Crear canal | Canal de chat público NIP-28 |
| 41 | Metadatos de canal | Nombre, descripción, imagen del canal |
| 42 | Mensaje de canal | Mensajes en canales públicos (eliminación propia vía kind 5) |
| 1059 | Gift wrap (NIP-59) | Sobre exterior cifrado para DMs NIP-17 y mensajes Mostro. Oculta remitente y destinatario |
| 1063 | Metadatos de archivo (NIP-94) | Devuelto por servidores NIP-96 al subir un archivo: URL, hash, mime, dimensiones |
| 1984 | Reporte | Reportes de spam NIP-56 |
| 9802 | Highlight (NIP-84) | Citas destacadas con comentario/contexto, integradas en el feed |
| 9734 | Solicitud de Zap | Metadatos de pago Lightning |
| 9735 | Recibo de Zap | Confirmación de pago desde el servidor |
| 23194 | NWC request (NIP-47) | Solicitud cifrada (NIP-04) del cliente a la wallet NWC: pay_invoice, get_balance, etc. |
| 23195 | NWC response (NIP-47) | Respuesta cifrada de la wallet con resultado o error |
| 24133 | Nostr Connect | Firma remota NIP-46 |
| 27235 | HTTP Auth (NIP-98) | Evento de autenticación para uploads NIP-96 y login web |
| 30023 | Artículo (NIP-23) | Contenido largo: mezclado en el feed con badge “Read”, vista completa con Markdown, composición de artículos |
| 38383 | Orden P2P (NIP-69) | Órdenes de compraventa Bitcoin de robots Mostro. Tab P2P ₿ con listado de órdenes, explicación didáctica y flujo de compra guiado |
| 38385 | Estado de instancia Mostro | Heartbeat con versión del daemon, protocol_version del transporte, límites, comisión y política de fianza. Alimenta la etiqueta v1/v2 y la ficha de cada instancia |
| 38386 | Disputa pública Mostro | Estado público de las disputas (initiated / in-progress) |
| 39383-39389 | NostrEscrow (on-chain) | Ofertas, estado de trade, disputas, arbitraje y funding del intercambio P2P on-chain con escrow Taproot |
Global, Siguiendo, Seguidores, Temas (suscripciones por hashtag) y Tendencias (ranking por engagement).
DMs cifrados con NIP-04 (AES-CBC) y NIP-17 con gift wrap (NIP-59 + NIP-44 XChaCha20-Poly1305). Mismo tab para ambos, distinguibles visualmente con 🔒 en los NIP-17. Hilos de conversación, caché en BD local y descifrado vía extensión NIP-07, NIP-46 o nsec.
Conexión con wallets compatibles con Nostr Wallet Connect (Alby, Mutiny, Phoenix, Coinos, etc.). Configura tu URI nostrwalletconnect:// una vez y paga zaps y facturas Mostro automáticamente desde la wallet del usuario sin pasar por BTCPay. WebSocket dedicado al relay NWC, cifrado NIP-04, timeout 30s.
Las imágenes adjuntas a notes se suben a servidores NIP-96 externos (nostr.build por defecto, configurables en el tab Relays). Auto-descubrimiento de capabilities vía /.well-known/nostr/nip96.json. Auth con NIP-98 (kind 27235) firmado con la clave del usuario. Soporte para múltiples servidores con cadena de fallback.
Crear, unirse y chatear en canales públicos. Metadatos de canal, fijar canales, enlaces de invitación y configuración exclusiva del creador. Eliminación de mensajes propios (NIP-09).
Contenido largo (kind 30023) mezclado en el feed con badge “Read” y deduplicación. Vista completa con renderizado Markdown. Compositor con campos de título, resumen, imagen y etiquetas.
Vista completa de hilos con marcadores root/reply, conteo de respuestas, orden cronológico y enlaces permanentes.
Zaps NIP-57 con transferencias internas entre usuarios registrados y facturas externas vía BTCPay y LNURL-pay.
Infraestructura Lightning auto-alojada vía BTCPay Server. El endpoint LNURL-pay sirve facturas, crea solicitudes de pago BOLT11 y procesa recibos de zap (kind 9735) con firmas Schnorr del servidor. Los sats recibidos se acumulan en el balance del usuario para transferencias internas o retiro.
Búsqueda de texto NIP-50 con fallback multi-relay. Búsqueda de perfiles con @usuario. Detección de entidades npub/note/nevent.
Suscríbete a hashtags (#bitcoin, #nostr, etc.) y filtra tu feed. Temas sugeridos, activación masiva, filtro de tendencias.
Guarda notas como favoritos localmente. Silencia usuarios con reporte de spam NIP-56 opcional. Gestión de silenciados en ajustes.
Imágenes embebidas (carga diferida), reproductores de vídeo, embeds de YouTube/Vimeo. Detección de dominios caídos con reintento a las 24h.
Editar nombre, bio, avatar, banner. NIP-05 y dirección Lightning auto-configurados desde la cuenta del servidor.
Añadir/eliminar/activar relays. Estado de conexión en tiempo real. Reconexión con backoff exponencial. Rebalanceo de suscripciones.
Tab dedicado para comprar Bitcoin sin inter/mediarios usando el protocolo Mostro sobre Nostr. Muestra órdenes de venta (kind 38383, NIP-69) con explicación didáctica en lenguaje llano. Flujo guiado: tomar orden → DM cifrado al robot → enviar factura Lightning de cobro → recibir sats. Sin nodo Lightning propio; compatible con Phoenix, Breez, Zeus.
Parsea y renderiza broadcasts de perfiles de redes mesh AR (ar_profile, ar_collaboration) como tarjetas visuales con avatar, ubicación y acciones sociales.
Una comparación imparcial de Noxtr frente a clientes Nostr establecidos. Cada cliente tiene fortalezas diferentes — esta tabla pretende ser factual, no promocional.
| Noxtr | Damus | Amethyst | Primal | Snort | Iris | Coracle | Nostur | |
|---|---|---|---|---|---|---|---|---|
| Plataforma | Web | iOS | Android | Web/iOS/Android | Web | Web/Multi | Web (PWA) | iOS/macOS |
| Código abierto | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Auto-alojado | ✓ | — | — | — | ✓ | ✓ | ✓ | — |
| Sin paso de compilación | ✓ | n/a | n/a | — | — | — | — | n/a |
| NIPs documentados | 18 | ~15 | 60+ | ~20 | 42 | ~15 | ~15 | ~15 |
| NIP | Noxtr | Damus | Amethyst | Primal | Snort | Iris | Coracle | Nostur | |
|---|---|---|---|---|---|---|---|---|---|
| 01 | Protocolo básico | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| 02 | Lista de contactos | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| 04 | DMs cifrados (legacy) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | lectura | ✓ |
| 05 | Identidad DNS | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| 07 | Firmante del navegador | ✓ | n/a | n/a | ✓ | ✓ | ✓ | ✓ | n/a |
| 09 | Eliminación de eventos | ✓ | ~ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| 10 | Hilos de respuesta | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| 17 | DMs privados (gift wrap) | ✓ | ~ | ✓ | — | ✓ | ✓ | ✓ | ✓ |
| 19 | Entidades Bech32 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| 23 | Contenido largo (artículos) | ✓ | — | ✓ | ✓ | ✓ | — | — | — |
| 25 | Reacciones | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| 28 | Canales públicos | ✓ | — | ✓ | — | ✓ | — | — | — |
| 44 | Cifrado versionado | ✓ | ~ | ✓ | — | ✓ | ✓ | ✓ | ✓ |
| 46 | Nostr Connect | ✓ | — | ~ | ✓ | ✓ | ✓ | ✓ | ✓ |
| 47 | Nostr Wallet Connect | ✓ | — | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| 50 | Búsqueda | ✓ | ~ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| 57 | Zaps Lightning | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| 65 | Metadatos de relays | ✓ | ✓ | ~ | ✓ | ✓ | ✓ | ✓ | ✓ |
| 94 | Metadatos de archivo | ✓ | — | ✓ | — | ~ | — | ~ | — |
| 96 | Almacenamiento HTTP de archivos | ✓ | — | ✓ | — | ✓ | — | ✓ | — |
| Pendientes de implementar en Noxtr | |||||||||
| 29 | Grupos relay-based | — | — | ~ | — | — | — | — | — |
| 35 | Torrents | — | — | — | — | — | — | — | — |
| 51 | Listas (mute, pin, bookmarks, sets) | — | ~ | ✓ | ~ | ✓ | ~ | ✓ | ✓ |
| 72 | Comunidades moderadas | — | — | ✓ | — | — | — | ✓ | — |
| 78 | App data personalizada | — | — | ~ | — | ~ | — | ~ | — |
| Funcionalidad | Noxtr | Damus | Amethyst | Primal | Snort | Iris | Coracle | Nostur |
|---|---|---|---|---|---|---|---|---|
| DMs modernos (NIP-17/44) | ✓ | ~ | ✓ | — | ✓ | ✓ | ✓ | ✓ |
| Wallet integrado | balance | Coinos | — | ✓ | — | Cashu | — | — |
| Búsqueda de perfiles (@user) | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Canales públicos (NIP-28) | ✓ | — | ✓ | — | ✓ | — | — | — |
| Feed de tendencias | ✓ | — | ✓ | ✓ | ✓ | — | — | — |
| Suscripción a temas/hashtags | ✓ | — | ✓ | ~ | ~ | — | — | ~ |
| Hosting NIP-05 | ✓ | — | — | premium | pago | — | — | — |
| Hosting dirección Lightning | ✓ | — | — | ✓ | pago | — | — | — |
| Múltiples cuentas | logout/login | — | ✓ | — | ✓ | — | ✓ | ✓ |
| Contenido largo (NIP-23) | ✓ | — | ✓ | ✓ | ✓ | — | — | — |
| Comunidades (NIP-72) | — | — | ✓ | — | — | — | ✓ | — |
| Subida de archivos (NIP-96) | ✓ | — | ✓ | — | ✓ | — | ✓ | — |
| Metadatos de archivo (NIP-94) | ✓ | — | ✓ | — | ~ | — | ~ | — |
| Nostr Wallet Connect (NIP-47) | ✓ | — | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Listas sincronizadas (NIP-51) | — | ~ | ✓ | ~ | ✓ | ~ | ✓ | ✓ |
| Grupos relay (NIP-29) | — | — | ~ | — | — | — | — | — |
| App data en relay (NIP-78) | — | — | ~ | — | ~ | — | ~ | — |
| Torrents (NIP-35) | — | — | — | — | — | — | — | — |
| Integración BTCPay Server | ✓ | — | — | — | — | — | — | — |
| Compra Bitcoin P2P (Mostro) | único | — | — | — | — | — | — | — |
| Renderizado de perfiles AR | único | — | — | — | — | — | — | — |
Áreas donde Noxtr está por detrás de otros clientes:
Noxtr incluye soporte nativo para Mostro, un protocolo de intercambio de Bitcoin entre pares (P2P) que funciona sobre Nostr. Puedes comprar o vender Bitcoin directamente con otras personas, sin inter/mediarios ni custodios, pagando con transferencia bancaria, Bizum, efectivo o cualquier otro método acordado.
El tab P2P ₿ en la barra de navegación te da acceso al order book en tiempo real con todas las ofertas disponibles.
Puedes añadir y activar varias instancias Mostro (robots) en la barra de chips del tab P2P. El order book agrega las ofertas de todas las instancias activas; al crear una oferta eliges en cuál se publica.
protocol_version de su evento de estado, kind 38385).No necesitas ninguna experiencia previa con Bitcoin. Solo necesitas una wallet Lightning en el móvil (Phoenix, Breez, Zeus, Wallet of Satoshi…).
usuario@wallet.com) o una factura bolt11 generada desde tu wallet — ahí es donde recibirás los sats.Si la wallet del vendedor o el nodo del robot no puede enrutar el pago a tu dirección, la ficha del trade mostrará un campo para introducir otra dirección Lightning alternativa. Tus sats están siempre a salvo con el robot.
Si ya usas la app Mostro Mobile, puedes importar tu identidad en Noxtr sin crear una cuenta nueva:
m/44'/1237'/38383'/0/0).Se importa la identidad (misma clave y, por tanto, misma reputación acumulada). Los trades iniciados en Mostro Mobile no se recuperan automáticamente: cada interfaz gestiona sus propias sesiones de trade.
Al completar un trade puedes valorar a la contraparte de 1 a 5 estrellas. Las valoraciones recibidas aparecen en tu ficha de reputación (⭐ promedio · número de trades). Los robots Mostro publican la reputación acumulada de cada usuario en sus órdenes del order book.
Por defecto Noxtr opera en modo privacidad total (cada trade con claves efímeras, sin rastro entre trades). Si quieres acumular reputación, activa el botón ⭐ Reputación: tus trades quedan ligados a tu identidad Nostr. Requiere login con nsec local (con extensión o firmador remoto no es posible, porque la prueba de identidad exige firmar fuera del estándar de eventos).
Si algo va mal en un trade en estados activo o fiat_enviado (la contraparte no responde, no envía el dinero, niega haber recibido un pago confirmado…), puedes iniciar una disputa. La disputa la resuelve un administrador humano del robot Mostro.
activo o fiat_enviado.dispute al robot.disputado con un identificador de disputa visible en la ficha.admin-took-dispute y aparecerá un nuevo recuadro de chat directo con el admin debajo de la ficha del trade.El botón Anular disputa (visible si la iniciaste tú y aún no hay admin asignado) solo la oculta de tu lista local: el protocolo Mostro no permite retirar una disputa, así que en el robot sigue abierta hasta que un admin la resuelva.
Si la contraparte solicita cancelación cooperativa de un trade activo y no estás de acuerdo, puedes Disputar en lugar de aceptar la cancelación.
Listado de tus disputas en /noxtr/disputes: muestra ID de disputa, estado público (initiated / in-progress), iniciador, admin asignado y última actualización.
Para enviar mensajes al robot es necesario que wss://relay.mostro.network esté activo en la lista de relays del usuario. El order book funciona con cualquier relay general, pero la comunicación con el robot requiere ese relay específico. Noxtr lo añade automáticamente como relay por defecto en las nuevas instalaciones.
Noxtr no requiere que el servidor tenga un nodo Lightning para el flujo Mostro. La wallet Lightning es del usuario final (Phoenix, Breez, Zeus, etc.). BTCPay Server solo es necesario para el sistema de zaps y direcciones Lightning de perfil, no para Mostro.
Los trades activos se guardan en NSTR_TRADES y los eventos Mostro en NSTR_EVENTS. Ambas tablas se crean automáticamente. Los datos de reputación se calculan a partir de NSTR_EVENTS sin tabla adicional.
Además del flujo Lightning con Mostro, Noxtr soporta intercambios P2P on-chain /mediante NostrEscrow: los fondos se depositan en una dirección escrow Taproot 2-de-3 (comprador, vendedor y árbitro), sin robot custodio.
39383-39389 son provisionales hasta su eventual envío al repositorio oficial de NIPs.
El Monitor es un proceso PHP que corre en el servidor en segundo plano y vigila los trades Mostro activos aunque ningún usuario tenga la web abierta. Escucha los relays Nostr continuamente y actúa cuando recibe eventos relevantes.
Si el administrador del sitio tiene el Monitor activo, recibirás avisos automáticos cuando ocurra algo en tus trades:
| Evento | Notificación recibida |
|---|---|
| Alguien toma tu orden publicada | Email: “Han tomado tu orden #XXXXXXXX” |
| El robot te pide pagar la hold invoice (vendes BTC) | Email: “Debes pagar la hold invoice” |
| El comprador confirma que envió el fiat (vendes BTC) | Email: “El comprador ha enviado el pago” |
| El trade se completa | Email: “Trade completado” |
| La contraparte inicia una disputa | Email + Telegram: “⚠️ La contraparte ha iniciado una disputa” |
| Has iniciado tú una disputa | Email + Telegram: confirmación “Has iniciado una disputa” |
| Un admin ha tomado la disputa | Email + Telegram: “🛡️ Un admin ha tomado la disputa — abre la web para chatear con él” |
| Mensaje privado nuevo en tu buzón | Telegram (si tienes el bot vinculado) |
Cada notificación se envía una sola vez por trade y tipo de evento — no hay spam.
/start CODIGO mostrado en esa misma pantalla (botón Copiar), abre Telegram, entra en el chat del bot del sitio y envíalo como mensaje.El Monitor se gestiona desde el panel de administración web (/noxtr/server_admin) con los botones Start / Stop / Status, o directamente desde la consola del servidor:
php /ruta/index.php noxtr/server/action=monitor --verbose
Para dejarlo corriendo en background:
nohup php /ruta/index.php noxtr/server/action=monitor > /var/log/monitor.log 2>&1 &
El Monitor tiene su propia identidad Nostr. Los administradores autorizados pueden enviarle DMs con comandos de texto plano desde cualquier cliente Nostr (incluyendo Noxtr). Su npub aparece en el mensaje de arranque y en el panel web.
| Comando | Acción |
|---|---|
ping | Comprueba que el canal responde. Devuelve pong. |
status | Versión, trades vigilados, uptime, relays. |
trades | Order book en tiempo real (opciones: age 4h, amount 50 EUR, status pending). |
relays | Relays conectados en la sesión actual. |
email | Envía un email de prueba al admin. |
reload | Reconecta a los relays sin reiniciar el proceso. |
stop | Para el proceso limpiamente. |
help | Ayuda contextual completa. |
Además de vigilar trades propios, el Monitor notifica al administrador cada nueva orden que aparece en el order book Mostro (solo de instancias con transporte v2; las v1, obsoletas, se ignoran) y cada nueva oferta on-chain. Se puede activar/desactivar con el comando notify-new-offers on|off.
Para recibir notificaciones de nuevas órdenes por Telegram, el administrador debe tener el bot vinculado y su pubkey Nostr añadida a admin_pubkeys en la configuración del Monitor.
admin_pubkeys pueden enviar comandos. Los eventos se verifican criptográficamente con firma Schnorr. Los comandos con más de 5 minutos de antigüedad se ignoran automáticamente.
| Componente | Tecnología |
|---|---|
| Frontend | JavaScript vanilla (IIFE único), helper DOM wquery |
| Backend | PHP (módulo del framework ExtFW) |
| Base de datos | MySQL o SQLite (SQL dual-compatible) |
| Servidor web | Apache (mod_rewrite) o nginx |
| Criptografía | noble-secp256k1 (BIP-340 Schnorr), noble-ciphers (XChaCha20-Poly1305), Web Crypto API (AES-CBC, HKDF) |
| Lightning | BTCPay Server (LNURL-pay, facturas BOLT11) |
| Almacenamiento | BD del servidor (contactos, temas, favoritos, DMs, relays, silenciados, canales, servidores NIP-96, NWC URI) + localStorage/IndexedDB (claves, estado UI). Imágenes adjuntas suben a servidores NIP-96 externos — no al servidor PHP |
Funcionalidades en cola sin fecha definida. La fuente canónica vive en _modules_/noxtr/BACKLOG.md dentro del repositorio.
Hacer portables las listas (topics, bookmarks, muted, channels, relays) entre clientes Nostr y entre instancias Noxtr vía kinds 10000-10015. Hoy las listas viven solo en BD local; el export/import manual cubre la migración. NIP-51 añadiría sync continuo y bidireccional.
Propuesta de NIP propio (no estandarizado) para directorio descentralizado de servidores ed2k y enlaces ed2k. Kinds 2010 (server) y 2011 (file). Especificación completa (borrador): NIP-ED2K.md.
Implementación sencilla de kind 2003 con tags magnet/nombre/tamaño. Postergado: el ecosistema está casi vacío hoy (0 eventos kind 2003 en los relays activos). Tendría sentido junto con NIP-ED2K en un tab unificado de "compartir archivos".
Comunidades tipo subreddit con moderación criptográfica. Kinds 34550 (definición) y 4550 (aprobación de moderador). Tab separado de Channels (NIP-28). Útil para feeds curados tipo foro.
Cifrar columnas sensibles de la tabla CLI_USER en el navegador, de manera que el servidor no vea datos personales en claro. Requiere diseño previo (qué columnas, qué clave, qué pasa si el usuario la pierde).