[codex] Fix standalone Nostr project routes - #22

Merged
agustinkassis merged 1 commit into
mainfrom
codex/fix-standalone-project-route
Jun 3, 2026
Merged

[codex] Fix standalone Nostr project routes#22
agustinkassis merged 1 commit into
mainfrom
codex/fix-standalone-project-route

Conversation

@agustinkassis

@agustinkassisagustinkassis commented Jun 3, 2026

Copy link
Copy Markdown
Member

Summary

  • Resolve /projects/[pubkey]/[id] params inside a Suspense boundary so Cache Components does not prerender placeholder [pubkey] / [id] values into the client payload.
  • Add snapshot and broad relay fallback for standalone project pages, using the same flexible project identity matching as hackathon project detail pages.
  • Preserve direct relay lookup first, then recover from /api/nostr-projects or relay scans before showing Proyecto no encontrado.

Root Cause

The production HTML for standalone project routes was hydrating StandaloneProjectPage with encoded placeholder params (%5Bpubkey%5D and %5Bid%5D) instead of the real URL segments. The client then queried Nostr using those placeholders, so existing projects looked missing. The standalone route also only tried an exact authors + #d relay query, without the snapshot fallback used elsewhere.

Validation

  • pnpm exec tsc --noEmit
  • pnpm build
  • Confirmed local HTML now serializes the real pubkey and projectId for the reported URL.
  • Confirmed /api/nostr-projects contains the reported project (Arcade timba simulator).
  • Verified in the in-app browser that the reported URL loads Arcade timba simulator and does not show Proyecto no encontrado.

Summary by CodeRabbit

  • Bug Fixes
    • Improved project discovery with enhanced fallback mechanisms that attempt multiple lookup strategies across different data sources for better reliability.
    • Refined user experience during page initialization with animated loading indicator displayed while page content is being prepared.

@vercel

vercelBot commented Jun 3, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
lacrypta-devReadyReadyPreview, CommentJun 3, 2026 9:18pm

Request Review

@coderabbitai

coderabbitaiBot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9f85e6c8-d6c1-429d-9774-52763aa09135

📥 Commits

Reviewing files that changed from the base of the PR and between d410dff and 66edb6d.

📒 Files selected for processing (2)
  • app/projects/[pubkey]/[id]/StandaloneProjectPage.tsx
  • app/projects/[pubkey]/[id]/page.tsx

📝 Walkthrough

Walkthrough

The pull request enhances the project detail page with a resilient data-loading strategy and improves perceived performance through early rendering. StandaloneProjectPage now implements a multi-tier fallback mechanism that attempts to load a project directly, then searches a snapshot, and finally queries a broader community relay if needed. Route parameter resolution is decoupled from rendering via Suspense, allowing a loading skeleton to display while parameters and project data are fetched asynchronously.

Changes

Project Detail Page Loading Architecture

Layer / File(s)Summary
Multi-tier Project Lookup with Fallbacks
app/projects/[pubkey]/[id]/StandaloneProjectPage.tsx
Extends imports to include fetchCommunityProjects, fetchCommunityProjectsSnapshot, and projectMatchesIdentifier. The useEffect loader is rewritten with AbortController cancellation: it attempts direct load via fetchProjectByDTag, falls back to snapshot matching, then community relay matching, fetches author pictures for the resolved author, and prevents post-unmount state updates.
Page Rendering with Suspense Boundary
app/projects/[pubkey]/[id]/page.tsx
Adds Suspense import and introduces ProjectFallback loading-skeleton component. Converts ProjectPage from async/await of params to a non-async render that wraps content in Suspense and resolves params via params.then(...), enabling incremental rendering with a fallback UI instead of blocking on async input.

Sequence Diagram

sequenceDiagram
participant Browser
participant ProjectPage
participant Suspense as Suspense Boundary
participant StandaloneProjectPage
participant Loader as Async Loader
participant Direct as fetchProjectByDTag
participant Snapshot as fetchCommunityProjectsSnapshot
participant Community as fetchCommunityProjects
participant AuthorAPI as fetchAuthorPictures
Browser->>ProjectPage: Request /{pubkey}/{id}
ProjectPage->>Suspense: Render with params.then(...)
Suspense->>Browser: Show ProjectFallback skeleton
ProjectPage->>StandaloneProjectPage: params resolve
StandaloneProjectPage->>Loader: useEffect triggered
Loader->>Direct: Try direct fetch
alt Project found
Direct->>Loader: Return project
else Project not found
Direct->>Loader: null/error
Loader->>Snapshot: Query snapshot
alt Match in snapshot
Snapshot->>Loader: Return project
else No match
Loader->>Community: Query relay (timeout)
Community->>Loader: Search results
Loader->>Loader: Match via projectMatchesIdentifier
end
end
Loader->>AuthorAPI: Fetch author pictures
AuthorAPI->>Loader: Author data
Loader->>StandaloneProjectPage: setProject(data)
StandaloneProjectPage->>Browser: Render project detail
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly Related PRs

  • lacrypta/lacrypta-dev#7: Both PRs add <Suspense> boundaries to page components (page.tsx routes) with fallback UI, replacing direct await of async inputs with params.then(...) rendering patterns.
  • lacrypta/lacrypta-dev#8: Both PRs implement fallback project lookups via fetchCommunityProjectsSnapshot with abortable async fetching and Suspense/params.then(...) page rendering in project detail pages.

Poem

🐰 The rabbit hops through nested queries deep,
From direct fetch to snapshot's fuzzy keep,
Then leaps to relays far and wide—
While Suspense shows a skeleton with pride!
Three chances to find the project's tale,
And graceful cancellation won't fail. ✨

✨ 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 codex/fix-standalone-project-route

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.

@agustinkassis
agustinkassis marked this pull request as ready for review June 3, 2026 21:23
@agustinkassis
agustinkassis merged commit 6c0b707 into mainJun 3, 2026
3 checks passed
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

