fix(subscribe): restore NIP-05 resolution + Nostr send, derive npub automatically - #32

Merged
agustinkassis merged 2 commits into
mainfrom
fix/newsletter-nip05-restore
Jun 9, 2026
Merged

fix(subscribe): restore NIP-05 resolution + Nostr send, derive npub automatically#32
agustinkassis merged 2 commits into
mainfrom
fix/newsletter-nip05-restore

Conversation

@agustinkassis

@agustinkassisagustinkassis commented Jun 9, 2026

Copy link
Copy Markdown
Member

What & why

Follow-up to #31. That PR replaced the homepage NewsletterCTA NIP-05 flow with a manual email/npub form and dropped the Nostr notification send. This restores the original flow and integrates the events.lacrypta.ar CRM subscription into it instead.

Changes (single file: components/sections/NewsletterCTA.tsx)

  • No manual npub field. The npub is derived automatically from the resolved NIP-05 (resolved.pubkey) — the user only enters a NIP-05.
  • Restored NIP-05 resolution → profile preview → notify by email / Nostr / both (Resend welcome email + NIP-17 relay publish with live per-relay progress).
  • handleNotify now also registers the subscriber in the events CRM via POST /api/events-subscribe (npub always; email + display name when the user opts into email) as the first step, before the existing Resend + Nostr notification.

Verification

  • tsc --noEmit clean.
  • /api/events-subscribe accepts the raw hex pubkey the component sends (resolved.pubkey), encodes it to bech32, and the CRM registers it (200 / Subscribed) — verified live.
  • Homepage section renders the NIP-05 input with no npub field and the three Notificar buttons.

Routes the restored component depends on (/api/subscribe, /api/nostr-opportunity-notification) already exist in main.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Enhanced newsletter subscription flow with NIP-05 profile resolution and preview display
    • Added support for configuring multiple CRM subscription lists
    • Improved subscription handling with automatic retry logic for identity conflicts
    • Added multi-relay Nostr event publishing with per-relay progress tracking for notifications

…utomatically
PR #31 replaced the NewsletterCTA NIP-05 flow with a manual email/npub
form, dropping the Nostr notification send. Restore the original flow and
integrate the events.lacrypta.ar CRM subscription into it instead:
- No manual npub field. The npub is derived from the resolved NIP-05
(resolved.pubkey) and registered in the CRM automatically.
- Bring back NIP-05 resolution → profile preview → email / Nostr / both
notification (Resend welcome email + NIP-17 relay publish).
- handleNotify now also POSTs to /api/events-subscribe (npub always; email
and display name when the user opts into email) as the first step.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercelBot commented Jun 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
lacrypta-devReadyReadyPreview, CommentJun 9, 2026 8:14pm

Request Review

@coderabbitai

coderabbitaiBot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR adds CRM list ID configuration with conflict-retry logic to the subscription route, and comprehensively rewrites the newsletter CTA to resolve NIP-05 addresses, support multi-action subscription (email, Nostr, or both), and publish notification events across Nostr relays with per-relay progress tracking.

Changes

Newsletter and CRM Subscription Flow

Layer / File(s)Summary
CRM List Configuration and Conflict Retry
.env.example, app/api/events-subscribe/route.ts
Environment variable EVENTS_SUBSCRIBE_LISTS defines optional CRM list UUIDs; getListIds() parses and defaults the config; subscription handler refactors to share common fields, centralizes CRM calls in a subscribe() helper, and retries separately with email-only then npub-only when a 409 identity conflict occurs.
NIP-05 Resolution and Publishing Infrastructure
components/sections/NewsletterCTA.tsx (lines 3–133)
Shared types for resolution/publishing phases; helper functions for formatting pubkeys, display names, NIP-05 validation; resolveInput() resolves NIP-05 to pubkey/profile/relays; publishNotification() publishes signed events across relays with per-relay progress callbacks and timeout.
CTA State Machine and Async Orchestration
components/sections/NewsletterCTA.tsx (lines 135–327)
Replaces manual email/npub entry with debounced NIP-05 resolution; multi-phase state tracking for subscription and publishing; dynamic action button visibility gating; handleNotify() orchestrates calls to subscription endpoints and notification publishing with progress/phase/error updates.
CTA UI Rendering and Components
components/sections/NewsletterCTA.tsx (lines 345–723)
Container width adjustment; single NIP-05 input replacing old form fields; dynamic action buttons for email/Nostr/both; conditional ProfilePreview showing resolved user details; multi-relay progress visualization; updated status messaging; new ProfilePreview component rendering banner/picture/about/verification.

Sequence Diagram

sequenceDiagram
participant User
participant CTA as NewsletterCTA
participant Resolve as resolveInput
participant API as API Endpoints
participant Pool as SimplePool
participant Relay as Relays
User->>CTA: Enter NIP-05 address
CTA->>Resolve: Resolve NIP-05 (debounced 500ms)
Resolve->>Resolve: Query profile, fetch metadata
Resolve->>CTA: Return pubkey + profile + relays
CTA->>CTA: Update resolution status
User->>CTA: Click Notify (Nostr)
CTA->>API: POST /api/nostr-opportunity-notification
API->>CTA: Return signed event
CTA->>Pool: Initialize SimplePool with relays
Pool->>Relay: Publish event to each relay
Relay->>Pool: Update progress per relay
Pool->>CTA: Per-relay progress callbacks
CTA->>CTA: Update progress panel
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly Related PRs

  • lacrypta/lacrypta-dev#18: This PR's new Nostr-based NewsletterCTA flow now calls /api/nostr-opportunity-notification and publishes the generated event via per-relay progress, matching the endpoint and related CTA rewrite.
  • lacrypta/lacrypta-dev#20: This PR's rewritten NewsletterCTA invokes /api/nostr-opportunity-notification for publishing Nostr notifications, and the retrieved PR changes that route to generate the NIP-17 notification event, so the changes are directly coupled.
  • lacrypta/lacrypta-dev#19: Both PRs modify components/sections/NewsletterCTA.tsx to refactor NIP-05/identity resolution and notification/subscribe flows, so this PR's CTA changes build on the retrieved PR's CTA logic.

Poem

🐰 A rabbit hops through NIP-05 gardens bright,
resolving pubkeys, lists left and right!
From conflict retries to relays in a pool,
the newsletter flows—now NIP-05 is the rule! 🌿✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 7.69% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately reflects the primary changes: restoring NIP-05 resolution, Nostr event sending, and automatic npub derivation from NIP-05 — all core objectives of the PR.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/newsletter-nip05-restore

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

… polish
Newsletter/subscribe refinements on top of the restored NIP-05 flow:
events-subscribe route:
- Subscribe contacts into a CRM list via EVENTS_SUBSCRIBE_LISTS (defaults to
the main newsletter list), forwarded as the `lists` array.
- Gracefully handle 409 identity_conflict on combined email+npub submissions
by retrying each identifier alone (email first) so the contact still lands
in the list.
NewsletterCTA:
- Only send `npub` when the user opts into Nostr, so email-only subscriptions
don't trigger identity_conflict.
- Button visibility: "Notificar por Nostr" is disabled until the NIP-05
resolves and hidden if it resolves badly; "Email + Nostr" is hidden until a
clean resolution; "Notificar por email" stays available (and no error text)
when the NIP-05 fails to resolve. Grid adapts to the visible button count.
- Removed the descriptive NIP-17 panel; re-added the per-relay publish
progress as its own card that auto-scrolls into view during a Nostr publish.
- Combined success line "Te notificamos email y nostr a {email}" when both
channels complete; preview card widened to match the form.
.env.example: document EVENTS_SUBSCRIBE_LISTS.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@agustinkassis
agustinkassis merged commit ce955fd into mainJun 9, 2026
2 of 3 checks passed
@agustinkassis
agustinkassis deleted the fix/newsletter-nip05-restore branch June 9, 2026 20:18
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@agustinkassis
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

fix(subscribe): restore NIP-05 resolution + Nostr send, derive npub automatically - #32

Merged
agustinkassis merged 2 commits into
mainfrom
fix/newsletter-nip05-restore
Jun 9, 2026
Merged

fix(subscribe): restore NIP-05 resolution + Nostr send, derive npub automatically#32
agustinkassis merged 2 commits into
mainfrom
fix/newsletter-nip05-restore

Conversation

@agustinkassis

@agustinkassisagustinkassis commented Jun 9, 2026

Copy link
Copy Markdown
Member

What & why

Follow-up to #31. That PR replaced the homepage NewsletterCTA NIP-05 flow with a manual email/npub form and dropped the Nostr notification send. This restores the original flow and integrates the events.lacrypta.ar CRM subscription into it instead.

Changes (single file: components/sections/NewsletterCTA.tsx)

  • No manual npub field. The npub is derived automatically from the resolved NIP-05 (resolved.pubkey) — the user only enters a NIP-05.
  • Restored NIP-05 resolution → profile preview → notify by email / Nostr / both (Resend welcome email + NIP-17 relay publish with live per-relay progress).
  • handleNotify now also registers the subscriber in the events CRM via POST /api/events-subscribe (npub always; email + display name when the user opts into email) as the first step, before the existing Resend + Nostr notification.

Verification

  • tsc --noEmit clean.
  • /api/events-subscribe accepts the raw hex pubkey the component sends (resolved.pubkey), encodes it to bech32, and the CRM registers it (200 / Subscribed) — verified live.
  • Homepage section renders the NIP-05 input with no npub field and the three Notificar buttons.

Routes the restored component depends on (/api/subscribe, /api/nostr-opportunity-notification) already exist in main.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Enhanced newsletter subscription flow with NIP-05 profile resolution and preview display
    • Added support for configuring multiple CRM subscription lists
    • Improved subscription handling with automatic retry logic for identity conflicts
    • Added multi-relay Nostr event publishing with per-relay progress tracking for notifications

…utomatically
PR #31 replaced the NewsletterCTA NIP-05 flow with a manual email/npub
form, dropping the Nostr notification send. Restore the original flow and
integrate the events.lacrypta.ar CRM subscription into it instead:
- No manual npub field. The npub is derived from the resolved NIP-05
(resolved.pubkey) and registered in the CRM automatically.
- Bring back NIP-05 resolution → profile preview → email / Nostr / both
notification (Resend welcome email + NIP-17 relay publish).
- handleNotify now also POSTs to /api/events-subscribe (npub always; email
and display name when the user opts into email) as the first step.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercelBot commented Jun 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
lacrypta-devReadyReadyPreview, CommentJun 9, 2026 8:14pm

Request Review

@coderabbitai

coderabbitaiBot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR adds CRM list ID configuration with conflict-retry logic to the subscription route, and comprehensively rewrites the newsletter CTA to resolve NIP-05 addresses, support multi-action subscription (email, Nostr, or both), and publish notification events across Nostr relays with per-relay progress tracking.

Changes

Newsletter and CRM Subscription Flow

Layer / File(s)Summary
CRM List Configuration and Conflict Retry
.env.example, app/api/events-subscribe/route.ts
Environment variable EVENTS_SUBSCRIBE_LISTS defines optional CRM list UUIDs; getListIds() parses and defaults the config; subscription handler refactors to share common fields, centralizes CRM calls in a subscribe() helper, and retries separately with email-only then npub-only when a 409 identity conflict occurs.
NIP-05 Resolution and Publishing Infrastructure
components/sections/NewsletterCTA.tsx (lines 3–133)
Shared types for resolution/publishing phases; helper functions for formatting pubkeys, display names, NIP-05 validation; resolveInput() resolves NIP-05 to pubkey/profile/relays; publishNotification() publishes signed events across relays with per-relay progress callbacks and timeout.
CTA State Machine and Async Orchestration
components/sections/NewsletterCTA.tsx (lines 135–327)
Replaces manual email/npub entry with debounced NIP-05 resolution; multi-phase state tracking for subscription and publishing; dynamic action button visibility gating; handleNotify() orchestrates calls to subscription endpoints and notification publishing with progress/phase/error updates.
CTA UI Rendering and Components
components/sections/NewsletterCTA.tsx (lines 345–723)
Container width adjustment; single NIP-05 input replacing old form fields; dynamic action buttons for email/Nostr/both; conditional ProfilePreview showing resolved user details; multi-relay progress visualization; updated status messaging; new ProfilePreview component rendering banner/picture/about/verification.

Sequence Diagram

sequenceDiagram
participant User
participant CTA as NewsletterCTA
participant Resolve as resolveInput
participant API as API Endpoints
participant Pool as SimplePool
participant Relay as Relays
User->>CTA: Enter NIP-05 address
CTA->>Resolve: Resolve NIP-05 (debounced 500ms)
Resolve->>Resolve: Query profile, fetch metadata
Resolve->>CTA: Return pubkey + profile + relays
CTA->>CTA: Update resolution status
User->>CTA: Click Notify (Nostr)
CTA->>API: POST /api/nostr-opportunity-notification
API->>CTA: Return signed event
CTA->>Pool: Initialize SimplePool with relays
Pool->>Relay: Publish event to each relay
Relay->>Pool: Update progress per relay
Pool->>CTA: Per-relay progress callbacks
CTA->>CTA: Update progress panel
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly Related PRs

  • lacrypta/lacrypta-dev#18: This PR's new Nostr-based NewsletterCTA flow now calls /api/nostr-opportunity-notification and publishes the generated event via per-relay progress, matching the endpoint and related CTA rewrite.
  • lacrypta/lacrypta-dev#20: This PR's rewritten NewsletterCTA invokes /api/nostr-opportunity-notification for publishing Nostr notifications, and the retrieved PR changes that route to generate the NIP-17 notification event, so the changes are directly coupled.
  • lacrypta/lacrypta-dev#19: Both PRs modify components/sections/NewsletterCTA.tsx to refactor NIP-05/identity resolution and notification/subscribe flows, so this PR's CTA changes build on the retrieved PR's CTA logic.

Poem

🐰 A rabbit hops through NIP-05 gardens bright,
resolving pubkeys, lists left and right!
From conflict retries to relays in a pool,
the newsletter flows—now NIP-05 is the rule! 🌿✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 7.69% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately reflects the primary changes: restoring NIP-05 resolution, Nostr event sending, and automatic npub derivation from NIP-05 — all core objectives of the PR.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/newsletter-nip05-restore

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

… polish
Newsletter/subscribe refinements on top of the restored NIP-05 flow:
events-subscribe route:
- Subscribe contacts into a CRM list via EVENTS_SUBSCRIBE_LISTS (defaults to
the main newsletter list), forwarded as the `lists` array.
- Gracefully handle 409 identity_conflict on combined email+npub submissions
by retrying each identifier alone (email first) so the contact still lands
in the list.
NewsletterCTA:
- Only send `npub` when the user opts into Nostr, so email-only subscriptions
don't trigger identity_conflict.
- Button visibility: "Notificar por Nostr" is disabled until the NIP-05
resolves and hidden if it resolves badly; "Email + Nostr" is hidden until a
clean resolution; "Notificar por email" stays available (and no error text)
when the NIP-05 fails to resolve. Grid adapts to the visible button count.
- Removed the descriptive NIP-17 panel; re-added the per-relay publish
progress as its own card that auto-scrolls into view during a Nostr publish.
- Combined success line "Te notificamos email y nostr a {email}" when both
channels complete; preview card widened to match the form.
.env.example: document EVENTS_SUBSCRIBE_LISTS.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@agustinkassis
agustinkassis merged commit ce955fd into mainJun 9, 2026
2 of 3 checks passed
@agustinkassis
agustinkassis deleted the fix/newsletter-nip05-restore branch June 9, 2026 20:18
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@agustinkassis
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(subscribe): restore NIP-05 resolution + Nostr send, derive npub automatically - #32

Merged
agustinkassis merged 2 commits into
mainfrom
fix/newsletter-nip05-restore
Jun 9, 2026
Merged

fix(subscribe): restore NIP-05 resolution + Nostr send, derive npub automatically#32
agustinkassis merged 2 commits into
mainfrom
fix/newsletter-nip05-restore

Conversation

@agustinkassis

@agustinkassisagustinkassis commented Jun 9, 2026

Copy link
Copy Markdown
Member

What & why

Follow-up to #31. That PR replaced the homepage NewsletterCTA NIP-05 flow with a manual email/npub form and dropped the Nostr notification send. This restores the original flow and integrates the events.lacrypta.ar CRM subscription into it instead.

Changes (single file: components/sections/NewsletterCTA.tsx)

  • No manual npub field. The npub is derived automatically from the resolved NIP-05 (resolved.pubkey) — the user only enters a NIP-05.
  • Restored NIP-05 resolution → profile preview → notify by email / Nostr / both (Resend welcome email + NIP-17 relay publish with live per-relay progress).
  • handleNotify now also registers the subscriber in the events CRM via POST /api/events-subscribe (npub always; email + display name when the user opts into email) as the first step, before the existing Resend + Nostr notification.

Verification

  • tsc --noEmit clean.
  • /api/events-subscribe accepts the raw hex pubkey the component sends (resolved.pubkey), encodes it to bech32, and the CRM registers it (200 / Subscribed) — verified live.
  • Homepage section renders the NIP-05 input with no npub field and the three Notificar buttons.

Routes the restored component depends on (/api/subscribe, /api/nostr-opportunity-notification) already exist in main.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Enhanced newsletter subscription flow with NIP-05 profile resolution and preview display
    • Added support for configuring multiple CRM subscription lists
    • Improved subscription handling with automatic retry logic for identity conflicts
    • Added multi-relay Nostr event publishing with per-relay progress tracking for notifications

…utomatically
PR #31 replaced the NewsletterCTA NIP-05 flow with a manual email/npub
form, dropping the Nostr notification send. Restore the original flow and
integrate the events.lacrypta.ar CRM subscription into it instead:
- No manual npub field. The npub is derived from the resolved NIP-05
(resolved.pubkey) and registered in the CRM automatically.
- Bring back NIP-05 resolution → profile preview → email / Nostr / both
notification (Resend welcome email + NIP-17 relay publish).
- handleNotify now also POSTs to /api/events-subscribe (npub always; email
and display name when the user opts into email) as the first step.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercelBot commented Jun 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
lacrypta-devReadyReadyPreview, CommentJun 9, 2026 8:14pm

Request Review

@coderabbitai

coderabbitaiBot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR adds CRM list ID configuration with conflict-retry logic to the subscription route, and comprehensively rewrites the newsletter CTA to resolve NIP-05 addresses, support multi-action subscription (email, Nostr, or both), and publish notification events across Nostr relays with per-relay progress tracking.

Changes

Newsletter and CRM Subscription Flow

Layer / File(s)Summary
CRM List Configuration and Conflict Retry
.env.example, app/api/events-subscribe/route.ts
Environment variable EVENTS_SUBSCRIBE_LISTS defines optional CRM list UUIDs; getListIds() parses and defaults the config; subscription handler refactors to share common fields, centralizes CRM calls in a subscribe() helper, and retries separately with email-only then npub-only when a 409 identity conflict occurs.
NIP-05 Resolution and Publishing Infrastructure
components/sections/NewsletterCTA.tsx (lines 3–133)
Shared types for resolution/publishing phases; helper functions for formatting pubkeys, display names, NIP-05 validation; resolveInput() resolves NIP-05 to pubkey/profile/relays; publishNotification() publishes signed events across relays with per-relay progress callbacks and timeout.
CTA State Machine and Async Orchestration
components/sections/NewsletterCTA.tsx (lines 135–327)
Replaces manual email/npub entry with debounced NIP-05 resolution; multi-phase state tracking for subscription and publishing; dynamic action button visibility gating; handleNotify() orchestrates calls to subscription endpoints and notification publishing with progress/phase/error updates.
CTA UI Rendering and Components
components/sections/NewsletterCTA.tsx (lines 345–723)
Container width adjustment; single NIP-05 input replacing old form fields; dynamic action buttons for email/Nostr/both; conditional ProfilePreview showing resolved user details; multi-relay progress visualization; updated status messaging; new ProfilePreview component rendering banner/picture/about/verification.

Sequence Diagram

sequenceDiagram
participant User
participant CTA as NewsletterCTA
participant Resolve as resolveInput
participant API as API Endpoints
participant Pool as SimplePool
participant Relay as Relays
User->>CTA: Enter NIP-05 address
CTA->>Resolve: Resolve NIP-05 (debounced 500ms)
Resolve->>Resolve: Query profile, fetch metadata
Resolve->>CTA: Return pubkey + profile + relays
CTA->>CTA: Update resolution status
User->>CTA: Click Notify (Nostr)
CTA->>API: POST /api/nostr-opportunity-notification
API->>CTA: Return signed event
CTA->>Pool: Initialize SimplePool with relays
Pool->>Relay: Publish event to each relay
Relay->>Pool: Update progress per relay
Pool->>CTA: Per-relay progress callbacks
CTA->>CTA: Update progress panel
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly Related PRs

  • lacrypta/lacrypta-dev#18: This PR's new Nostr-based NewsletterCTA flow now calls /api/nostr-opportunity-notification and publishes the generated event via per-relay progress, matching the endpoint and related CTA rewrite.
  • lacrypta/lacrypta-dev#20: This PR's rewritten NewsletterCTA invokes /api/nostr-opportunity-notification for publishing Nostr notifications, and the retrieved PR changes that route to generate the NIP-17 notification event, so the changes are directly coupled.
  • lacrypta/lacrypta-dev#19: Both PRs modify components/sections/NewsletterCTA.tsx to refactor NIP-05/identity resolution and notification/subscribe flows, so this PR's CTA changes build on the retrieved PR's CTA logic.

Poem

🐰 A rabbit hops through NIP-05 gardens bright,
resolving pubkeys, lists left and right!
From conflict retries to relays in a pool,
the newsletter flows—now NIP-05 is the rule! 🌿✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 7.69% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately reflects the primary changes: restoring NIP-05 resolution, Nostr event sending, and automatic npub derivation from NIP-05 — all core objectives of the PR.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/newsletter-nip05-restore

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

… polish
Newsletter/subscribe refinements on top of the restored NIP-05 flow:
events-subscribe route:
- Subscribe contacts into a CRM list via EVENTS_SUBSCRIBE_LISTS (defaults to
the main newsletter list), forwarded as the `lists` array.
- Gracefully handle 409 identity_conflict on combined email+npub submissions
by retrying each identifier alone (email first) so the contact still lands
in the list.
NewsletterCTA:
- Only send `npub` when the user opts into Nostr, so email-only subscriptions
don't trigger identity_conflict.
- Button visibility: "Notificar por Nostr" is disabled until the NIP-05
resolves and hidden if it resolves badly; "Email + Nostr" is hidden until a
clean resolution; "Notificar por email" stays available (and no error text)
when the NIP-05 fails to resolve. Grid adapts to the visible button count.
- Removed the descriptive NIP-17 panel; re-added the per-relay publish
progress as its own card that auto-scrolls into view during a Nostr publish.
- Combined success line "Te notificamos email y nostr a {email}" when both
channels complete; preview card widened to match the form.
.env.example: document EVENTS_SUBSCRIBE_LISTS.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@agustinkassis
agustinkassis merged commit ce955fd into mainJun 9, 2026
2 of 3 checks passed
@agustinkassis
agustinkassis deleted the fix/newsletter-nip05-restore branch June 9, 2026 20:18
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@agustinkassis
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(subscribe): restore NIP-05 resolution + Nostr send, derive npub automatically - #32

Merged
agustinkassis merged 2 commits into
mainfrom
fix/newsletter-nip05-restore
Jun 9, 2026
Merged

fix(subscribe): restore NIP-05 resolution + Nostr send, derive npub automatically#32
agustinkassis merged 2 commits into
mainfrom
fix/newsletter-nip05-restore

Conversation

@agustinkassis

@agustinkassisagustinkassis commented Jun 9, 2026

Copy link
Copy Markdown
Member

What & why

Follow-up to #31. That PR replaced the homepage NewsletterCTA NIP-05 flow with a manual email/npub form and dropped the Nostr notification send. This restores the original flow and integrates the events.lacrypta.ar CRM subscription into it instead.

Changes (single file: components/sections/NewsletterCTA.tsx)

  • No manual npub field. The npub is derived automatically from the resolved NIP-05 (resolved.pubkey) — the user only enters a NIP-05.
  • Restored NIP-05 resolution → profile preview → notify by email / Nostr / both (Resend welcome email + NIP-17 relay publish with live per-relay progress).
  • handleNotify now also registers the subscriber in the events CRM via POST /api/events-subscribe (npub always; email + display name when the user opts into email) as the first step, before the existing Resend + Nostr notification.

Verification

  • tsc --noEmit clean.
  • /api/events-subscribe accepts the raw hex pubkey the component sends (resolved.pubkey), encodes it to bech32, and the CRM registers it (200 / Subscribed) — verified live.
  • Homepage section renders the NIP-05 input with no npub field and the three Notificar buttons.

Routes the restored component depends on (/api/subscribe, /api/nostr-opportunity-notification) already exist in main.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Enhanced newsletter subscription flow with NIP-05 profile resolution and preview display
    • Added support for configuring multiple CRM subscription lists
    • Improved subscription handling with automatic retry logic for identity conflicts
    • Added multi-relay Nostr event publishing with per-relay progress tracking for notifications

…utomatically
PR #31 replaced the NewsletterCTA NIP-05 flow with a manual email/npub
form, dropping the Nostr notification send. Restore the original flow and
integrate the events.lacrypta.ar CRM subscription into it instead:
- No manual npub field. The npub is derived from the resolved NIP-05
(resolved.pubkey) and registered in the CRM automatically.
- Bring back NIP-05 resolution → profile preview → email / Nostr / both
notification (Resend welcome email + NIP-17 relay publish).
- handleNotify now also POSTs to /api/events-subscribe (npub always; email
and display name when the user opts into email) as the first step.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercelBot commented Jun 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
lacrypta-devReadyReadyPreview, CommentJun 9, 2026 8:14pm

Request Review

@coderabbitai

coderabbitaiBot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR adds CRM list ID configuration with conflict-retry logic to the subscription route, and comprehensively rewrites the newsletter CTA to resolve NIP-05 addresses, support multi-action subscription (email, Nostr, or both), and publish notification events across Nostr relays with per-relay progress tracking.

Changes

Newsletter and CRM Subscription Flow

Layer / File(s)Summary
CRM List Configuration and Conflict Retry
.env.example, app/api/events-subscribe/route.ts
Environment variable EVENTS_SUBSCRIBE_LISTS defines optional CRM list UUIDs; getListIds() parses and defaults the config; subscription handler refactors to share common fields, centralizes CRM calls in a subscribe() helper, and retries separately with email-only then npub-only when a 409 identity conflict occurs.
NIP-05 Resolution and Publishing Infrastructure
components/sections/NewsletterCTA.tsx (lines 3–133)
Shared types for resolution/publishing phases; helper functions for formatting pubkeys, display names, NIP-05 validation; resolveInput() resolves NIP-05 to pubkey/profile/relays; publishNotification() publishes signed events across relays with per-relay progress callbacks and timeout.
CTA State Machine and Async Orchestration
components/sections/NewsletterCTA.tsx (lines 135–327)
Replaces manual email/npub entry with debounced NIP-05 resolution; multi-phase state tracking for subscription and publishing; dynamic action button visibility gating; handleNotify() orchestrates calls to subscription endpoints and notification publishing with progress/phase/error updates.
CTA UI Rendering and Components
components/sections/NewsletterCTA.tsx (lines 345–723)
Container width adjustment; single NIP-05 input replacing old form fields; dynamic action buttons for email/Nostr/both; conditional ProfilePreview showing resolved user details; multi-relay progress visualization; updated status messaging; new ProfilePreview component rendering banner/picture/about/verification.

Sequence Diagram

sequenceDiagram
participant User
participant CTA as NewsletterCTA
participant Resolve as resolveInput
participant API as API Endpoints
participant Pool as SimplePool
participant Relay as Relays
User->>CTA: Enter NIP-05 address
CTA->>Resolve: Resolve NIP-05 (debounced 500ms)
Resolve->>Resolve: Query profile, fetch metadata
Resolve->>CTA: Return pubkey + profile + relays
CTA->>CTA: Update resolution status
User->>CTA: Click Notify (Nostr)
CTA->>API: POST /api/nostr-opportunity-notification
API->>CTA: Return signed event
CTA->>Pool: Initialize SimplePool with relays
Pool->>Relay: Publish event to each relay
Relay->>Pool: Update progress per relay
Pool->>CTA: Per-relay progress callbacks
CTA->>CTA: Update progress panel
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly Related PRs

  • lacrypta/lacrypta-dev#18: This PR's new Nostr-based NewsletterCTA flow now calls /api/nostr-opportunity-notification and publishes the generated event via per-relay progress, matching the endpoint and related CTA rewrite.
  • lacrypta/lacrypta-dev#20: This PR's rewritten NewsletterCTA invokes /api/nostr-opportunity-notification for publishing Nostr notifications, and the retrieved PR changes that route to generate the NIP-17 notification event, so the changes are directly coupled.
  • lacrypta/lacrypta-dev#19: Both PRs modify components/sections/NewsletterCTA.tsx to refactor NIP-05/identity resolution and notification/subscribe flows, so this PR's CTA changes build on the retrieved PR's CTA logic.

Poem

🐰 A rabbit hops through NIP-05 gardens bright,
resolving pubkeys, lists left and right!
From conflict retries to relays in a pool,
the newsletter flows—now NIP-05 is the rule! 🌿✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 7.69% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately reflects the primary changes: restoring NIP-05 resolution, Nostr event sending, and automatic npub derivation from NIP-05 — all core objectives of the PR.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/newsletter-nip05-restore

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

… polish
Newsletter/subscribe refinements on top of the restored NIP-05 flow:
events-subscribe route:
- Subscribe contacts into a CRM list via EVENTS_SUBSCRIBE_LISTS (defaults to
the main newsletter list), forwarded as the `lists` array.
- Gracefully handle 409 identity_conflict on combined email+npub submissions
by retrying each identifier alone (email first) so the contact still lands
in the list.
NewsletterCTA:
- Only send `npub` when the user opts into Nostr, so email-only subscriptions
don't trigger identity_conflict.
- Button visibility: "Notificar por Nostr" is disabled until the NIP-05
resolves and hidden if it resolves badly; "Email + Nostr" is hidden until a
clean resolution; "Notificar por email" stays available (and no error text)
when the NIP-05 fails to resolve. Grid adapts to the visible button count.
- Removed the descriptive NIP-17 panel; re-added the per-relay publish
progress as its own card that auto-scrolls into view during a Nostr publish.
- Combined success line "Te notificamos email y nostr a {email}" when both
channels complete; preview card widened to match the form.
.env.example: document EVENTS_SUBSCRIBE_LISTS.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@agustinkassis
agustinkassis merged commit ce955fd into mainJun 9, 2026
2 of 3 checks passed
@agustinkassis
agustinkassis deleted the fix/newsletter-nip05-restore branch June 9, 2026 20:18
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@agustinkassis
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

fix(subscribe): restore NIP-05 resolution + Nostr send, derive npub automatically - #32

