feat(web): add stores discovery page#334
Conversation
Review or Edit in CodeSandboxOpen the branch in Web Editor • VS Code • Insiders |
📝 WalkthroughWalkthroughThis PR adds a new public Stores discovery page to the Next.js app. It fetches up to 24 verified stores from an API endpoint, validates the payload with type guards, formats store metadata (initials, follower counts), renders individual store cards with banners/logos and fallback states, and provides empty/error UI when data is unavailable or malformed. ChangesStores Page Feature
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
apps/web/src/app/(public)/stores/page.tsx (1)
235-238: Confirm store profile URL handling (/stores/${handle}vs/@${handle})
apps/web/src/app/(public)/stores/page.tsxlinks to/stores/${handle}, whileapps/web/src/components/feed/FeedCard.tsxlinks to/@${store.handle}—both work becauseapps/web/src/middleware.tsrewrites"/@handle"→"/stores/handle", andapps/web/src/app/(public)/stores/[handle]/page.tsxreadsparams.handlefrom/stores/[handle].🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@apps/web/src/app/`(public)/stores/page.tsx around lines 235 - 238, Inconsistent store URL formats are used: one Link uses `/stores/${handle}` (page.tsx) while FeedCard uses `/@${store.handle}`; pick a canonical URL (use `/stores/${handle}` to match the stores/[handle]/page component) and update all Link usages to that pattern (update FeedCard's Link href to `/stores/${store.handle}` and any other occurrences). Also verify middleware rewrite still maps `/@handle` → `/stores/handle` if you want backwards compatibility and ensure the stores/[handle]/page component continues to read params.handle correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/web/src/app/`(public)/stores/page.tsx:
- Around line 86-112: The fetchStores function currently uses raw fetch and
should use the shared api helper to centralize base URL, credentials and
envelope unwrapping: in fetchStores replace the fetch(...) call with
api.get<FeedResponse>("/feed/stores?limit=24") (or first extend the api client
to accept Next fetch options like cache: "no-store" if you need to preserve that
behavior), then consume response.data and pass it to unwrapFeedResponse instead
of awaiting response.json(); keep the same error-path checks but base them on
the api client's response and status.
---
Nitpick comments:
In `@apps/web/src/app/`(public)/stores/page.tsx:
- Around line 235-238: Inconsistent store URL formats are used: one Link uses
`/stores/${handle}` (page.tsx) while FeedCard uses `/@${store.handle}`; pick a
canonical URL (use `/stores/${handle}` to match the stores/[handle]/page
component) and update all Link usages to that pattern (update FeedCard's Link
href to `/stores/${store.handle}` and any other occurrences). Also verify
middleware rewrite still maps `/@handle` → `/stores/handle` if you want
backwards compatibility and ensure the stores/[handle]/page component continues
to read params.handle correctly.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: a06a6fb9-ab75-4e28-9ab8-1b11dbc2113f
📒 Files selected for processing (1)
apps/web/src/app/(public)/stores/page.tsx
| async function fetchStores(): Promise<StoreLoadState> { | ||
| const apiBase = process.env.NEXT_PUBLIC_API_URL?.replace(/\/$/, ""); | ||
|
|
||
| if (!apiBase) { | ||
| return { | ||
| status: "error", | ||
| message: "Store discovery is not configured for this environment.", | ||
| }; | ||
| } | ||
|
|
||
| try { | ||
| const response = await fetch(`${apiBase}/feed/stores?limit=24`, { | ||
| cache: "no-store", | ||
| headers: { | ||
| Accept: "application/json", | ||
| }, | ||
| }); | ||
|
|
||
| if (!response.ok) { | ||
| return { | ||
| status: "error", | ||
| message: "Verified stores could not be loaded right now.", | ||
| }; | ||
| } | ||
|
|
||
| const parsed = unwrapFeedResponse(await response.json()); | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify that a shared Axios client with response unwrapping exists and is the expected frontend standard.
fd -i 'api*.ts' apps/web/src
rg -n -C3 'axios\.create|baseURL|withCredentials|interceptors\.response|success.*data' apps/web/src
rg -n -C3 '\bfetch\s*\(' apps/web/src/app/(public)/stores/page.tsxRepository: coded-devs/twizrr
Length of output: 2105
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Show shared API client implementation (if any)
echo "---- apps/web/src/lib/api.ts (head) ----"
wc -l apps/web/src/lib/api.ts
sed -n '1,220p' apps/web/src/lib/api.ts | cat -n
echo "---- apps/web/src/lib/api.ts (tail) ----"
sed -n '220,520p' apps/web/src/lib/api.ts | cat -n || true
# Inspect the stores discovery page around the reported lines
echo "---- apps/web/src/app/(public)/stores/page.tsx (region) ----"
wc -l "apps/web/src/app/(public)/stores/page.tsx"
sed -n '60,160p' "apps/web/src/app/(public)/stores/page.tsx" | cat -n
# Re-run a safe search for fetch usage in that page
echo "---- fetch usage in stores page ----"
rg -n '\bfetch\s*\(' "apps/web/src/app/(public)/stores/page.tsx" || true
# Check whether /stores/[handle] exists
echo "---- routes under apps/web/src/app/(public)/stores ----"
fd -e ts -e tsx "apps/web/src/app/(public)/stores" -a | sort || true
fd -e ts -e tsx "apps/web/src/app/(public)" | rg '/stores/' | head -n 50 || true
# Search for links that use /stores/${handle}
echo "---- link patterns for /stores/ ----"
rg -n '\/stores\/\$\{.*handle.*\}' apps/web/src | head -n 50 || true
rg -n '\/stores\/' apps/web/src/app/(public)/stores/page.tsx || trueRepository: coded-devs/twizrr
Length of output: 9632
Use the shared api client instead of raw fetch in fetchStores()
apps/web/src/app/(public)/stores/page.tsxcallsfetch(...)directly, bypassingapps/web/src/lib/api.ts(apihelper) that centralizesNEXT_PUBLIC_API_URL,credentials: "include", and{ data }envelope unwrapping. Replace the direct call withapi.get<FeedResponse>("/feed/stores?limit=24")(or extend the helper to accept Nextfetchoptions likecache: "no-store"to preserve current semantics).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@apps/web/src/app/`(public)/stores/page.tsx around lines 86 - 112, The
fetchStores function currently uses raw fetch and should use the shared api
helper to centralize base URL, credentials and envelope unwrapping: in
fetchStores replace the fetch(...) call with
api.get<FeedResponse>("/feed/stores?limit=24") (or first extend the api client
to accept Next fetch options like cache: "no-store" if you need to preserve that
behavior), then consume response.data and pass it to unwrapFeedResponse instead
of awaiting response.json(); keep the same error-path checks but base them on
the api client's response and status.
Summary by CodeRabbit