[codex] Fix standalone Nostr project routes - #22

Merged
agustinkassis merged 1 commit into
mainfrom
codex/fix-standalone-project-route
Jun 3, 2026
Merged

[codex] Fix standalone Nostr project routes#22
agustinkassis merged 1 commit into
mainfrom
codex/fix-standalone-project-route

Conversation

@agustinkassis

@agustinkassisagustinkassis commented Jun 3, 2026

Copy link
Copy Markdown
Member

Summary

  • Resolve /projects/[pubkey]/[id] params inside a Suspense boundary so Cache Components does not prerender placeholder [pubkey] / [id] values into the client payload.
  • Add snapshot and broad relay fallback for standalone project pages, using the same flexible project identity matching as hackathon project detail pages.
  • Preserve direct relay lookup first, then recover from /api/nostr-projects or relay scans before showing Proyecto no encontrado.

Root Cause

The production HTML for standalone project routes was hydrating StandaloneProjectPage with encoded placeholder params (%5Bpubkey%5D and %5Bid%5D) instead of the real URL segments. The client then queried Nostr using those placeholders, so existing projects looked missing. The standalone route also only tried an exact authors + #d relay query, without the snapshot fallback used elsewhere.

Validation

  • pnpm exec tsc --noEmit
  • pnpm build
  • Confirmed local HTML now serializes the real pubkey and projectId for the reported URL.
  • Confirmed /api/nostr-projects contains the reported project (Arcade timba simulator).
  • Verified in the in-app browser that the reported URL loads Arcade timba simulator and does not show Proyecto no encontrado.

Summary by CodeRabbit

  • Bug Fixes
    • Improved project discovery with enhanced fallback mechanisms that attempt multiple lookup strategies across different data sources for better reliability.
    • Refined user experience during page initialization with animated loading indicator displayed while page content is being prepared.

@vercel

vercelBot commented Jun 3, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
lacrypta-devReadyReadyPreview, CommentJun 3, 2026 9:18pm

Request Review

@coderabbitai

coderabbitaiBot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9f85e6c8-d6c1-429d-9774-52763aa09135

📥 Commits

Reviewing files that changed from the base of the PR and between d410dff and 66edb6d.

📒 Files selected for processing (2)
  • app/projects/[pubkey]/[id]/StandaloneProjectPage.tsx
  • app/projects/[pubkey]/[id]/page.tsx

📝 Walkthrough

Walkthrough

The pull request enhances the project detail page with a resilient data-loading strategy and improves perceived performance through early rendering. StandaloneProjectPage now implements a multi-tier fallback mechanism that attempts to load a project directly, then searches a snapshot, and finally queries a broader community relay if needed. Route parameter resolution is decoupled from rendering via Suspense, allowing a loading skeleton to display while parameters and project data are fetched asynchronously.

Changes

Project Detail Page Loading Architecture

Layer / File(s)Summary
Multi-tier Project Lookup with Fallbacks
app/projects/[pubkey]/[id]/StandaloneProjectPage.tsx
Extends imports to include fetchCommunityProjects, fetchCommunityProjectsSnapshot, and projectMatchesIdentifier. The useEffect loader is rewritten with AbortController cancellation: it attempts direct load via fetchProjectByDTag, falls back to snapshot matching, then community relay matching, fetches author pictures for the resolved author, and prevents post-unmount state updates.
Page Rendering with Suspense Boundary
app/projects/[pubkey]/[id]/page.tsx
Adds Suspense import and introduces ProjectFallback loading-skeleton component. Converts ProjectPage from async/await of params to a non-async render that wraps content in Suspense and resolves params via params.then(...), enabling incremental rendering with a fallback UI instead of blocking on async input.

Sequence Diagram

sequenceDiagram
participant Browser
participant ProjectPage
participant Suspense as Suspense Boundary
participant StandaloneProjectPage
participant Loader as Async Loader
participant Direct as fetchProjectByDTag
participant Snapshot as fetchCommunityProjectsSnapshot
participant Community as fetchCommunityProjects
participant AuthorAPI as fetchAuthorPictures
Browser->>ProjectPage: Request /{pubkey}/{id}
ProjectPage->>Suspense: Render with params.then(...)
Suspense->>Browser: Show ProjectFallback skeleton
ProjectPage->>StandaloneProjectPage: params resolve
StandaloneProjectPage->>Loader: useEffect triggered
Loader->>Direct: Try direct fetch
alt Project found
Direct->>Loader: Return project
else Project not found
Direct->>Loader: null/error
Loader->>Snapshot: Query snapshot
alt Match in snapshot
Snapshot->>Loader: Return project
else No match
Loader->>Community: Query relay (timeout)
Community->>Loader: Search results
Loader->>Loader: Match via projectMatchesIdentifier
end
end
Loader->>AuthorAPI: Fetch author pictures
AuthorAPI->>Loader: Author data
Loader->>StandaloneProjectPage: setProject(data)
StandaloneProjectPage->>Browser: Render project detail
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly Related PRs

  • lacrypta/lacrypta-dev#7: Both PRs add <Suspense> boundaries to page components (page.tsx routes) with fallback UI, replacing direct await of async inputs with params.then(...) rendering patterns.
  • lacrypta/lacrypta-dev#8: Both PRs implement fallback project lookups via fetchCommunityProjectsSnapshot with abortable async fetching and Suspense/params.then(...) page rendering in project detail pages.

Poem

🐰 The rabbit hops through nested queries deep,
From direct fetch to snapshot's fuzzy keep,
Then leaps to relays far and wide—
While Suspense shows a skeleton with pride!
Three chances to find the project's tale,
And graceful cancellation won't fail. ✨

✨ 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 codex/fix-standalone-project-route

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.

@agustinkassis
agustinkassis marked this pull request as ready for review June 3, 2026 21:23
@agustinkassis
agustinkassis merged commit 6c0b707 into mainJun 3, 2026
3 checks passed
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

[codex] Fix standalone Nostr project routes - #22

Merged
agustinkassis merged 1 commit into
mainfrom
codex/fix-standalone-project-route
Jun 3, 2026
Merged

[codex] Fix standalone Nostr project routes#22
agustinkassis merged 1 commit into
mainfrom
codex/fix-standalone-project-route

Conversation

@agustinkassis

@agustinkassisagustinkassis commented Jun 3, 2026

Copy link
Copy Markdown
Member

Summary

  • Resolve /projects/[pubkey]/[id] params inside a Suspense boundary so Cache Components does not prerender placeholder [pubkey] / [id] values into the client payload.
  • Add snapshot and broad relay fallback for standalone project pages, using the same flexible project identity matching as hackathon project detail pages.
  • Preserve direct relay lookup first, then recover from /api/nostr-projects or relay scans before showing Proyecto no encontrado.

Root Cause

The production HTML for standalone project routes was hydrating StandaloneProjectPage with encoded placeholder params (%5Bpubkey%5D and %5Bid%5D) instead of the real URL segments. The client then queried Nostr using those placeholders, so existing projects looked missing. The standalone route also only tried an exact authors + #d relay query, without the snapshot fallback used elsewhere.

Validation

  • pnpm exec tsc --noEmit
  • pnpm build
  • Confirmed local HTML now serializes the real pubkey and projectId for the reported URL.
  • Confirmed /api/nostr-projects contains the reported project (Arcade timba simulator).
  • Verified in the in-app browser that the reported URL loads Arcade timba simulator and does not show Proyecto no encontrado.

Summary by CodeRabbit

  • Bug Fixes
    • Improved project discovery with enhanced fallback mechanisms that attempt multiple lookup strategies across different data sources for better reliability.
    • Refined user experience during page initialization with animated loading indicator displayed while page content is being prepared.

@vercel

vercelBot commented Jun 3, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
lacrypta-devReadyReadyPreview, CommentJun 3, 2026 9:18pm

Request Review

@coderabbitai

coderabbitaiBot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9f85e6c8-d6c1-429d-9774-52763aa09135

📥 Commits

Reviewing files that changed from the base of the PR and between d410dff and 66edb6d.

📒 Files selected for processing (2)
  • app/projects/[pubkey]/[id]/StandaloneProjectPage.tsx
  • app/projects/[pubkey]/[id]/page.tsx

📝 Walkthrough

Walkthrough

The pull request enhances the project detail page with a resilient data-loading strategy and improves perceived performance through early rendering. StandaloneProjectPage now implements a multi-tier fallback mechanism that attempts to load a project directly, then searches a snapshot, and finally queries a broader community relay if needed. Route parameter resolution is decoupled from rendering via Suspense, allowing a loading skeleton to display while parameters and project data are fetched asynchronously.

Changes

Project Detail Page Loading Architecture

Layer / File(s)Summary
Multi-tier Project Lookup with Fallbacks
app/projects/[pubkey]/[id]/StandaloneProjectPage.tsx
Extends imports to include fetchCommunityProjects, fetchCommunityProjectsSnapshot, and projectMatchesIdentifier. The useEffect loader is rewritten with AbortController cancellation: it attempts direct load via fetchProjectByDTag, falls back to snapshot matching, then community relay matching, fetches author pictures for the resolved author, and prevents post-unmount state updates.
Page Rendering with Suspense Boundary
app/projects/[pubkey]/[id]/page.tsx
Adds Suspense import and introduces ProjectFallback loading-skeleton component. Converts ProjectPage from async/await of params to a non-async render that wraps content in Suspense and resolves params via params.then(...), enabling incremental rendering with a fallback UI instead of blocking on async input.

Sequence Diagram

sequenceDiagram
participant Browser
participant ProjectPage
participant Suspense as Suspense Boundary
participant StandaloneProjectPage
participant Loader as Async Loader
participant Direct as fetchProjectByDTag
participant Snapshot as fetchCommunityProjectsSnapshot
participant Community as fetchCommunityProjects
participant AuthorAPI as fetchAuthorPictures
Browser->>ProjectPage: Request /{pubkey}/{id}
ProjectPage->>Suspense: Render with params.then(...)
Suspense->>Browser: Show ProjectFallback skeleton
ProjectPage->>StandaloneProjectPage: params resolve
StandaloneProjectPage->>Loader: useEffect triggered
Loader->>Direct: Try direct fetch
alt Project found
Direct->>Loader: Return project
else Project not found
Direct->>Loader: null/error
Loader->>Snapshot: Query snapshot
alt Match in snapshot
Snapshot->>Loader: Return project
else No match
Loader->>Community: Query relay (timeout)
Community->>Loader: Search results
Loader->>Loader: Match via projectMatchesIdentifier
end
end
Loader->>AuthorAPI: Fetch author pictures
AuthorAPI->>Loader: Author data
Loader->>StandaloneProjectPage: setProject(data)
StandaloneProjectPage->>Browser: Render project detail
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly Related PRs

  • lacrypta/lacrypta-dev#7: Both PRs add <Suspense> boundaries to page components (page.tsx routes) with fallback UI, replacing direct await of async inputs with params.then(...) rendering patterns.
  • lacrypta/lacrypta-dev#8: Both PRs implement fallback project lookups via fetchCommunityProjectsSnapshot with abortable async fetching and Suspense/params.then(...) page rendering in project detail pages.

Poem

🐰 The rabbit hops through nested queries deep,
From direct fetch to snapshot's fuzzy keep,
Then leaps to relays far and wide—
While Suspense shows a skeleton with pride!
Three chances to find the project's tale,
And graceful cancellation won't fail. ✨

✨ 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 codex/fix-standalone-project-route

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.

@agustinkassis
agustinkassis marked this pull request as ready for review June 3, 2026 21:23
@agustinkassis
agustinkassis merged commit 6c0b707 into mainJun 3, 2026
3 checks passed
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

