Skip to content

chore: sync dev with main#1844

Closed
chip-peanut-bot[bot] wants to merge 18 commits intodevfrom
main
Closed

chore: sync dev with main#1844
chip-peanut-bot[bot] wants to merge 18 commits intodevfrom
main

Conversation

@chip-peanut-bot
Copy link
Copy Markdown
Contributor

Branch Sync

main is 18 commits ahead of dev.

Commits to sync:

• fix: guard createAppKit with typeof window to restore SSR
• fix: move createAppKit into component render to survive production SSR
• fix: wrap NoFees in Suspense to prevent landing page SSR bailout
• refactor: consolidate ensureAppKit into initializeAppKit
• Merge pull request #1818 from peanutprotocol/fix/ssr-landing-page
• fix: remove sanctioned countries from country list
• Merge pull request #1829 from peanutprotocol/chip/remove-sanctioned-countries-v2
• fix(verify): make published field optional (default to true)
• Merge pull request #1838 from peanutprotocol/chip/fix-published-optional-v3
• Update content submodule to latest main (27 commits)
• Merge pull request #1839 from peanutprotocol/auto/update-content-20260327-190511
• fix: blog routes 404 — update content paths and enable static generation
• Merge remote-tracking branch 'origin/main' into fix/blog-routes-404
• fix: use resolved content locale in blog post schema
• fix: coerce frontmatter date to string and align category locale
• Merge pull request #1840 from peanutprotocol/fix/blog-routes-404
• hotfix: switch blog rendering from marked to MDX pipeline
• Merge pull request #1843 from peanutprotocol/hotfix/blog-mdx-rendering


Auto-generated by Chip 🐿️

Hugo0 and others added 18 commits March 27, 2026 08:32
The top-level createAppKit() call accesses browser APIs (window,
localStorage) during module evaluation, causing Next.js to emit a
BAILOUT_TO_CLIENT_SIDE_RENDERING and send an empty HTML shell for
every page. This meant Google's crawler saw zero content.

Wrapping in typeof window !== 'undefined' defers initialization to
the browser while preserving eager init for AppKit hooks
(useDisconnect, useAppKit) that require it before hydration.
Module-level typeof window guards in 'use client' files can be
evaluated server-side during Next.js production builds. Moving the
init into ContextProvider's render body with a runtime window check
ensures it only runs during client hydration, not during SSR.
ExchangeRateWidget (rendered by NoFees) calls useSearchParams(),
which suspends during SSR. Since the entire LandingPageClient was
inside a single Suspense with no fallback, this caused the whole
page to render as empty HTML on the server.

Adding a scoped Suspense around NoFees isolates the suspension so
the rest of the landing page (Hero, FAQs, SecurityBuiltIn, etc.)
renders server-side for crawlers and SEO.
Address CR feedback: remove duplicate createAppKit config by
funneling the eager init through initializeAppKit(), which already
handles deduplication, retry, and error recovery.

createAppKit() runs synchronously inside the async IIFE (no await
before it), so AppKit is ready before child hooks in the same
render pass.
fix: restore SSR for landing page (SEO)
…ountries-v2

fix: remove sanctioned countries from country list
- Pass 7: No longer errors on missing published field
- Only reports drafts (published: false) for visibility
- Pass 8: Unified behavior, both default to published
- Pass 4: Removed warning about missing published field
- Pass 9: Fixed security issue (execFileSync instead of execSync)
- Missing published = published, published: false = draft

Fixes GitHub Advanced Security alerts.
…nal-v3

fix(verify): make published field optional (default to true)
Co-authored-by: Chip <chip-bot@users.noreply.github.com>
…0327-190511

Update content submodule (27 commits)
Three issues caused all blog pages to 404 in production:

1. generateStaticParams returned [] in prod + dynamicParams was false,
   so Next.js rejected every blog slug
2. lib/blog.ts read from src/content/blog/{locale}/ but the submodule
   structure is src/content/content/blog/{slug}/{locale}.md
3. Content submodule was outdated and missing blog posts

Fix: update blog.ts to match the actual content structure, remove the
production guard from generateStaticParams, set dynamicParams = true as
safety net, and update peanut-content submodule to latest.
When a post falls back to English, inLanguage in the JSON-LD schema
should reflect the actual content language, not the requested locale.
gray-matter parses YAML dates (e.g. 2026-03-27) as Date objects, which
React cannot render as children. Coerce to ISO date string in both
getAllPosts and getPostBySlug.

Also resolve categories from the same locale as posts when falling back
to English, so category filters stay consistent.
Blog was the only marketing page using `marked` for rendering. All other
content pages (countries, compare, deposit, etc.) use `renderContent()`
from lib/mdx.ts which handles MDX components (Hero, Steps, CTA, etc.)
via next-mdx-remote. The blog content uses these same components, so
marked couldn't render them — headings and components showed as plain text.

Switch to the same MDX pipeline used everywhere else. Remove marked and
shiki dependencies from blog.ts.
hotfix: switch blog rendering from marked to MDX
@vercel
Copy link
Copy Markdown

vercel bot commented Mar 28, 2026

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

Project Deployment Actions Updated (UTC)
peanut-wallet Ready Ready Preview, Comment Mar 28, 2026 9:00am

Request Review

@chip-peanut-bot
Copy link
Copy Markdown
Contributor Author

Superseded by #1849

@chip-peanut-bot chip-peanut-bot bot closed this Mar 30, 2026
Sign up for free to 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