Merged
agustinkassis merged 2 commits into
mainfrom
fix/newsletter-nip05-restore
Jun 9, 2026
Merged

fix(subscribe): restore NIP-05 resolution + Nostr send, derive npub automatically#32
agustinkassis merged 2 commits into
mainfrom
fix/newsletter-nip05-restore

Conversation

@agustinkassis

@agustinkassisagustinkassis commented Jun 9, 2026

Copy link
Copy Markdown
Member

What & why

Follow-up to #31. That PR replaced the homepage NewsletterCTA NIP-05 flow with a manual email/npub form and dropped the Nostr notification send. This restores the original flow and integrates the events.lacrypta.ar CRM subscription into it instead.

Changes (single file: components/sections/NewsletterCTA.tsx)

  • No manual npub field. The npub is derived automatically from the resolved NIP-05 (resolved.pubkey) — the user only enters a NIP-05.
  • Restored NIP-05 resolution → profile preview → notify by email / Nostr / both (Resend welcome email + NIP-17 relay publish with live per-relay progress).
  • handleNotify now also registers the subscriber in the events CRM via POST /api/events-subscribe (npub always; email + display name when the user opts into email) as the first step, before the existing Resend + Nostr notification.

Verification

  • tsc --noEmit clean.
  • /api/events-subscribe accepts the raw hex pubkey the component sends (resolved.pubkey), encodes it to bech32, and the CRM registers it (200 / Subscribed) — verified live.
  • Homepage section renders the NIP-05 input with no npub field and the three Notificar buttons.

Routes the restored component depends on (/api/subscribe, /api/nostr-opportunity-notification) already exist in main.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Enhanced newsletter subscription flow with NIP-05 profile resolution and preview display
    • Added support for configuring multiple CRM subscription lists
    • Improved subscription handling with automatic retry logic for identity conflicts
    • Added multi-relay Nostr event publishing with per-relay progress tracking for notifications

…utomatically
PR #31 replaced the NewsletterCTA NIP-05 flow with a manual email/npub
form, dropping the Nostr notification send. Restore the original flow and
integrate the events.lacrypta.ar CRM subscription into it instead:
- No manual npub field. The npub is derived from the resolved NIP-05
(resolved.pubkey) and registered in the CRM automatically.
- Bring back NIP-05 resolution → profile preview → email / Nostr / both
notification (Resend welcome email + NIP-17 relay publish).
- handleNotify now also POSTs to /api/events-subscribe (npub always; email
and display name when the user opts into email) as the first step.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercelBot commented Jun 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
lacrypta-devReadyReadyPreview, CommentJun 9, 2026 8:14pm

Request Review

@coderabbitai

coderabbitaiBot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR adds CRM list ID configuration with conflict-retry logic to the subscription route, and comprehensively rewrites the newsletter CTA to resolve NIP-05 addresses, support multi-action subscription (email, Nostr, or both), and publish notification events across Nostr relays with per-relay progress tracking.

Changes

Newsletter and CRM Subscription Flow

Layer / File(s)Summary
CRM List Configuration and Conflict Retry
.env.example, app/api/events-subscribe/route.ts
Environment variable EVENTS_SUBSCRIBE_LISTS defines optional CRM list UUIDs; getListIds() parses and defaults the config; subscription handler refactors to share common fields, centralizes CRM calls in a subscribe() helper, and retries separately with email-only then npub-only when a 409 identity conflict occurs.
NIP-05 Resolution and Publishing Infrastructure
components/sections/NewsletterCTA.tsx (lines 3–133)
Shared types for resolution/publishing phases; helper functions for formatting pubkeys, display names, NIP-05 validation; resolveInput() resolves NIP-05 to pubkey/profile/relays; publishNotification() publishes signed events across relays with per-relay progress callbacks and timeout.
CTA State Machine and Async Orchestration
components/sections/NewsletterCTA.tsx (lines 135–327)
Replaces manual email/npub entry with debounced NIP-05 resolution; multi-phase state tracking for subscription and publishing; dynamic action button visibility gating; handleNotify() orchestrates calls to subscription endpoints and notification publishing with progress/phase/error updates.
CTA UI Rendering and Components
components/sections/NewsletterCTA.tsx (lines 345–723)
Container width adjustment; single NIP-05 input replacing old form fields; dynamic action buttons for email/Nostr/both; conditional ProfilePreview showing resolved user details; multi-relay progress visualization; updated status messaging; new ProfilePreview component rendering banner/picture/about/verification.

Sequence Diagram

sequenceDiagram
participant User
participant CTA as NewsletterCTA
participant Resolve as resolveInput
participant API as API Endpoints
participant Pool as SimplePool
participant Relay as Relays
User->>CTA: Enter NIP-05 address
CTA->>Resolve: Resolve NIP-05 (debounced 500ms)
Resolve->>Resolve: Query profile, fetch metadata
Resolve->>CTA: Return pubkey + profile + relays
CTA->>CTA: Update resolution status
User->>CTA: Click Notify (Nostr)
CTA->>API: POST /api/nostr-opportunity-notification
API->>CTA: Return signed event
CTA->>Pool: Initialize SimplePool with relays
Pool->>Relay: Publish event to each relay
Relay->>Pool: Update progress per relay
Pool->>CTA: Per-relay progress callbacks
CTA->>CTA: Update progress panel
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly Related PRs

  • lacrypta/lacrypta-dev#18: This PR's new Nostr-based NewsletterCTA flow now calls /api/nostr-opportunity-notification and publishes the generated event via per-relay progress, matching the endpoint and related CTA rewrite.
  • lacrypta/lacrypta-dev#20: This PR's rewritten NewsletterCTA invokes /api/nostr-opportunity-notification for publishing Nostr notifications, and the retrieved PR changes that route to generate the NIP-17 notification event, so the changes are directly coupled.
  • lacrypta/lacrypta-dev#19: Both PRs modify components/sections/NewsletterCTA.tsx to refactor NIP-05/identity resolution and notification/subscribe flows, so this PR's CTA changes build on the retrieved PR's CTA logic.

Poem

🐰 A rabbit hops through NIP-05 gardens bright,
resolving pubkeys, lists left and right!
From conflict retries to relays in a pool,
the newsletter flows—now NIP-05 is the rule! 🌿✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 7.69% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately reflects the primary changes: restoring NIP-05 resolution, Nostr event sending, and automatic npub derivation from NIP-05 — all core objectives of the PR.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/newsletter-nip05-restore

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

… polish
Newsletter/subscribe refinements on top of the restored NIP-05 flow:
events-subscribe route:
- Subscribe contacts into a CRM list via EVENTS_SUBSCRIBE_LISTS (defaults to
the main newsletter list), forwarded as the `lists` array.
- Gracefully handle 409 identity_conflict on combined email+npub submissions
by retrying each identifier alone (email first) so the contact still lands
in the list.
NewsletterCTA:
- Only send `npub` when the user opts into Nostr, so email-only subscriptions
don't trigger identity_conflict.
- Button visibility: "Notificar por Nostr" is disabled until the NIP-05
resolves and hidden if it resolves badly; "Email + Nostr" is hidden until a
clean resolution; "Notificar por email" stays available (and no error text)
when the NIP-05 fails to resolve. Grid adapts to the visible button count.
- Removed the descriptive NIP-17 panel; re-added the per-relay publish
progress as its own card that auto-scrolls into view during a Nostr publish.
- Combined success line "Te notificamos email y nostr a {email}" when both
channels complete; preview card widened to match the form.
.env.example: document EVENTS_SUBSCRIBE_LISTS.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@agustinkassis
agustinkassis merged commit ce955fd into mainJun 9, 2026
2 of 3 checks passed
@agustinkassis
agustinkassis deleted the fix/newsletter-nip05-restore branch June 9, 2026 20:18
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@agustinkassis
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(subscribe): restore NIP-05 resolution + Nostr send, derive npub automatically - #32