[codex] Fix standalone Nostr project routes - #22

Merged
agustinkassis merged 1 commit into
mainfrom
codex/fix-standalone-project-route
Jun 3, 2026
Merged

[codex] Fix standalone Nostr project routes#22
agustinkassis merged 1 commit into
mainfrom
codex/fix-standalone-project-route

Conversation

@agustinkassis

@agustinkassisagustinkassis commented Jun 3, 2026

Copy link
Copy Markdown
Member

Summary

  • Resolve /projects/[pubkey]/[id] params inside a Suspense boundary so Cache Components does not prerender placeholder [pubkey] / [id] values into the client payload.
  • Add snapshot and broad relay fallback for standalone project pages, using the same flexible project identity matching as hackathon project detail pages.
  • Preserve direct relay lookup first, then recover from /api/nostr-projects or relay scans before showing Proyecto no encontrado.

Root Cause

The production HTML for standalone project routes was hydrating StandaloneProjectPage with encoded placeholder params (%5Bpubkey%5D and %5Bid%5D) instead of the real URL segments. The client then queried Nostr using those placeholders, so existing projects looked missing. The standalone route also only tried an exact authors + #d relay query, without the snapshot fallback used elsewhere.

Validation

  • pnpm exec tsc --noEmit
  • pnpm build
  • Confirmed local HTML now serializes the real pubkey and projectId for the reported URL.
  • Confirmed /api/nostr-projects contains the reported project (Arcade timba simulator).
  • Verified in the in-app browser that the reported URL loads Arcade timba simulator and does not show Proyecto no encontrado.

Summary by CodeRabbit

  • Bug Fixes
    • Improved project discovery with enhanced fallback mechanisms that attempt multiple lookup strategies across different data sources for better reliability.
    • Refined user experience during page initialization with animated loading indicator displayed while page content is being prepared.

@vercel

vercelBot commented Jun 3, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
lacrypta-devReadyReadyPreview, CommentJun 3, 2026 9:18pm

Request Review

@coderabbitai

coderabbitaiBot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9f85e6c8-d6c1-429d-9774-52763aa09135

📥 Commits

Reviewing files that changed from the base of the PR and between d410dff and 66edb6d.

📒 Files selected for processing (2)
  • app/projects/[pubkey]/[id]/StandaloneProjectPage.tsx
  • app/projects/[pubkey]/[id]/page.tsx

📝 Walkthrough

Walkthrough

The pull request enhances the project detail page with a resilient data-loading strategy and improves perceived performance through early rendering. StandaloneProjectPage now implements a multi-tier fallback mechanism that attempts to load a project directly, then searches a snapshot, and finally queries a broader community relay if needed. Route parameter resolution is decoupled from rendering via Suspense, allowing a loading skeleton to display while parameters and project data are fetched asynchronously.

Changes

Project Detail Page Loading Architecture

Layer / File(s)Summary
Multi-tier Project Lookup with Fallbacks
app/projects/[pubkey]/[id]/StandaloneProjectPage.tsx
Extends imports to include fetchCommunityProjects, fetchCommunityProjectsSnapshot, and projectMatchesIdentifier. The useEffect loader is rewritten with AbortController cancellation: it attempts direct load via fetchProjectByDTag, falls back to snapshot matching, then community relay matching, fetches author pictures for the resolved author, and prevents post-unmount state updates.
Page Rendering with Suspense Boundary
app/projects/[pubkey]/[id]/page.tsx
Adds Suspense import and introduces ProjectFallback loading-skeleton component. Converts ProjectPage from async/await of params to a non-async render that wraps content in Suspense and resolves params via params.then(...), enabling incremental rendering with a fallback UI instead of blocking on async input.

Sequence Diagram

sequenceDiagram
participant Browser
participant ProjectPage
participant Suspense as Suspense Boundary
participant StandaloneProjectPage
participant Loader as Async Loader
participant Direct as fetchProjectByDTag
participant Snapshot as fetchCommunityProjectsSnapshot
participant Community as fetchCommunityProjects
participant AuthorAPI as fetchAuthorPictures
Browser->>ProjectPage: Request /{pubkey}/{id}
ProjectPage->>Suspense: Render with params.then(...)
Suspense->>Browser: Show ProjectFallback skeleton
ProjectPage->>StandaloneProjectPage: params resolve
StandaloneProjectPage->>Loader: useEffect triggered
Loader->>Direct: Try direct fetch
alt Project found
Direct->>Loader: Return project
else Project not found
Direct->>Loader: null/error
Loader->>Snapshot: Query snapshot
alt Match in snapshot
Snapshot->>Loader: Return project
else No match
Loader->>Community: Query relay (timeout)
Community->>Loader: Search results
Loader->>Loader: Match via projectMatchesIdentifier
end
end
Loader->>AuthorAPI: Fetch author pictures
AuthorAPI->>Loader: Author data
Loader->>StandaloneProjectPage: setProject(data)
StandaloneProjectPage->>Browser: Render project detail
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly Related PRs

  • lacrypta/lacrypta-dev#7: Both PRs add <Suspense> boundaries to page components (page.tsx routes) with fallback UI, replacing direct await of async inputs with params.then(...) rendering patterns.
  • lacrypta/lacrypta-dev#8: Both PRs implement fallback project lookups via fetchCommunityProjectsSnapshot with abortable async fetching and Suspense/params.then(...) page rendering in project detail pages.

Poem

🐰 The rabbit hops through nested queries deep,
From direct fetch to snapshot's fuzzy keep,
Then leaps to relays far and wide—
While Suspense shows a skeleton with pride!
Three chances to find the project's tale,
And graceful cancellation won't fail. ✨

✨ 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 codex/fix-standalone-project-route

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.

@agustinkassis
agustinkassis marked this pull request as ready for review June 3, 2026 21:23
@agustinkassis
agustinkassis merged commit 6c0b707 into mainJun 3, 2026
3 checks passed
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

[codex] Fix standalone Nostr project routes - #22

Merged
agustinkassis merged 1 commit into
mainfrom
codex/fix-standalone-project-route
Jun 3, 2026
Merged

[codex] Fix standalone Nostr project routes#22
agustinkassis merged 1 commit into
mainfrom
codex/fix-standalone-project-route

Conversation

@agustinkassis

@agustinkassisagustinkassis commented Jun 3, 2026

Copy link
Copy Markdown
Member

Summary

  • Resolve /projects/[pubkey]/[id] params inside a Suspense boundary so Cache Components does not prerender placeholder [pubkey] / [id] values into the client payload.
  • Add snapshot and broad relay fallback for standalone project pages, using the same flexible project identity matching as hackathon project detail pages.
  • Preserve direct relay lookup first, then recover from /api/nostr-projects or relay scans before showing Proyecto no encontrado.

Root Cause

The production HTML for standalone project routes was hydrating StandaloneProjectPage with encoded placeholder params (%5Bpubkey%5D and %5Bid%5D) instead of the real URL segments. The client then queried Nostr using those placeholders, so existing projects looked missing. The standalone route also only tried an exact authors + #d relay query, without the snapshot fallback used elsewhere.

Validation

  • pnpm exec tsc --noEmit
  • pnpm build
  • Confirmed local HTML now serializes the real pubkey and projectId for the reported URL.
  • Confirmed /api/nostr-projects contains the reported project (Arcade timba simulator).
  • Verified in the in-app browser that the reported URL loads Arcade timba simulator and does not show Proyecto no encontrado.

Summary by CodeRabbit

  • Bug Fixes
    • Improved project discovery with enhanced fallback mechanisms that attempt multiple lookup strategies across different data sources for better reliability.
    • Refined user experience during page initialization with animated loading indicator displayed while page content is being prepared.

@vercel

vercelBot commented Jun 3, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
lacrypta-devReadyReadyPreview, CommentJun 3, 2026 9:18pm

Request Review

@coderabbitai

coderabbitaiBot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9f85e6c8-d6c1-429d-9774-52763aa09135

📥 Commits

Reviewing files that changed from the base of the PR and between d410dff and 66edb6d.

📒 Files selected for processing (2)
  • app/projects/[pubkey]/[id]/StandaloneProjectPage.tsx
  • app/projects/[pubkey]/[id]/page.tsx

📝 Walkthrough

Walkthrough

The pull request enhances the project detail page with a resilient data-loading strategy and improves perceived performance through early rendering. StandaloneProjectPage now implements a multi-tier fallback mechanism that attempts to load a project directly, then searches a snapshot, and finally queries a broader community relay if needed. Route parameter resolution is decoupled from rendering via Suspense, allowing a loading skeleton to display while parameters and project data are fetched asynchronously.

Changes

Project Detail Page Loading Architecture

Layer / File(s)Summary
Multi-tier Project Lookup with Fallbacks
app/projects/[pubkey]/[id]/StandaloneProjectPage.tsx
Extends imports to include fetchCommunityProjects, fetchCommunityProjectsSnapshot, and projectMatchesIdentifier. The useEffect loader is rewritten with AbortController cancellation: it attempts direct load via fetchProjectByDTag, falls back to snapshot matching, then community relay matching, fetches author pictures for the resolved author, and prevents post-unmount state updates.
Page Rendering with Suspense Boundary
app/projects/[pubkey]/[id]/page.tsx
Adds Suspense import and introduces ProjectFallback loading-skeleton component. Converts ProjectPage from async/await of params to a non-async render that wraps content in Suspense and resolves params via params.then(...), enabling incremental rendering with a fallback UI instead of blocking on async input.

Sequence Diagram

sequenceDiagram
participant Browser
participant ProjectPage
participant Suspense as Suspense Boundary
participant StandaloneProjectPage
participant Loader as Async Loader
participant Direct as fetchProjectByDTag
participant Snapshot as fetchCommunityProjectsSnapshot
participant Community as fetchCommunityProjects
participant AuthorAPI as fetchAuthorPictures
Browser->>ProjectPage: Request /{pubkey}/{id}
ProjectPage->>Suspense: Render with params.then(...)
Suspense->>Browser: Show ProjectFallback skeleton
ProjectPage->>StandaloneProjectPage: params resolve
StandaloneProjectPage->>Loader: useEffect triggered
Loader->>Direct: Try direct fetch
alt Project found
Direct->>Loader: Return project
else Project not found
Direct->>Loader: null/error
Loader->>Snapshot: Query snapshot
alt Match in snapshot
Snapshot->>Loader: Return project
else No match
Loader->>Community: Query relay (timeout)
Community->>Loader: Search results
Loader->>Loader: Match via projectMatchesIdentifier
end
end
Loader->>AuthorAPI: Fetch author pictures
AuthorAPI->>Loader: Author data
Loader->>StandaloneProjectPage: setProject(data)
StandaloneProjectPage->>Browser: Render project detail
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly Related PRs

  • lacrypta/lacrypta-dev#7: Both PRs add <Suspense> boundaries to page components (page.tsx routes) with fallback UI, replacing direct await of async inputs with params.then(...) rendering patterns.
  • lacrypta/lacrypta-dev#8: Both PRs implement fallback project lookups via fetchCommunityProjectsSnapshot with abortable async fetching and Suspense/params.then(...) page rendering in project detail pages.

Poem

🐰 The rabbit hops through nested queries deep,
From direct fetch to snapshot's fuzzy keep,
Then leaps to relays far and wide—
While Suspense shows a skeleton with pride!
Three chances to find the project's tale,
And graceful cancellation won't fail. ✨

✨ 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 codex/fix-standalone-project-route

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.

@agustinkassis
agustinkassis marked this pull request as ready for review June 3, 2026 21:23
@agustinkassis
agustinkassis merged commit 6c0b707 into mainJun 3, 2026
3 checks passed
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

