Skip to content

feat(apps): restructure apps page with typed config, download modal, and powered-by section #883#884

Merged
dadofsambonzuki merged 31 commits intomainfrom
powered-by-apps
Apr 3, 2026
Merged

feat(apps): restructure apps page with typed config, download modal, and powered-by section #883#884
dadofsambonzuki merged 31 commits intomainfrom
powered-by-apps

Conversation

@dadofsambonzuki
Copy link
Copy Markdown
Member

@dadofsambonzuki dadofsambonzuki commented Apr 2, 2026

Does this PR address a related issue?

#883

A description of the changes proposed in the pull request

  • Introduces src/lib/apps.ts with a typed AppConfig system (platforms, stores, tag, sponsor)
  • /apps page restructured into three sections: BTC Map Apps, Powered by BTC Map, and Coming Soon
  • Sponsored apps sort first within the Powered by BTC Map section
  • Clicking a multi-store app opens a download modal; single-store navigates directly
  • Home page app buttons now show platform icons (Android / iOS / Web) in the same rounded-circle style
  • Platform names shown +-separated under each app card, centered to match the coming-soon style
  • App card titles and platform labels are now center-aligned consistently across all sections
  • Sponsor badge rendered on all card types including coming-soon
  • New store SVG icons added: zapstore, app-store, google-play, apk, obtainium, linux-package
  • Legacy apps readable store removed from store.ts
  • Fixed focus restoration in Modal.svelte — auto-captures document.activeElement when the modal opens so keyboard focus returns to the trigger button on close; triggerEl is reset after focus is restored
  • Removed unused "play" store key from StoreKey type and AppDownloadModal.svelte (dead code; all configs use "google-play")
  • Translated comingSoon i18n 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 English
  • Simplified storeLabels in AppDownloadModal.svelte to Record<StoreKey, string> (label only) — since every StoreKey value is an identical AppIconName, entry.store is passed directly to IconApps as the icon; the redundant icon field and AppIconName import are removed
  • Moved hardcoded sponsor badge text ("Sponsor") and download button aria-label ("Download {name}") in AppCard.svelte to i18n keys (apps.sponsor, apps.downloadAria) with translations in all 8 locale files (en, bg, de, es, fr, nl, pt-BR, ru)
  • Added apps.openAria i18n key ("Open {name}") used as the button aria-label for single-store web app cards (which navigate rather than download), keeping apps.downloadAria for all other cases; translated in all 8 locale files
  • Fixed handleClick in AppCard.svelte: goto is now used only for internal/relative web URLs (e.g., /map); absolute external URLs (e.g., https://coinos.io) use window.open(..., "_blank", "noopener,noreferrer") to correctly open in a new tab

Screenshots

Additional context

  • BTC Map app cards display only the platform label (e.g. Android, iOS, Web) rather than repeating the app name
  • Mobile modal styling improvements are deferred to a follow-up PR

…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)
@netlify
Copy link
Copy Markdown

netlify bot commented Apr 2, 2026

Deploy Preview for btcmap ready!

Name Link
🔨 Latest commit 435d475
🔍 Latest deploy log https://app.netlify.com/projects/btcmap/deploys/69cf4b5cd18f1b0008a57880
😎 Deploy Preview https://deploy-preview-884--btcmap.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 51 (🔴 down 21 from production)
Accessibility: 97 (no change from production)
Best Practices: 92 (🔴 down 8 from production)
SEO: 96 (no change from production)
PWA: 90 (no change from production)
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 2, 2026

📝 Walkthrough

Walkthrough

New modal-driven app download flow and centralized app metadata were added: a reusable Modal, an AppDownloadModal, a typed appConfigs dataset, updates to icon types/assets, and refactors converting pages/components from a global apps store to use AppConfig structures. i18n files updated for app categories.

Changes