Merged
agustinkassis merged 2 commits into
mainfrom
fix/newsletter-nip05-restore
Jun 9, 2026
Merged

fix(subscribe): restore NIP-05 resolution + Nostr send, derive npub automatically#32
agustinkassis merged 2 commits into
mainfrom
fix/newsletter-nip05-restore

Conversation

@agustinkassis

@agustinkassisagustinkassis commented Jun 9, 2026

Copy link
Copy Markdown
Member

What & why

Follow-up to #31. That PR replaced the homepage NewsletterCTA NIP-05 flow with a manual email/npub form and dropped the Nostr notification send. This restores the original flow and integrates the events.lacrypta.ar CRM subscription into it instead.

Changes (single file: components/sections/NewsletterCTA.tsx)

  • No manual npub field. The npub is derived automatically from the resolved NIP-05 (resolved.pubkey) — the user only enters a NIP-05.
  • Restored NIP-05 resolution → profile preview → notify by email / Nostr / both (Resend welcome email + NIP-17 relay publish with live per-relay progress).
  • handleNotify now also registers the subscriber in the events CRM via POST /api/events-subscribe (npub always; email + display name when the user opts into email) as the first step, before the existing Resend + Nostr notification.

Verification

  • tsc --noEmit clean.
  • /api/events-subscribe accepts the raw hex pubkey the component sends (resolved.pubkey), encodes it to bech32, and the CRM registers it (200 / Subscribed) — verified live.
  • Homepage section renders the NIP-05 input with no npub field and the three Notificar buttons.

Routes the restored component depends on (/api/subscribe, /api/nostr-opportunity-notification) already exist in main.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Enhanced newsletter subscription flow with NIP-05 profile resolution and preview display
    • Added support for configuring multiple CRM subscription lists
    • Improved subscription handling with automatic retry logic for identity conflicts
    • Added multi-relay Nostr event publishing with per-relay progress tracking for notifications

…utomatically
PR #31 replaced the NewsletterCTA NIP-05 flow with a manual email/npub
form, dropping the Nostr notification send. Restore the original flow and
integrate the events.lacrypta.ar CRM subscription into it instead:
- No manual npub field. The npub is derived from the resolved NIP-05
(resolved.pubkey) and registered in the CRM automatically.
- Bring back NIP-05 resolution → profile preview → email / Nostr / both
notification (Resend welcome email + NIP-17 relay publish).
- handleNotify now also POSTs to /api/events-subscribe (npub always; email
and display name when the user opts into email) as the first step.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercelBot commented Jun 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
lacrypta-devReadyReadyPreview, CommentJun 9, 2026 8:14pm

Request Review

@coderabbitai

coderabbitaiBot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR adds CRM list ID configuration with conflict-retry logic to the subscription route, and comprehensively rewrites the newsletter CTA to resolve NIP-05 addresses, support multi-action subscription (email, Nostr, or both), and publish notification events across Nostr relays with per-relay progress tracking.

Changes

Newsletter and CRM Subscription Flow

Layer / File(s)Summary
CRM List Configuration and Conflict Retry
.env.example, app/api/events-subscribe/route.ts
Environment variable EVENTS_SUBSCRIBE_LISTS defines optional CRM list UUIDs; getListIds() parses and defaults the config; subscription handler refactors to share common fields, centralizes CRM calls in a subscribe() helper, and retries separately with email-only then npub-only when a 409 identity conflict occurs.
NIP-05 Resolution and Publishing Infrastructure
components/sections/NewsletterCTA.tsx (lines 3–133)
Shared types for resolution/publishing phases; helper functions for formatting pubkeys, display names, NIP-05 validation; resolveInput() resolves NIP-05 to pubkey/profile/relays; publishNotification() publishes signed events across relays with per-relay progress callbacks and timeout.
CTA State Machine and Async Orchestration
components/sections/NewsletterCTA.tsx (lines 135–327)
Replaces manual email/npub entry with debounced NIP-05 resolution; multi-phase state tracking for subscription and publishing; dynamic action button visibility gating; handleNotify() orchestrates calls to subscription endpoints and notification publishing with progress/phase/error updates.
CTA UI Rendering and Components
components/sections/NewsletterCTA.tsx (lines 345–723)
Container width adjustment; single NIP-05 input replacing old form fields; dynamic action buttons for email/Nostr/both; conditional ProfilePreview showing resolved user details; multi-relay progress visualization; updated status messaging; new ProfilePreview component rendering banner/picture/about/verification.

Sequence Diagram

sequenceDiagram
participant User
participant CTA as NewsletterCTA
participant Resolve as resolveInput
participant API as API Endpoints
participant Pool as SimplePool
participant Relay as Relays
User->>CTA: Enter NIP-05 address
CTA->>Resolve: Resolve NIP-05 (debounced 500ms)
Resolve->>Resolve: Query profile, fetch metadata
Resolve->>CTA: Return pubkey + profile + relays
CTA->>CTA: Update resolution status
User->>CTA: Click Notify (Nostr)
CTA->>API: POST /api/nostr-opportunity-notification
API->>CTA: Return signed event
CTA->>Pool: Initialize SimplePool with relays
Pool->>Relay: Publish event to each relay
Relay->>Pool: Update progress per relay
Pool->>CTA: Per-relay progress callbacks
CTA->>CTA: Update progress panel
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly Related PRs

  • lacrypta/lacrypta-dev#18: This PR's new Nostr-based NewsletterCTA flow now calls /api/nostr-opportunity-notification and publishes the generated event via per-relay progress, matching the endpoint and related CTA rewrite.
  • lacrypta/lacrypta-dev#20: This PR's rewritten NewsletterCTA invokes /api/nostr-opportunity-notification for publishing Nostr notifications, and the retrieved PR changes that route to generate the NIP-17 notification event, so the changes are directly coupled.
  • lacrypta/lacrypta-dev#19: Both PRs modify components/sections/NewsletterCTA.tsx to refactor NIP-05/identity resolution and notification/subscribe flows, so this PR's CTA changes build on the retrieved PR's CTA logic.

Poem

🐰 A rabbit hops through NIP-05 gardens bright,
resolving pubkeys, lists left and right!
From conflict retries to relays in a pool,
the newsletter flows—now NIP-05 is the rule! 🌿✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 7.69% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately reflects the primary changes: restoring NIP-05 resolution, Nostr event sending, and automatic npub derivation from NIP-05 — all core objectives of the PR.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/newsletter-nip05-restore

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

… polish
Newsletter/subscribe refinements on top of the restored NIP-05 flow:
events-subscribe route:
- Subscribe contacts into a CRM list via EVENTS_SUBSCRIBE_LISTS (defaults to
the main newsletter list), forwarded as the `lists` array.
- Gracefully handle 409 identity_conflict on combined email+npub submissions
by retrying each identifier alone (email first) so the contact still lands
in the list.
NewsletterCTA:
- Only send `npub` when the user opts into Nostr, so email-only subscriptions
don't trigger identity_conflict.
- Button visibility: "Notificar por Nostr" is disabled until the NIP-05
resolves and hidden if it resolves badly; "Email + Nostr" is hidden until a
clean resolution; "Notificar por email" stays available (and no error text)
when the NIP-05 fails to resolve. Grid adapts to the visible button count.
- Removed the descriptive NIP-17 panel; re-added the per-relay publish
progress as its own card that auto-scrolls into view during a Nostr publish.
- Combined success line "Te notificamos email y nostr a {email}" when both
channels complete; preview card widened to match the form.
.env.example: document EVENTS_SUBSCRIBE_LISTS.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@agustinkassis
agustinkassis merged commit ce955fd into mainJun 9, 2026
2 of 3 checks passed
@agustinkassis
agustinkassis deleted the fix/newsletter-nip05-restore branch June 9, 2026 20:18
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@agustinkassis
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(subscribe): restore NIP-05 resolution + Nostr send, derive npub automatically - #32

Merged
agustinkassis merged 2 commits into
mainfrom
fix/newsletter-nip05-restore
Jun 9, 2026
Merged

fix(subscribe): restore NIP-05 resolution + Nostr send, derive npub automatically#32
agustinkassis merged 2 commits into
mainfrom
fix/newsletter-nip05-restore

Conversation

@agustinkassis

@agustinkassisagustinkassis commented Jun 9, 2026

Copy link
Copy Markdown
Member

What & why

Follow-up to #31. That PR replaced the homepage NewsletterCTA NIP-05 flow with a manual email/npub form and dropped the Nostr notification send. This restores the original flow and integrates the events.lacrypta.ar CRM subscription into it instead.

Changes (single file: components/sections/NewsletterCTA.tsx)

  • No manual npub field. The npub is derived automatically from the resolved NIP-05 (resolved.pubkey) — the user only enters a NIP-05.
  • Restored NIP-05 resolution → profile preview → notify by email / Nostr / both (Resend welcome email + NIP-17 relay publish with live per-relay progress).
  • handleNotify now also registers the subscriber in the events CRM via POST /api/events-subscribe (npub always; email + display name when the user opts into email) as the first step, before the existing Resend + Nostr notification.

Verification

  • tsc --noEmit clean.
  • /api/events-subscribe accepts the raw hex pubkey the component sends (resolved.pubkey), encodes it to bech32, and the CRM registers it (200 / Subscribed) — verified live.
  • Homepage section renders the NIP-05 input with no npub field and the three Notificar buttons.

Routes the restored component depends on (/api/subscribe, /api/nostr-opportunity-notification) already exist in main.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Enhanced newsletter subscription flow with NIP-05 profile resolution and preview display
    • Added support for configuring multiple CRM subscription lists
    • Improved subscription handling with automatic retry logic for identity conflicts
    • Added multi-relay Nostr event publishing with per-relay progress tracking for notifications

…utomatically
PR #31 replaced the NewsletterCTA NIP-05 flow with a manual email/npub
form, dropping the Nostr notification send. Restore the original flow and
integrate the events.lacrypta.ar CRM subscription into it instead:
- No manual npub field. The npub is derived from the resolved NIP-05
(resolved.pubkey) and registered in the CRM automatically.
- Bring back NIP-05 resolution → profile preview → email / Nostr / both
notification (Resend welcome email + NIP-17 relay publish).
- handleNotify now also POSTs to /api/events-subscribe (npub always; email
and display name when the user opts into email) as the first step.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercelBot commented Jun 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
lacrypta-devReadyReadyPreview, CommentJun 9, 2026 8:14pm

Request Review

@coderabbitai

coderabbitaiBot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR adds CRM list ID configuration with conflict-retry logic to the subscription route, and comprehensively rewrites the newsletter CTA to resolve NIP-05 addresses, support multi-action subscription (email, Nostr, or both), and publish notification events across Nostr relays with per-relay progress tracking.

Changes

Newsletter and CRM Subscription Flow

Layer / File(s)Summary
CRM List Configuration and Conflict Retry
.env.example, app/api/events-subscribe/route.ts
Environment variable EVENTS_SUBSCRIBE_LISTS defines optional CRM list UUIDs; getListIds() parses and defaults the config; subscription handler refactors to share common fields, centralizes CRM calls in a subscribe() helper, and retries separately with email-only then npub-only when a 409 identity conflict occurs.
NIP-05 Resolution and Publishing Infrastructure
components/sections/NewsletterCTA.tsx (lines 3–133)
Shared types for resolution/publishing phases; helper functions for formatting pubkeys, display names, NIP-05 validation; resolveInput() resolves NIP-05 to pubkey/profile/relays; publishNotification() publishes signed events across relays with per-relay progress callbacks and timeout.
CTA State Machine and Async Orchestration
components/sections/NewsletterCTA.tsx (lines 135–327)
Replaces manual email/npub entry with debounced NIP-05 resolution; multi-phase state tracking for subscription and publishing; dynamic action button visibility gating; handleNotify() orchestrates calls to subscription endpoints and notification publishing with progress/phase/error updates.
CTA UI Rendering and Components
components/sections/NewsletterCTA.tsx (lines 345–723)
Container width adjustment; single NIP-05 input replacing old form fields; dynamic action buttons for email/Nostr/both; conditional ProfilePreview showing resolved user details; multi-relay progress visualization; updated status messaging; new ProfilePreview component rendering banner/picture/about/verification.

Sequence Diagram

sequenceDiagram
participant User
participant CTA as NewsletterCTA
participant Resolve as resolveInput
participant API as API Endpoints
participant Pool as SimplePool
participant Relay as Relays
User->>CTA: Enter NIP-05 address
CTA->>Resolve: Resolve NIP-05 (debounced 500ms)
Resolve->>Resolve: Query profile, fetch metadata
Resolve->>CTA: Return pubkey + profile + relays
CTA->>CTA: Update resolution status
User->>CTA: Click Notify (Nostr)
CTA->>API: POST /api/nostr-opportunity-notification
API->>CTA: Return signed event
CTA->>Pool: Initialize SimplePool with relays
Pool->>Relay: Publish event to each relay
Relay->>Pool: Update progress per relay
Pool->>CTA: Per-relay progress callbacks
CTA->>CTA: Update progress panel
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly Related PRs

  • lacrypta/lacrypta-dev#18: This PR's new Nostr-based NewsletterCTA flow now calls /api/nostr-opportunity-notification and publishes the generated event via per-relay progress, matching the endpoint and related CTA rewrite.
  • lacrypta/lacrypta-dev#20: This PR's rewritten NewsletterCTA invokes /api/nostr-opportunity-notification for publishing Nostr notifications, and the retrieved PR changes that route to generate the NIP-17 notification event, so the changes are directly coupled.
  • lacrypta/lacrypta-dev#19: Both PRs modify components/sections/NewsletterCTA.tsx to refactor NIP-05/identity resolution and notification/subscribe flows, so this PR's CTA changes build on the retrieved PR's CTA logic.

Poem

🐰 A rabbit hops through NIP-05 gardens bright,
resolving pubkeys, lists left and right!
From conflict retries to relays in a pool,
the newsletter flows—now NIP-05 is the rule! 🌿✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 7.69% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately reflects the primary changes: restoring NIP-05 resolution, Nostr event sending, and automatic npub derivation from NIP-05 — all core objectives of the PR.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/newsletter-nip05-restore

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

… polish
Newsletter/subscribe refinements on top of the restored NIP-05 flow:
events-subscribe route:
- Subscribe contacts into a CRM list via EVENTS_SUBSCRIBE_LISTS (defaults to
the main newsletter list), forwarded as the `lists` array.
- Gracefully handle 409 identity_conflict on combined email+npub submissions
by retrying each identifier alone (email first) so the contact still lands
in the list.
NewsletterCTA:
- Only send `npub` when the user opts into Nostr, so email-only subscriptions
don't trigger identity_conflict.
- Button visibility: "Notificar por Nostr" is disabled until the NIP-05
resolves and hidden if it resolves badly; "Email + Nostr" is hidden until a
clean resolution; "Notificar por email" stays available (and no error text)
when the NIP-05 fails to resolve. Grid adapts to the visible button count.
- Removed the descriptive NIP-17 panel; re-added the per-relay publish
progress as its own card that auto-scrolls into view during a Nostr publish.
- Combined success line "Te notificamos email y nostr a {email}" when both
channels complete; preview card widened to match the form.
.env.example: document EVENTS_SUBSCRIBE_LISTS.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@agustinkassis
agustinkassis merged commit ce955fd into mainJun 9, 2026
2 of 3 checks passed
@agustinkassis
agustinkassis deleted the fix/newsletter-nip05-restore branch June 9, 2026 20:18
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@agustinkassis
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

fix(subscribe): restore NIP-05 resolution + Nostr send, derive npub automatically - #32