[codex] Fix standalone Nostr project routes - #22

Merged
agustinkassis merged 1 commit into
mainfrom
codex/fix-standalone-project-route
Jun 3, 2026
Merged

[codex] Fix standalone Nostr project routes#22
agustinkassis merged 1 commit into
mainfrom
codex/fix-standalone-project-route

Conversation

@agustinkassis

@agustinkassisagustinkassis commented Jun 3, 2026

Copy link
Copy Markdown
Member

Summary

  • Resolve /projects/[pubkey]/[id] params inside a Suspense boundary so Cache Components does not prerender placeholder [pubkey] / [id] values into the client payload.
  • Add snapshot and broad relay fallback for standalone project pages, using the same flexible project identity matching as hackathon project detail pages.
  • Preserve direct relay lookup first, then recover from /api/nostr-projects or relay scans before showing Proyecto no encontrado.

Root Cause

The production HTML for standalone project routes was hydrating StandaloneProjectPage with encoded placeholder params (%5Bpubkey%5D and %5Bid%5D) instead of the real URL segments. The client then queried Nostr using those placeholders, so existing projects looked missing. The standalone route also only tried an exact authors + #d relay query, without the snapshot fallback used elsewhere.

Validation

  • pnpm exec tsc --noEmit
  • pnpm build
  • Confirmed local HTML now serializes the real pubkey and projectId for the reported URL.
  • Confirmed /api/nostr-projects contains the reported project (Arcade timba simulator).
  • Verified in the in-app browser that the reported URL loads Arcade timba simulator and does not show Proyecto no encontrado.

Summary by CodeRabbit

  • Bug Fixes
    • Improved project discovery with enhanced fallback mechanisms that attempt multiple lookup strategies across different data sources for better reliability.
    • Refined user experience during page initialization with animated loading indicator displayed while page content is being prepared.

@vercel

vercelBot commented Jun 3, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
lacrypta-devReadyReadyPreview, CommentJun 3, 2026 9:18pm

Request Review

@coderabbitai

coderabbitaiBot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9f85e6c8-d6c1-429d-9774-52763aa09135

📥 Commits

Reviewing files that changed from the base of the PR and between d410dff and 66edb6d.

📒 Files selected for processing (2)
  • app/projects/[pubkey]/[id]/StandaloneProjectPage.tsx
  • app/projects/[pubkey]/[id]/page.tsx

📝 Walkthrough

Walkthrough

The pull request enhances the project detail page with a resilient data-loading strategy and improves perceived performance through early rendering. StandaloneProjectPage now implements a multi-tier fallback mechanism that attempts to load a project directly, then searches a snapshot, and finally queries a broader community relay if needed. Route parameter resolution is decoupled from rendering via Suspense, allowing a loading skeleton to display while parameters and project data are fetched asynchronously.

Changes

Project Detail Page Loading Architecture

Layer / File(s)Summary
Multi-tier Project Lookup with Fallbacks
app/projects/[pubkey]/[id]/StandaloneProjectPage.tsx
Extends imports to include fetchCommunityProjects, fetchCommunityProjectsSnapshot, and projectMatchesIdentifier. The useEffect loader is rewritten with AbortController cancellation: it attempts direct load via fetchProjectByDTag, falls back to snapshot matching, then community relay matching, fetches author pictures for the resolved author, and prevents post-unmount state updates.
Page Rendering with Suspense Boundary
app/projects/[pubkey]/[id]/page.tsx
Adds Suspense import and introduces ProjectFallback loading-skeleton component. Converts ProjectPage from async/await of params to a non-async render that wraps content in Suspense and resolves params via params.then(...), enabling incremental rendering with a fallback UI instead of blocking on async input.

Sequence Diagram

sequenceDiagram
participant Browser
participant ProjectPage
participant Suspense as Suspense Boundary
participant StandaloneProjectPage
participant Loader as Async Loader
participant Direct as fetchProjectByDTag
participant Snapshot as fetchCommunityProjectsSnapshot
participant Community as fetchCommunityProjects
participant AuthorAPI as fetchAuthorPictures
Browser->>ProjectPage: Request /{pubkey}/{id}
ProjectPage->>Suspense: Render with params.then(...)
Suspense->>Browser: Show ProjectFallback skeleton
ProjectPage->>StandaloneProjectPage: params resolve
StandaloneProjectPage->>Loader: useEffect triggered
Loader->>Direct: Try direct fetch
alt Project found
Direct->>Loader: Return project
else Project not found
Direct->>Loader: null/error
Loader->>Snapshot: Query snapshot
alt Match in snapshot
Snapshot->>Loader: Return project
else No match
Loader->>Community: Query relay (timeout)
Community->>Loader: Search results
Loader->>Loader: Match via projectMatchesIdentifier
end
end
Loader->>AuthorAPI: Fetch author pictures
AuthorAPI->>Loader: Author data
Loader->>StandaloneProjectPage: setProject(data)
StandaloneProjectPage->>Browser: Render project detail
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly Related PRs

  • lacrypta/lacrypta-dev#7: Both PRs add <Suspense> boundaries to page components (page.tsx routes) with fallback UI, replacing direct await of async inputs with params.then(...) rendering patterns.
  • lacrypta/lacrypta-dev#8: Both PRs implement fallback project lookups via fetchCommunityProjectsSnapshot with abortable async fetching and Suspense/params.then(...) page rendering in project detail pages.

Poem

🐰 The rabbit hops through nested queries deep,
From direct fetch to snapshot's fuzzy keep,
Then leaps to relays far and wide—
While Suspense shows a skeleton with pride!
Three chances to find the project's tale,
And graceful cancellation won't fail. ✨

✨ 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 codex/fix-standalone-project-route

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.

@agustinkassis
agustinkassis marked this pull request as ready for review June 3, 2026 21:23
@agustinkassis
agustinkassis merged commit 6c0b707 into mainJun 3, 2026
3 checks passed
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

[codex] Fix standalone Nostr project routes - #22

Merged
agustinkassis merged 1 commit into
mainfrom
codex/fix-standalone-project-route
Jun 3, 2026
Merged

[codex] Fix standalone Nostr project routes#22
agustinkassis merged 1 commit into
mainfrom
codex/fix-standalone-project-route

Conversation

@agustinkassis

@agustinkassisagustinkassis commented Jun 3, 2026

Copy link
Copy Markdown
Member

Summary

  • Resolve /projects/[pubkey]/[id] params inside a Suspense boundary so Cache Components does not prerender placeholder [pubkey] / [id] values into the client payload.
  • Add snapshot and broad relay fallback for standalone project pages, using the same flexible project identity matching as hackathon project detail pages.
  • Preserve direct relay lookup first, then recover from /api/nostr-projects or relay scans before showing Proyecto no encontrado.

Root Cause

The production HTML for standalone project routes was hydrating StandaloneProjectPage with encoded placeholder params (%5Bpubkey%5D and %5Bid%5D) instead of the real URL segments. The client then queried Nostr using those placeholders, so existing projects looked missing. The standalone route also only tried an exact authors + #d relay query, without the snapshot fallback used elsewhere.

Validation

  • pnpm exec tsc --noEmit
  • pnpm build
  • Confirmed local HTML now serializes the real pubkey and projectId for the reported URL.
  • Confirmed /api/nostr-projects contains the reported project (Arcade timba simulator).
  • Verified in the in-app browser that the reported URL loads Arcade timba simulator and does not show Proyecto no encontrado.

Summary by CodeRabbit

  • Bug Fixes
    • Improved project discovery with enhanced fallback mechanisms that attempt multiple lookup strategies across different data sources for better reliability.
    • Refined user experience during page initialization with animated loading indicator displayed while page content is being prepared.

@vercel

vercelBot commented Jun 3, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
lacrypta-devReadyReadyPreview, CommentJun 3, 2026 9:18pm

Request Review

@coderabbitai

coderabbitaiBot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9f85e6c8-d6c1-429d-9774-52763aa09135

📥 Commits

Reviewing files that changed from the base of the PR and between d410dff and 66edb6d.

📒 Files selected for processing (2)
  • app/projects/[pubkey]/[id]/StandaloneProjectPage.tsx
  • app/projects/[pubkey]/[id]/page.tsx

📝 Walkthrough

Walkthrough

The pull request enhances the project detail page with a resilient data-loading strategy and improves perceived performance through early rendering. StandaloneProjectPage now implements a multi-tier fallback mechanism that attempts to load a project directly, then searches a snapshot, and finally queries a broader community relay if needed. Route parameter resolution is decoupled from rendering via Suspense, allowing a loading skeleton to display while parameters and project data are fetched asynchronously.

Changes

Project Detail Page Loading Architecture

Layer / File(s)Summary
Multi-tier Project Lookup with Fallbacks
app/projects/[pubkey]/[id]/StandaloneProjectPage.tsx
Extends imports to include fetchCommunityProjects, fetchCommunityProjectsSnapshot, and projectMatchesIdentifier. The useEffect loader is rewritten with AbortController cancellation: it attempts direct load via fetchProjectByDTag, falls back to snapshot matching, then community relay matching, fetches author pictures for the resolved author, and prevents post-unmount state updates.
Page Rendering with Suspense Boundary
app/projects/[pubkey]/[id]/page.tsx
Adds Suspense import and introduces ProjectFallback loading-skeleton component. Converts ProjectPage from async/await of params to a non-async render that wraps content in Suspense and resolves params via params.then(...), enabling incremental rendering with a fallback UI instead of blocking on async input.

Sequence Diagram

sequenceDiagram
participant Browser
participant ProjectPage
participant Suspense as Suspense Boundary
participant StandaloneProjectPage
participant Loader as Async Loader
participant Direct as fetchProjectByDTag
participant Snapshot as fetchCommunityProjectsSnapshot
participant Community as fetchCommunityProjects
participant AuthorAPI as fetchAuthorPictures
Browser->>ProjectPage: Request /{pubkey}/{id}
ProjectPage->>Suspense: Render with params.then(...)
Suspense->>Browser: Show ProjectFallback skeleton
ProjectPage->>StandaloneProjectPage: params resolve
StandaloneProjectPage->>Loader: useEffect triggered
Loader->>Direct: Try direct fetch
alt Project found
Direct->>Loader: Return project
else Project not found
Direct->>Loader: null/error
Loader->>Snapshot: Query snapshot
alt Match in snapshot
Snapshot->>Loader: Return project
else No match
Loader->>Community: Query relay (timeout)
Community->>Loader: Search results
Loader->>Loader: Match via projectMatchesIdentifier
end
end
Loader->>AuthorAPI: Fetch author pictures
AuthorAPI->>Loader: Author data
Loader->>StandaloneProjectPage: setProject(data)
StandaloneProjectPage->>Browser: Render project detail
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly Related PRs

  • lacrypta/lacrypta-dev#7: Both PRs add <Suspense> boundaries to page components (page.tsx routes) with fallback UI, replacing direct await of async inputs with params.then(...) rendering patterns.
  • lacrypta/lacrypta-dev#8: Both PRs implement fallback project lookups via fetchCommunityProjectsSnapshot with abortable async fetching and Suspense/params.then(...) page rendering in project detail pages.

Poem

🐰 The rabbit hops through nested queries deep,
From direct fetch to snapshot's fuzzy keep,
Then leaps to relays far and wide—
While Suspense shows a skeleton with pride!
Three chances to find the project's tale,
And graceful cancellation won't fail. ✨

✨ 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 codex/fix-standalone-project-route

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.

@agustinkassis
agustinkassis marked this pull request as ready for review June 3, 2026 21:23
@agustinkassis
agustinkassis merged commit 6c0b707 into mainJun 3, 2026
3 checks passed
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