Cohort / File(s) Summary
Modal Components
src/components/Modal.svelte, src/components/AppDownloadModal.svelte
Add reusable Modal with focus/escape/outclick handling and setTrigger; add AppDownloadModal exposing app and open, rendering store-specific download links and icons.
Language Modal Update
src/components/LanguageModal.svelte
Replaced inline modal/focus logic with shared Modal component and simplified trigger; swapped icon rendering to inline SVG.
App Configuration
src/lib/apps.ts
New typed AppConfig, AppStoreEntry, Platform, StoreKey, AppTag, and exported appConfigs list of app metadata.
Icon System
src/lib/icons/types.ts, src/lib/icons/IconApps.svelte
Replaced bolt with store-specific icons (apk, app-store, google-play, linux-package, obtainium, zapstore) and wired raw SVG imports; updated AppIconName union.
Removed Global Store
src/lib/store.ts
Removed exported apps readable store; app data now sourced from appConfigs.
App Listing & Card Refactor
src/routes/+page.svelte, src/routes/apps/+page.svelte, src/routes/apps/components/AppCard.svelte
Pages and AppCard now consume appConfigs (filtered by tag) and pass app: AppConfig; click behavior centralized to open modal or navigate/open store links; AppCard props replaced by single app.
i18n Updates
src/lib/i18n/locales/{bg,de,en,es,fr,nl,pt-BR,ru}.json
Removed platform-specific keys (googlePlayNote, official, community, pwa, fdroid, directandroid, zapstore, ios); added btcmap, poweredBy, comingSoon, sponsor, downloadAria; formatting tweaks for badge entries.

Sequence Diagram

sequenceDiagram
    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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

Review effort 4/5

Suggested reviewers

  • dadofsambonzuki
  • bubelov

Poem

🐇 I hopped in with a modal bright,
Apps lined up in gentle light,
Icons clattered, links took flight,
Configs snug and translations right,
Hooray — downloads dance all night! 🎉

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(apps): restructure apps page with typed config, download modal, and powered-by section #883' accurately captures the main changes: introducing typed app configuration, restructuring the apps page into sections, adding a download modal, and a powered-by section.
Description check ✅ Passed The PR description follows the repository template with all required sections completed: links to issue #883, provides detailed technical description of changes including config system, page restructuring, UI improvements, i18n updates, and accessibility fixes. Additional context clarifies deferred mobile styling work.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch powered-by-apps

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@escapedcat

This comment was marked as resolved.

This comment was marked as resolved.

@dadofsambonzuki
Copy link
Copy Markdown
Member Author

dadofsambonzuki commented Apr 2, 2026

Do we need to write "BTC Map" for eahc item again?

Nah we don't. Was clunky and just default from the config. Now uses just platform label and not app title for btcmap apps.

Icons coming later?

Yup

Should be align the modal style? The app one looks nicer I think, maybe let the LLM create a shared model component?

Yup, although I prefer the language one 😂

(Does writing BTC Map as header make sense? Why not Android?)

Name does make sense for mutli-platform apps with common code base. We could change the title from name to platform too to make consistent with how we've treated the BTC Map apps in the other components.

…al style with LanguageModal #883

🤖 Generated with [opencode](https://opencode.ai)
… App Store and Google Play #883

🤖 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)
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread src/components/Modal.svelte
Comment thread src/routes/apps/components/AppCard.svelte
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread src/routes/+page.svelte Outdated
Comment thread src/routes/apps/components/AppCard.svelte
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (2)
src/lib/i18n/locales/es.json (1)

949-949: ⚠️ Potential issue | 🟡 Minor

apps.poweredBy is still English in the Spanish locale.

comingSoon was 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.poweredBy is still English in the Dutch locale.

comingSoon was 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: Model stores as non-empty in the central config type.

src/components/AppDownloadModal.svelte and src/routes/apps/components/AppCard.svelte both index app.stores[0] to derive titles/icons and click behavior, so allowing stores: [] 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

📥 Commits

Reviewing files that changed from the base of the PR and between 64b2244 and 2304580.

📒 Files selected for processing (13)
  • src/components/AppDownloadModal.svelte
  • src/components/Modal.svelte
  • src/lib/apps.ts
  • src/lib/i18n/locales/bg.json
  • src/lib/i18n/locales/de.json
  • src/lib/i18n/locales/en.json
  • src/lib/i18n/locales/es.json
  • src/lib/i18n/locales/fr.json
  • src/lib/i18n/locales/nl.json
  • src/lib/i18n/locales/pt-BR.json
  • src/lib/i18n/locales/ru.json
  • src/routes/+page.svelte
  • src/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

Comment thread src/lib/i18n/locales/de.json
Comment thread src/lib/i18n/locales/pt-BR.json
Comment thread src/routes/apps/components/AppCard.svelte
Comment thread src/components/AppDownloadModal.svelte Outdated
@escapedcat

This comment was marked as outdated.

This comment was marked as resolved.

@dadofsambonzuki dadofsambonzuki merged commit 39e91ee into main Apr 3, 2026
11 checks 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.

4 participants