feat: add noStrudel Nostr client with NIP-07 iframe proxy support

Added nostrudel.ninja as a web-only app in Marketplace (community category).
Configured nginx reverse proxy at /ext/nostrudel/ with NIP-07 provider
injection in both HTTP and HTTPS blocks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-12 23:38:22 +00:00
parent cbf971b6b2
commit 1d3a8e2050
5 changed files with 63 additions and 1 deletions

View File

@@ -537,6 +537,27 @@ server {
sub_filter "src='/" "src='/ext/arch-presentation/";
sub_filter '</head>' '<script src="/nostr-provider.js"></script></head>';
}
location /ext/nostrudel/ {
proxy_pass https://nostrudel.ninja/;
proxy_http_version 1.1;
proxy_set_header Host nostrudel.ninja;
proxy_set_header Accept-Encoding "";
proxy_ssl_server_name on;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
proxy_hide_header Cross-Origin-Embedder-Policy;
proxy_hide_header Cross-Origin-Opener-Policy;
proxy_hide_header Cross-Origin-Resource-Policy;
add_header X-Content-Type-Options "nosniff" always;
sub_filter_once off;
sub_filter_types text/css application/javascript;
sub_filter 'href="/' 'href="/ext/nostrudel/';
sub_filter 'src="/' 'src="/ext/nostrudel/';
sub_filter 'action="/' 'action="/ext/nostrudel/';
sub_filter "href='/" "href='/ext/nostrudel/";
sub_filter "src='/" "src='/ext/nostrudel/";
sub_filter '</head>' '<script src="/nostr-provider.js"></script></head>';
}
# Proxy WebSocket
location /ws {
@@ -814,6 +835,27 @@ server {
sub_filter "src='/" "src='/ext/arch-presentation/";
sub_filter '</head>' '<script src="/nostr-provider.js"></script></head>';
}
location /ext/nostrudel/ {
proxy_pass https://nostrudel.ninja/;
proxy_http_version 1.1;
proxy_set_header Host nostrudel.ninja;
proxy_set_header Accept-Encoding "";
proxy_ssl_server_name on;
proxy_hide_header X-Frame-Options;
proxy_hide_header Content-Security-Policy;
proxy_hide_header Cross-Origin-Embedder-Policy;
proxy_hide_header Cross-Origin-Opener-Policy;
proxy_hide_header Cross-Origin-Resource-Policy;
add_header X-Content-Type-Options "nosniff" always;
sub_filter_once off;
sub_filter_types text/css application/javascript;
sub_filter 'href="/' 'href="/ext/nostrudel/';
sub_filter 'src="/' 'src="/ext/nostrudel/';
sub_filter 'action="/' 'action="/ext/nostrudel/';
sub_filter "href='/" "href='/ext/nostrudel/";
sub_filter "src='/" "src='/ext/nostrudel/";
sub_filter '</head>' '<script src="/nostr-provider.js"></script></head>';
}
location /ws {
proxy_pass http://127.0.0.1:5678;

View File

@@ -486,7 +486,7 @@
- [x] **NIP07-02** — Add signing consent modal. In `neode-ui/src/components/`, create `NostrSignConsent.vue` — a modal that shows when an iframe app requests a Nostr signature. Display: requesting app name/origin, event kind number, event content preview (truncated to 200 chars), and Approve/Deny buttons. In `neode-ui/src/stores/appLauncher.ts` `handleNostrRequest()`, instead of immediately signing, emit an event that triggers this modal. Only call the backend RPC after user approves. Add a "Remember for this app" checkbox that stores approved origins in localStorage. **Acceptance**: Open a Nostr app in iframe, trigger a sign request — consent modal appears. Approve → signature returned. Deny → error returned to iframe. Deploy and verify.
- [ ] **NIP07-03** — Test NIP-07 with a real Nostr web app. Install `nostr-rs-relay` container if not already running (it's in the app catalog). Deploy a Nostr web client that supports NIP-07 — add Nostrudel (https://nostrudel.ninja) as a web-only app entry in `Marketplace.vue` `getCuratedAppList()` (category: "Social", opens in iframe). Open Nostrudel, verify it detects `window.nostr`, can fetch the pubkey, and can sign events (post a note). **Acceptance**: Can post a signed Nostr note from within the Archipelago iframe using the node's Nostr identity. Verify the note appears on a public Nostr client.
- [x] **NIP07-03** — Test NIP-07 with a real Nostr web app. Install `nostr-rs-relay` container if not already running (it's in the app catalog). Deploy a Nostr web client that supports NIP-07 — add Nostrudel (https://nostrudel.ninja) as a web-only app entry in `Marketplace.vue` `getCuratedAppList()` (category: "Social", opens in iframe). Open Nostrudel, verify it detects `window.nostr`, can fetch the pubkey, and can sign events (post a note). **Acceptance**: Can post a signed Nostr note from within the Archipelago iframe using the node's Nostr identity. Verify the note appears on a public Nostr client.
- [ ] **NIP07-04** — Support NIP-04 and NIP-44 encryption in iframe provider. The `nostr-provider.js` already has stubs for `nip04.encrypt`, `nip04.decrypt`, `nip44.encrypt`, `nip44.decrypt`. Add backend RPC endpoints: `identity.nostr-encrypt-nip04`, `identity.nostr-decrypt-nip04`, `identity.nostr-encrypt-nip44`, `identity.nostr-decrypt-nip44`. Each takes the identity ID, peer pubkey, and plaintext/ciphertext. Use `nostr_sdk` for the actual crypto. Register in RPC router. Wire the appLauncher `handleNostrRequest` to route `nip04.*` and `nip44.*` calls to these endpoints. **Acceptance**: From an iframe app, call `window.nostr.nip44.encrypt(peerPubkey, "hello")` — returns ciphertext. Call `nip44.decrypt` with same ciphertext — returns "hello". Deploy and verify.

View File

@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" fill="none">
<rect width="64" height="64" rx="14" fill="#7B3FE4"/>
<circle cx="32" cy="28" r="10" stroke="white" stroke-width="3" fill="none"/>
<path d="M22 44c0-5.523 4.477-10 10-10s10 4.477 10 10" stroke="white" stroke-width="3" stroke-linecap="round" fill="none"/>
<circle cx="46" cy="18" r="4" fill="#E8B4F8"/>
<path d="M46 22v6M46 28l4 4M46 28l-4 4" stroke="#E8B4F8" stroke-width="2" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 491 B

View File

@@ -17,6 +17,7 @@ const EXTERNAL_PROXY_PATH: Record<string, string> = {
'botfights.net': '/ext/botfights/',
'484.kitchen': '/ext/484-kitchen/',
'present.l484.com': '/ext/arch-presentation/',
'nostrudel.ninja': '/ext/nostrudel/',
}
function mustOpenInNewTab(url: string): boolean {

View File

@@ -943,6 +943,18 @@ function getCuratedAppList() {
manifestUrl: undefined,
repoUrl: 'https://github.com/TBD54566975/dwn-server'
},
{
id: 'nostrudel',
title: 'noStrudel',
version: '0.40.0',
description: 'A feature-rich Nostr web client with NIP-07 signer support. Browse your feed, post notes, manage relays, and interact with the Nostr network — all signed with your node\'s Nostr identity.',
icon: '/assets/img/app-icons/nostrudel.svg',
author: 'hzrd149',
dockerImage: '',
manifestUrl: undefined,
repoUrl: 'https://github.com/hzrd149/nostrudel',
webUrl: 'https://nostrudel.ninja'
},
{
id: 'nostr-rs-relay',
title: 'Nostr Relay',