[codex] Fix standalone Nostr project routes - #22

Merged
agustinkassis merged 1 commit into
mainfrom
codex/fix-standalone-project-route
Jun 3, 2026
Merged

[codex] Fix standalone Nostr project routes#22
agustinkassis merged 1 commit into
mainfrom
codex/fix-standalone-project-route

Conversation

@agustinkassis

@agustinkassisagustinkassis commented Jun 3, 2026

Copy link
Copy Markdown
Member

Summary

  • Resolve /projects/[pubkey]/[id] params inside a Suspense boundary so Cache Components does not prerender placeholder [pubkey] / [id] values into the client payload.
  • Add snapshot and broad relay fallback for standalone project pages, using the same flexible project identity matching as hackathon project detail pages.
  • Preserve direct relay lookup first, then recover from /api/nostr-projects or relay scans before showing Proyecto no encontrado.

Root Cause

The production HTML for standalone project routes was hydrating StandaloneProjectPage with encoded placeholder params (%5Bpubkey%5D and %5Bid%5D) instead of the real URL segments. The client then queried Nostr using those placeholders, so existing projects looked missing. The standalone route also only tried an exact authors + #d relay query, without the snapshot fallback used elsewhere.

Validation

  • pnpm exec tsc --noEmit
  • pnpm build
  • Confirmed local HTML now serializes the real pubkey and projectId for the reported URL.
  • Confirmed /api/nostr-projects contains the reported project (Arcade timba simulator).
  • Verified in the in-app browser that the reported URL loads Arcade timba simulator and does not show Proyecto no encontrado.

Summary by CodeRabbit

  • Bug Fixes
    • Improved project discovery with enhanced fallback mechanisms that attempt multiple lookup strategies across different data sources for better reliability.
    • Refined user experience during page initialization with animated loading indicator displayed while page content is being prepared.

@vercel

vercelBot commented Jun 3, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
lacrypta-devReadyReadyPreview, CommentJun 3, 2026 9:18pm

Request Review

@coderabbitai

coderabbitaiBot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9f85e6c8-d6c1-429d-9774-52763aa09135

📥 Commits

Reviewing files that changed from the base of the PR and between d410dff and 66edb6d.

📒 Files selected for processing (2)
  • app/projects/[pubkey]/[id]/StandaloneProjectPage.tsx
  • app/projects/[pubkey]/[id]/page.tsx

📝 Walkthrough

Walkthrough

The pull request enhances the project detail page with a resilient data-loading strategy and improves perceived performance through early rendering. StandaloneProjectPage now implements a multi-tier fallback mechanism that attempts to load a project directly, then searches a snapshot, and finally queries a broader community relay if needed. Route parameter resolution is decoupled from rendering via Suspense, allowing a loading skeleton to display while parameters and project data are fetched asynchronously.

Changes

Project Detail Page Loading Architecture

Layer / File(s)Summary
Multi-tier Project Lookup with Fallbacks
app/projects/[pubkey]/[id]/StandaloneProjectPage.tsx
Extends imports to include fetchCommunityProjects, fetchCommunityProjectsSnapshot, and projectMatchesIdentifier. The useEffect loader is rewritten with AbortController cancellation: it attempts direct load via fetchProjectByDTag, falls back to snapshot matching, then community relay matching, fetches author pictures for the resolved author, and prevents post-unmount state updates.
Page Rendering with Suspense Boundary
app/projects/[pubkey]/[id]/page.tsx
Adds Suspense import and introduces ProjectFallback loading-skeleton component. Converts ProjectPage from async/await of params to a non-async render that wraps content in Suspense and resolves params via params.then(...), enabling incremental rendering with a fallback UI instead of blocking on async input.

Sequence Diagram

sequenceDiagram
participant Browser
participant ProjectPage
participant Suspense as Suspense Boundary
participant StandaloneProjectPage
participant Loader as Async Loader
participant Direct as fetchProjectByDTag
participant Snapshot as fetchCommunityProjectsSnapshot
participant Community as fetchCommunityProjects
participant AuthorAPI as fetchAuthorPictures
Browser->>ProjectPage: Request /{pubkey}/{id}
ProjectPage->>Suspense: Render with params.then(...)
Suspense->>Browser: Show ProjectFallback skeleton
ProjectPage->>StandaloneProjectPage: params resolve
StandaloneProjectPage->>Loader: useEffect triggered
Loader->>Direct: Try direct fetch
alt Project found
Direct->>Loader: Return project
else Project not found
Direct->>Loader: null/error
Loader->>Snapshot: Query snapshot
alt Match in snapshot
Snapshot->>Loader: Return project
else No match
Loader->>Community: Query relay (timeout)
Community->>Loader: Search results
Loader->>Loader: Match via projectMatchesIdentifier
end
end
Loader->>AuthorAPI: Fetch author pictures
AuthorAPI->>Loader: Author data
Loader->>StandaloneProjectPage: setProject(data)
StandaloneProjectPage->>Browser: Render project detail
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly Related PRs

  • lacrypta/lacrypta-dev#7: Both PRs add <Suspense> boundaries to page components (page.tsx routes) with fallback UI, replacing direct await of async inputs with params.then(...) rendering patterns.
  • lacrypta/lacrypta-dev#8: Both PRs implement fallback project lookups via fetchCommunityProjectsSnapshot with abortable async fetching and Suspense/params.then(...) page rendering in project detail pages.

Poem

🐰 The rabbit hops through nested queries deep,
From direct fetch to snapshot's fuzzy keep,
Then leaps to relays far and wide—
While Suspense shows a skeleton with pride!
Three chances to find the project's tale,
And graceful cancellation won't fail. ✨

✨ 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 codex/fix-standalone-project-route

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.

@agustinkassis
agustinkassis marked this pull request as ready for review June 3, 2026 21:23
@agustinkassis
agustinkassis merged commit 6c0b707 into mainJun 3, 2026
3 checks passed
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