Skip to content

[GF-20] [FRONTEND] UX Polish, Mobile Optimization & PWA #52

@wumibals

Description

@wumibals

Overview

This issue is independent — it can be worked in parallel with any other issue. No contracts, SDK, or live data required.

Polish the frontend for production quality: skeleton loading screens, error boundaries, a custom 404 page, mobile optimisation, PWA support, dark/light mode toggle, and fixing a commented-out UI element.

Problem

The app currently lacks standard production-quality UI infrastructure:

  1. No loading states — data-fetching pages will show blank content while RPC calls complete
  2. No error boundaries — an uncaught error in any component crashes the entire page with no recovery option
  3. No 404 page — navigating to an unknown route shows a plain Next.js default
  4. Hero badge commented outapp/src/app/page.tsx line 43: {/* <div className={styles.heroBadge}>Live on Stellar · Soroban</div> */} — this is commented out but the CSS class heroBadge is fully defined in page.module.css
  5. No PWA support — no manifest.json, no service worker
  6. No dark/light mode toggle — the app is dark-only (background: #060810 in globals.css)
  7. No OpenGraph imageapp/src/app/layout.tsx sets title and description metadata but no og:image, causing social share cards to appear blank

Proposed Solution

1. Skeleton loading screens
Create a app/src/components/Skeleton.tsx component (CSS shimmer animation). Apply to:

  • Portfolio position cards while usePosition is loading
  • Analytics stat cards while useTVL / useAPY is loading
  • Allocation table rows while useAllocations is loading

2. Error boundary (app/src/components/ErrorBoundary.tsx)
A React class component that catches render errors. Wrap all data-heavy pages. Show: Something went wrong — try refreshing, or check your wallet connection. with a Retry button.

3. Custom 404 page (app/src/app/not-found.tsx)
A branded 404 page matching the dark theme. Include the YieldLadder logo, a Page not found message, and a link back to the homepage.

4. Enable the hero badge
Uncomment line 43 in app/src/app/page.tsx:

<div className={styles.heroBadge}>Live on Stellar · Soroban</div>

This CSS class and all its styles are already defined in app/src/app/page.module.css — just uncomment.

5. Mobile optimisation audit
Test and fix the deposit flow (/deposit), portfolio (/portfolio), and analytics (/analytics) pages on 375px and 390px viewports. Add any missing breakpoints to the relevant CSS Module files.

6. PWA (app/public/manifest.json + service worker)
Add manifest.json with app name, icons, and display: standalone. Register a service worker for offline-capable asset caching (not data caching — RPC calls should always be live).

7. Dark/light mode toggle
Add a sun/moon icon toggle in the nav. Persist preference to localStorage. Use CSS custom properties (variables) in globals.css for all colours so toggling a data-theme attribute on <html> switches the palette.

8. OpenGraph image
Create app/public/og-image.png (1200×630px) with the YieldLadder branding. Add to layout.tsx:

openGraph: { images: [{ url: '/og-image.png', width: 1200, height: 630 }] }

Acceptance Criteria

  • Skeleton shimmer appears on all data-fetching pages while loading
  • Error boundary catches render errors and shows a recovery UI (not a blank screen)
  • Navigating to /unknown-route renders the custom branded 404 page
  • Hero badge is visible on the landing page (Live on Stellar · Soroban)
  • All interactive pages render correctly on 375px mobile viewport
  • manifest.json present; app is installable as PWA on Android Chrome
  • Dark/light mode toggle works and preference persists across page reloads
  • Social share card (Twitter, iMessage) shows og-image.png when the URL is shared

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions