feat(apps): restructure apps page with typed config, download modal, and powered-by section #883#884
Conversation
…and powered-by section #883 - Add src/lib/apps.ts with AppConfig type (platforms, stores, tag, sponsor) - Add coming-soon tag with dedicated section at bottom of /apps page - Sponsor badge shown on both active and coming-soon cards - Pipe-separated platform list shown under each app name - Download modal opens for multi-store apps, direct link for single-store - btcmap-tagged apps shown on home page; clicking opens modal - Add new store SVG icons: zapstore, app-store, google-play, apk, obtainium, linux-package - Remove legacy apps readable store 🤖 Generated with [opencode](https://opencode.ai)
🤖 Generated with [opencode](https://opencode.ai)
🤖 Generated with [opencode](https://opencode.ai)
…ge and home page #883 🤖 Generated with [opencode](https://opencode.ai)
✅ Deploy Preview for btcmap ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
📝 WalkthroughWalkthroughNew modal-driven app download flow and centralized app metadata were added: a reusable Changes
Sequence DiagramsequenceDiagram
participant User
participant Page as Page (Home/Apps)
participant AppCard
participant Modal as AppDownloadModal
participant Store as Store/URL
User->>Page: click app button
Page->>AppCard: provide app config
AppCard->>AppCard: evaluate app.stores
alt single store && platform == web
AppCard->>Store: goto(store.url)
else single store && platform != web
AppCard->>Store: window.open(store.url, "noopener,noreferrer")
else multiple stores
AppCard->>Modal: open with app
Modal->>User: show store options
User->>Modal: select store
Modal->>Store: goto() or window.open()
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ 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 |
This comment was marked as resolved.
This comment was marked as resolved.
🤖 Generated with [opencode](https://opencode.ai)
Nah we don't. Was clunky and just default from the config. Now uses just platform label and not app title for
Yup
Yup, although I prefer the language one 😂
Name does make sense for mutli-platform apps with common code base. We could change the title from |
#883 🤖 Generated with [opencode](https://opencode.ai)
🤖 Generated with [opencode](https://opencode.ai)
🤖 Generated with [opencode](https://opencode.ai)
…al style with LanguageModal #883 🤖 Generated with [opencode](https://opencode.ai)
… App Store and Google Play #883 🤖 Generated with [opencode](https://opencode.ai)
🤖 Generated with [opencode](https://opencode.ai)
…remove unused keys #883 🤖 Generated with [opencode](https://opencode.ai)
🤖 Generated with [opencode](https://opencode.ai)
…883 - Sourced logos from GitHub for Alby Go (1024x1024), Blink (120x120), Bull Bitcoin (512x512), and WOS (256x256) - BTC Map entries updated to use existing /images/logo.svg - BitLocal, Aqua, Cash App logos need to be added manually (placeholder fallback shown) 🤖 Generated with [opencode](https://opencode.ai)
🤖 Generated with [opencode](https://opencode.ai)
🤖 Generated with [opencode](https://opencode.ai)
🤖 Generated with [opencode](https://opencode.ai)
🤖 Generated with [opencode](https://opencode.ai)
🤖 Generated with [opencode](https://opencode.ai)
🤖 Generated with [opencode](https://opencode.ai)
🤖 Generated with [opencode](https://opencode.ai)
🤖 Generated with [opencode](https://opencode.ai)
🤖 Generated with [opencode](https://opencode.ai)
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 18 out of 32 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 18 out of 32 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (2)
src/lib/i18n/locales/es.json (1)
949-949:⚠️ Potential issue | 🟡 Minor
apps.poweredByis still English in the Spanish locale.
comingSoonwas translated, but this heading still leaves the Apps page mixed-language in Spanish.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/lib/i18n/locales/es.json` at line 949, The Spanish locale still contains an English string for the key "poweredBy" in the locales JSON; update the "poweredBy" value in src/lib/i18n/locales/es.json to the proper Spanish translation (e.g., "Desarrollado por BTC Map" or another preferred Spanish phrase) so the Apps page is fully localized; ensure you only change the value for the "poweredBy" key and preserve the JSON structure and punctuation.src/lib/i18n/locales/nl.json (1)
945-945:⚠️ Potential issue | 🟡 Minor
apps.poweredByis still English in the Dutch locale.
comingSoonwas fixed, but this heading still leaves the Apps page mixed-language in Dutch.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/lib/i18n/locales/nl.json` at line 945, The Dutch locale still has the apps.poweredBy key in English; update the "poweredBy" value in src/lib/i18n/locales/nl.json (the apps.poweredBy string) to the proper Dutch translation so the Apps page is fully localized (replace "Powered by BTC Map" with the Dutch equivalent).
🧹 Nitpick comments (1)
src/lib/apps.ts (1)
21-29: Modelstoresas non-empty in the central config type.
src/components/AppDownloadModal.svelteandsrc/routes/apps/components/AppCard.svelteboth indexapp.stores[0]to derive titles/icons and click behavior, so allowingstores: []weakens the new typed config and still lets broken cards compile.♻️ Proposed fix
export type AppConfig = { id: string; name: string; // path in /static, e.g. '/images/apps/btcmap.png' logo: string; tag: AppTag; sponsor: boolean; - stores: AppStoreEntry[]; + stores: [AppStoreEntry, ...AppStoreEntry[]]; };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/lib/apps.ts` around lines 21 - 29, The AppConfig type allows an empty stores array but downstream code (AppDownloadModal.svelte and AppCard.svelte) assumes at least one store exists; update the AppConfig.stores type to require a non-empty array (e.g., a tuple/rest type such as [AppStoreEntry, ...AppStoreEntry[]] or an equivalent non-empty-array type) so the compiler forces callers to provide at least one AppStoreEntry and prevents indexing app.stores[0] from being unsafe.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/lib/i18n/locales/de.json`:
- Line 949: The de.json localization still has "poweredBy": "Powered by BTC Map"
untranslated; update the German translation for the key apps.poweredBy (the
"poweredBy" entry in src/lib/i18n/locales/de.json) to an appropriate German
phrase (e.g., "Angetrieben von BTC Map" or similar) ensuring the string matches
the existing JSON quoting/format and preserves punctuation/capitalization
consistency with other German entries.
In `@src/lib/i18n/locales/pt-BR.json`:
- Line 900: The "poweredBy" key in pt-BR locale is still in English; update the
value for apps.poweredBy in src/lib/i18n/locales/pt-BR.json (the "poweredBy"
entry) to a Portuguese translation such as "Desenvolvido por BTC Map" (or
"Fornecido por BTC Map") so the Apps page renders fully in Portuguese.
In `@src/routes/apps/components/AppCard.svelte`:
- Around line 40-47: The click handler handleClick currently calls
goto(store.url) for any store with store.store === "web", but goto only works
for internal routes; update handleClick to check the form of store.url and only
use goto for relative/internal paths (e.g., startsWith("/") or otherwise not an
absolute URL), and use window.open(store.url, "_blank", "noopener,noreferrer")
for absolute/external URLs (e.g., starting with "http://" or "https://");
reference the app.stores array and the store.url value when implementing the
conditional.
---
Duplicate comments:
In `@src/lib/i18n/locales/es.json`:
- Line 949: The Spanish locale still contains an English string for the key
"poweredBy" in the locales JSON; update the "poweredBy" value in
src/lib/i18n/locales/es.json to the proper Spanish translation (e.g.,
"Desarrollado por BTC Map" or another preferred Spanish phrase) so the Apps page
is fully localized; ensure you only change the value for the "poweredBy" key and
preserve the JSON structure and punctuation.
In `@src/lib/i18n/locales/nl.json`:
- Line 945: The Dutch locale still has the apps.poweredBy key in English; update
the "poweredBy" value in src/lib/i18n/locales/nl.json (the apps.poweredBy
string) to the proper Dutch translation so the Apps page is fully localized
(replace "Powered by BTC Map" with the Dutch equivalent).
---
Nitpick comments:
In `@src/lib/apps.ts`:
- Around line 21-29: The AppConfig type allows an empty stores array but
downstream code (AppDownloadModal.svelte and AppCard.svelte) assumes at least
one store exists; update the AppConfig.stores type to require a non-empty array
(e.g., a tuple/rest type such as [AppStoreEntry, ...AppStoreEntry[]] or an
equivalent non-empty-array type) so the compiler forces callers to provide at
least one AppStoreEntry and prevents indexing app.stores[0] from being unsafe.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: 3f126933-baa7-4a18-8d4f-26e6ae2605c2
📒 Files selected for processing (13)
src/components/AppDownloadModal.sveltesrc/components/Modal.sveltesrc/lib/apps.tssrc/lib/i18n/locales/bg.jsonsrc/lib/i18n/locales/de.jsonsrc/lib/i18n/locales/en.jsonsrc/lib/i18n/locales/es.jsonsrc/lib/i18n/locales/fr.jsonsrc/lib/i18n/locales/nl.jsonsrc/lib/i18n/locales/pt-BR.jsonsrc/lib/i18n/locales/ru.jsonsrc/routes/+page.sveltesrc/routes/apps/components/AppCard.svelte
✅ Files skipped from review due to trivial changes (1)
- src/lib/i18n/locales/bg.json
🚧 Files skipped from review as they are similar to previous changes (5)
- src/lib/i18n/locales/en.json
- src/lib/i18n/locales/ru.json
- src/routes/+page.svelte
- src/components/Modal.svelte
- src/lib/i18n/locales/fr.json

Does this PR address a related issue?
#883
A description of the changes proposed in the pull request
src/lib/apps.tswith a typedAppConfigsystem (platforms, stores, tag, sponsor)/appspage restructured into three sections: BTC Map Apps, Powered by BTC Map, and Coming Soon+-separated under each app card, centered to match the coming-soon stylezapstore,app-store,google-play,apk,obtainium,linux-packageappsreadable store removed fromstore.tsModal.svelte— auto-capturesdocument.activeElementwhen the modal opens so keyboard focus returns to the trigger button on close;triggerElis reset after focus is restored"play"store key fromStoreKeytype andAppDownloadModal.svelte(dead code; all configs use"google-play")comingSooni18n key in all non-English locale files (bg, de, es, fr, nl, pt-BR, ru); brand names"BTC Map Apps"and"Powered by BTC Map"remain in EnglishstoreLabelsinAppDownloadModal.sveltetoRecord<StoreKey, string>(label only) — since everyStoreKeyvalue is an identicalAppIconName,entry.storeis passed directly toIconAppsas the icon; the redundanticonfield andAppIconNameimport are removed"Sponsor") and download buttonaria-label("Download {name}") inAppCard.svelteto i18n keys (apps.sponsor,apps.downloadAria) with translations in all 8 locale files (en, bg, de, es, fr, nl, pt-BR, ru)apps.openAriai18n key ("Open {name}") used as the buttonaria-labelfor single-store web app cards (which navigate rather than download), keepingapps.downloadAriafor all other cases; translated in all 8 locale fileshandleClickinAppCard.svelte:gotois now used only for internal/relative web URLs (e.g.,/map); absolute external URLs (e.g.,https://coinos.io) usewindow.open(..., "_blank", "noopener,noreferrer")to correctly open in a new tabScreenshots
Additional context