Merged
agustinkassis merged 2 commits into
mainfrom
fix/newsletter-nip05-restore
Jun 9, 2026
Merged

fix(subscribe): restore NIP-05 resolution + Nostr send, derive npub automatically#32
agustinkassis merged 2 commits into
mainfrom
fix/newsletter-nip05-restore

Conversation

@agustinkassis

@agustinkassisagustinkassis commented Jun 9, 2026

Copy link
Copy Markdown
Member

What & why

Follow-up to #31. That PR replaced the homepage NewsletterCTA NIP-05 flow with a manual email/npub form and dropped the Nostr notification send. This restores the original flow and integrates the events.lacrypta.ar CRM subscription into it instead.

Changes (single file: components/sections/NewsletterCTA.tsx)

  • No manual npub field. The npub is derived automatically from the resolved NIP-05 (resolved.pubkey) — the user only enters a NIP-05.
  • Restored NIP-05 resolution → profile preview → notify by email / Nostr / both (Resend welcome email + NIP-17 relay publish with live per-relay progress).
  • handleNotify now also registers the subscriber in the events CRM via POST /api/events-subscribe (npub always; email + display name when the user opts into email) as the first step, before the existing Resend + Nostr notification.

Verification

  • tsc --noEmit clean.
  • /api/events-subscribe accepts the raw hex pubkey the component sends (resolved.pubkey), encodes it to bech32, and the CRM registers it (200 / Subscribed) — verified live.
  • Homepage section renders the NIP-05 input with no npub field and the three Notificar buttons.

Routes the restored component depends on (/api/subscribe, /api/nostr-opportunity-notification) already exist in main.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Enhanced newsletter subscription flow with NIP-05 profile resolution and preview display
    • Added support for configuring multiple CRM subscription lists
    • Improved subscription handling with automatic retry logic for identity conflicts
    • Added multi-relay Nostr event publishing with per-relay progress tracking for notifications

…utomatically
PR #31 replaced the NewsletterCTA NIP-05 flow with a manual email/npub
form, dropping the Nostr notification send. Restore the original flow and
integrate the events.lacrypta.ar CRM subscription into it instead:
- No manual npub field. The npub is derived from the resolved NIP-05
(resolved.pubkey) and registered in the CRM automatically.
- Bring back NIP-05 resolution → profile preview → email / Nostr / both
notification (Resend welcome email + NIP-17 relay publish).
- handleNotify now also POSTs to /api/events-subscribe (npub always; email
and display name when the user opts into email) as the first step.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercelBot commented Jun 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
lacrypta-devReadyReadyPreview, CommentJun 9, 2026 8:14pm

Request Review

@coderabbitai

coderabbitaiBot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR adds CRM list ID configuration with conflict-retry logic to the subscription route, and comprehensively rewrites the newsletter CTA to resolve NIP-05 addresses, support multi-action subscription (email, Nostr, or both), and publish notification events across Nostr relays with per-relay progress tracking.

Changes

Newsletter and CRM Subscription Flow

Layer / File(s)Summary
CRM List Configuration and Conflict Retry
.env.example, app/api/events-subscribe/route.ts
Environment variable EVENTS_SUBSCRIBE_LISTS defines optional CRM list UUIDs; getListIds() parses and defaults the config; subscription handler refactors to share common fields, centralizes CRM calls in a subscribe() helper, and retries separately with email-only then npub-only when a 409 identity conflict occurs.
NIP-05 Resolution and Publishing Infrastructure
components/sections/NewsletterCTA.tsx (lines 3–133)
Shared types for resolution/publishing phases; helper functions for formatting pubkeys, display names, NIP-05 validation; resolveInput() resolves NIP-05 to pubkey/profile/relays; publishNotification() publishes signed events across relays with per-relay progress callbacks and timeout.
CTA State Machine and Async Orchestration
components/sections/NewsletterCTA.tsx (lines 135–327)
Replaces manual email/npub entry with debounced NIP-05 resolution; multi-phase state tracking for subscription and publishing; dynamic action button visibility gating; handleNotify() orchestrates calls to subscription endpoints and notification publishing with progress/phase/error updates.
CTA UI Rendering and Components
components/sections/NewsletterCTA.tsx (lines 345–723)
Container width adjustment; single NIP-05 input replacing old form fields; dynamic action buttons for email/Nostr/both; conditional ProfilePreview showing resolved user details; multi-relay progress visualization; updated status messaging; new ProfilePreview component rendering banner/picture/about/verification.

Sequence Diagram

sequenceDiagram
participant User
participant CTA as NewsletterCTA
participant Resolve as resolveInput
participant API as API Endpoints
participant Pool as SimplePool
participant Relay as Relays
User->>CTA: Enter NIP-05 address
CTA->>Resolve: Resolve NIP-05 (debounced 500ms)
Resolve->>Resolve: Query profile, fetch metadata
Resolve->>CTA: Return pubkey + profile + relays
CTA->>CTA: Update resolution status
User->>CTA: Click Notify (Nostr)
CTA->>API: POST /api/nostr-opportunity-notification
API->>CTA: Return signed event
CTA->>Pool: Initialize SimplePool with relays
Pool->>Relay: Publish event to each relay
Relay->>Pool: Update progress per relay
Pool->>CTA: Per-relay progress callbacks
CTA->>CTA: Update progress panel
Loading

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly Related PRs

  • lacrypta/lacrypta-dev#18: This PR's new Nostr-based NewsletterCTA flow now calls /api/nostr-opportunity-notification and publishes the generated event via per-relay progress, matching the endpoint and related CTA rewrite.
  • lacrypta/lacrypta-dev#20: This PR's rewritten NewsletterCTA invokes /api/nostr-opportunity-notification for publishing Nostr notifications, and the retrieved PR changes that route to generate the NIP-17 notification event, so the changes are directly coupled.
  • lacrypta/lacrypta-dev#19: Both PRs modify components/sections/NewsletterCTA.tsx to refactor NIP-05/identity resolution and notification/subscribe flows, so this PR's CTA changes build on the retrieved PR's CTA logic.

Poem

🐰 A rabbit hops through NIP-05 gardens bright,
resolving pubkeys, lists left and right!
From conflict retries to relays in a pool,
the newsletter flows—now NIP-05 is the rule! 🌿✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check nameStatusExplanationResolution
Docstring Coverage⚠️ WarningDocstring coverage is 7.69% which is insufficient. The required threshold is 80.00%.Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title accurately reflects the primary changes: restoring NIP-05 resolution, Nostr event sending, and automatic npub derivation from NIP-05 — all core objectives of the PR.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/newsletter-nip05-restore

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

… polish
Newsletter/subscribe refinements on top of the restored NIP-05 flow:
events-subscribe route:
- Subscribe contacts into a CRM list via EVENTS_SUBSCRIBE_LISTS (defaults to
the main newsletter list), forwarded as the `lists` array.
- Gracefully handle 409 identity_conflict on combined email+npub submissions
by retrying each identifier alone (email first) so the contact still lands
in the list.
NewsletterCTA:
- Only send `npub` when the user opts into Nostr, so email-only subscriptions
don't trigger identity_conflict.
- Button visibility: "Notificar por Nostr" is disabled until the NIP-05
resolves and hidden if it resolves badly; "Email + Nostr" is hidden until a
clean resolution; "Notificar por email" stays available (and no error text)
when the NIP-05 fails to resolve. Grid adapts to the visible button count.
- Removed the descriptive NIP-17 panel; re-added the per-relay publish
progress as its own card that auto-scrolls into view during a Nostr publish.
- Combined success line "Te notificamos email y nostr a {email}" when both
channels complete; preview card widened to match the form.
.env.example: document EVENTS_SUBSCRIBE_LISTS.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@agustinkassis
agustinkassis merged commit ce955fd into mainJun 9, 2026
2 of 3 checks passed
@agustinkassis
agustinkassis deleted the fix/newsletter-nip05-restore branch June 9, 2026 20:18
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@agustinkassis