Skip to content

feat: serve web UI from relay + repos page redesign#479

Merged
wesbillman merged 6 commits intomainfrom
web-repo-list
May 5, 2026
Merged

feat: serve web UI from relay + repos page redesign#479
wesbillman merged 6 commits intomainfrom
web-repo-list

Conversation

@wesbillman
Copy link
Copy Markdown
Collaborator

Summary

  • Serve web SPA from relay: When SPROUT_WEB_DIR is set, the relay serves the built web frontend as a fallback, with reserved-prefix guards to avoid swallowing API/media/git 404s. Content negotiation at GET / correctly prioritizes nostr+json → WebSocket → text/html → NIP-11 fallback.
  • Same-origin WebSocket derivation: relayWsUrl() now derives the WS URL from window.location when VITE_RELAY_URL is absent, so the web app works when served directly from the relay without hardcoded URLs.
  • Docker multi-stage build: Added a Node/pnpm build stage to the Dockerfile that produces the web dist and sets SPROUT_WEB_DIR in the runtime image.
  • Repos page redesign: Redesigned the repos page to a GitHub-org-style layout with sidebar, search/filter, list view, and made it the home page.
  • just relay-web recipe: Convenience command to build the web frontend and start the relay serving it locally.

Changed files

  • Cargo.toml — added "fs" feature to tower-http
  • crates/sprout-relay/src/config.rsSPROUT_WEB_DIR config with startup validation
  • crates/sprout-relay/src/router.rsServeDir fallback + root handler content negotiation
  • web/src/shared/lib/relay-url.ts — same-origin WS URL derivation
  • .dockerignore — removed web/ exclusion
  • Dockerfile — Node build stage
  • .env.example — documented SPROUT_WEB_DIR
  • justfilerelay-web recipe
  • web/src/** — repos page redesign, new components, route changes

Test plan

  • All pre-commit hooks pass (desktop-check, web-check, mobile-check, rust-fmt, desktop-tauri-fmt)
  • All pre-push hooks pass (rust-clippy, desktop-tauri-check, desktop-build, web-build, mobile-test, rust-tests)
  • 148 sprout-core unit tests pass
  • 53 sprout-auth unit tests pass
  • Manual: just relay-web serves web UI at localhost
  • Manual: verify Docker image builds and serves web UI
  • Manual: staging deployment serves web app from relay

🤖 Generated with Claude Code

wesbillman and others added 6 commits May 5, 2026 12:08
Replace 3-column card grid with two-column layout: left sidebar with
"Connect to Relay" button and People section, main content area with
vertical repo list, search input, and sort dropdown.

- Add OrgSidebar with relay deep link button and contributor identicons
- Replace RepoCard with RepoListItem (name + Public badge + description + metadata)
- Add client-side search (name/description) and sort (newest/oldest/name)
- Add shared badge.tsx and input.tsx UI components
- Extract unique contributors from p tags into Repo interface

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Merge the separate / and /repos routes into a single index route
that renders the org-style repos page directly. Remove the "Repos"
nav link since there's only one page now. Update smoke test to check
for the Repositories section instead of the old relay URL card.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The webUrl from kind:30617 points to the relay's server-rendered page,
not a client-side route. Open it in a new tab instead of navigating
within the SPA. When no webUrl is set, render the name as plain text.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add ConnectButton component, show it on mobile (lg:hidden) and in
  the empty state so the deep link CTA is always accessible
- Change "View all N people" from a no-op button to static text
- Add aria-label="Sort repositories" to the sort select
- Restore /repos route as a redirect to / for bookmark compat

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add optional SPROUT_WEB_DIR config that enables the relay to serve the
React SPA directly. When set, browser requests get index.html while
WebSocket upgrades and Nostr clients continue working as before.

- Add "fs" feature to tower-http for ServeDir support
- Add web_dir config field with startup validation (index.html must exist)
- Add SPA fallback service with reserved-prefix protection (/api/, /media/,
  /git/, etc. return 404, not index.html; missing asset files also 404)
- Modify nip11_or_ws_handler: Accept:text/html → SPA after WS upgrade
  attempt, before NIP-11 fallback
- Fix relay-url.ts to derive WebSocket URL from window.location when
  VITE_RELAY_URL is unset (zero-config same-origin serving)
- Add Node/pnpm build stage to Dockerfile, set SPROUT_WEB_DIR=/code/web
- Remove web/ from .dockerignore so Node stage can access it
- Document SPROUT_WEB_DIR in .env.example

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a `just relay-web` convenience command that builds the web frontend
with pnpm and starts the relay with SPROUT_WEB_DIR pointed at the build
output, so you can test the production-like SPA serving locally.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@wesbillman wesbillman enabled auto-merge (squash) May 5, 2026 19:16
@wesbillman wesbillman merged commit 3a12369 into main May 5, 2026
14 checks passed
@wesbillman wesbillman deleted the web-repo-list branch May 5, 2026 19:20
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