Skip to content

PWA, FCM, and web Stripe checkout#18

Merged
rezwana-karim merged 7 commits into
mainfrom
pwa
Jun 4, 2026
Merged

PWA, FCM, and web Stripe checkout#18
rezwana-karim merged 7 commits into
mainfrom
pwa

Conversation

@rezwana-karim
Copy link
Copy Markdown
Collaborator

@rezwana-karim rezwana-karim commented Jun 4, 2026

Summary

Adds end-to-end web/PWA support: Firebase Cloud Messaging (Flutter + service worker + Supabase dispatch), improved installability and web shell, platform abstractions for notifications/media/payments, and Stripe Hosted Checkout on web. Includes Cursor ignore/config cleanup and deployment workflow updates.

Scope

  • Firebase/FCM client, web SW, Supabase edge functions and migrations
  • Web marketplace checkout (hosted Stripe) with path-based return URLs
  • PWA manifest, splash, and care web push reminders
  • Tooling: Firebase sync scripts, GitHub Actions Vercel deploy

Test plan

  • flutter analyze and flutter test
  • Web: sign in, complete Stripe checkout, confirm return to /marketplace/order/:id?stripe=success
  • Web: enable push from Care tab; verify FCM token in user_fcm_devices
  • Android/iOS: FCM foreground/background notification tap routing
  • Set Supabase secret PUBLIC_APP_ORIGIN (comma-separated origins allowed via ALLOWED_REDIRECT_ORIGINS) before production hosted checkout

Copilot AI review requested due to automatic review settings June 4, 2026 22:00
Copy link
Copy Markdown

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

This PR expands the project’s web/PWA and notification capabilities by adding Firebase Cloud Messaging (FCM) support end-to-end (Flutter client + web service worker + Supabase functions/migrations), improving the web shell/manifest, and extending marketplace checkout to use Stripe Hosted Checkout on web. It also includes tooling/docs updates and Cursor ignore/config changes.

Changes:

  • Add Firebase/FCM integration across Flutter (token sync + routing + local display), web (service worker), and Supabase (dispatch functions + DB triggers/outbox).
  • Improve web/PWA UX and installability (manifest start_url, screenshots/shortcuts, iOS splash assets, updated PWA banner, loading timeout).
  • Add web-specific platform abstractions (notifications, media picking, image caching, payments) and adjust marketplace flow for web Stripe checkout.

Reviewed changes

Copilot reviewed 106 out of 115 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
web/pwa_banner.js Refactors iOS install banner injection/styling and delays it until Flutter first frame.
web/push_register.js Adds a JS helper for VAPID Web Push registration (currently not wired/used).
web/manifest.json Updates PWA metadata (id, start_url, screenshots, shortcuts).
web/index.html Adds splash timeout/error handling, startup images, and registers Firebase messaging SW.
web/firebase-messaging-sw.js Adds Firebase Messaging service worker for background notifications.
web/firebase-config.js.example Example Firebase web config for the SW.
web/firebase-config.js Firebase web config used by the SW.
tool/sync_firebase_web_config.dart Tool to generate web/firebase-config.js from .env.
tool/sync_firebase_from_cli.ps1 PowerShell helper to regenerate Firebase configs via CLI/FlutterFire.
tool/set_fcm_supabase_secrets.ps1 PowerShell helper to upload FCM secrets to Supabase and sync dispatch secret.
test/core/firebase/fcm_message_router_test.dart Unit tests for push payload → route mapping behavior.
supabase/migrations/20260607140000_fcm_dispatch_system.sql Adds FCM dispatch tables, triggers, outbox, pg_net + cron schedules.
supabase/migrations/20260606120000_user_fcm_devices.sql Adds user_fcm_devices table + RLS for storing FCM tokens.
supabase/migrations/20260605130000_waitlist_insert_policy_hardening.sql Tightens waitlist insert policy with basic email validation.
supabase/migrations/20260605120000_restore_matching_discovery_candidates_cursor.sql Restores keyset/cursor-based matching discovery RPC signature + grants.
supabase/migrations/20260605100000_pwa_phase2.sql Adds checkout/care web tables and web push subscription table + RLS.
supabase/migrations/20260604000000_fix_matching_discovery_candidates_offset_signature.sql Converts a previously conflicting migration into a no-op placeholder.
supabase/functions/stripe-webhook/index.ts Adds Checkout Session events and shared idempotent fulfillment helper.
supabase/functions/send-fcm-notification/index.ts Adds authenticated (secret header) FCM send endpoint.
supabase/functions/register-web-push-subscription/index.ts Adds edge function to store web push subscriptions for a user.
supabase/functions/process-fcm-outbox/index.ts Adds dispatcher to send queued FCM notifications from fcm_push_outbox.
supabase/functions/process-care-fcm-reminders/index.ts Adds cron-driven care reminder dispatch via FCM.
supabase/functions/create-payment-intent/index.ts Adds checkout_mode to create Stripe Hosted Checkout sessions on web.
supabase/functions/_shared/fcm_send.ts Adds Firebase HTTP v1 sender with service-account JWT + token cleanup.
supabase/.temp/cli-latest Bumps stored Supabase CLI marker.
PWA_WEB_AUDIT.md Adds a detailed web/PWA audit document and recommended roadmap.
pubspec.yaml Adds firebase_core and firebase_messaging.
progress.md Logs PWA + backend phases and operational notes.
lib/main.dart Initializes Firebase/FCM, adjusts Stripe init (non-web at startup), and token sync on auth changes.
lib/firebase_options.dart Adds FlutterFire-style Firebase options (currently misconfigured for iOS).
lib/features/social/presentation/widgets/post_comments_bottom_sheet.dart Adds semantics + key for comment input (web/a11y/testing).
lib/features/social/presentation/screens/story_viewer_screen.dart Applies web image cache sizing helpers for story images.
lib/features/social/presentation/screens/social_screen.dart Applies web image cache sizing helpers for feed images.
lib/features/social/presentation/screens/social_profile_screen.dart Applies web image cache sizing helpers for grid thumbnails.
lib/features/social/presentation/screens/post_detail_screen.dart Applies web image cache sizing helpers for detail images.
lib/features/social/presentation/screens/create_story_screen.dart Uses platform media picker on web and adjusts thumbnail caching.
lib/features/social/presentation/screens/create_post_screen.dart Adds web media picker branch (but still uses dart:io preview logic).
lib/features/pet_profile/presentation/screens/edit_profile_screen.dart Switches to platform media picker for profile image selection.
lib/features/matching/presentation/widgets/match_celebration_overlay.dart Applies web image cache sizing for avatars.
lib/features/matching/presentation/screens/matching_screen.dart Improves web matching behavior and error messaging + caching.
lib/features/matching/presentation/screens/matches_inbox_screen.dart Uses safer back navigation (popOrGo).
lib/features/matching/presentation/screens/chat_screen.dart Uses safer back navigation (popOrGo) and avoids router import cycle.
lib/features/matching/presentation/matching_navigation.dart Adds popOrGo helper.
lib/features/matching/presentation/controllers/discovery_candidates_controller.dart Improves error handling when replenishing candidates fails.
lib/features/matching/data/datasources/matching_supabase_data_source.dart Wraps PostgREST errors in app DatabaseException.
lib/features/marketplace/presentation/widgets/web_checkout_resume_listener.dart Adds web lifecycle listener to resume/cancel checkout flows.
lib/features/marketplace/presentation/screens/vendor/edit_shop_screen.dart Uses platform media picker for shop image selection.
lib/features/marketplace/presentation/screens/order_confirmation_screen.dart Adds web confirmation polling when returning from Stripe.
lib/features/marketplace/presentation/screens/marketplace_screen.dart Adds web checkout cancel handling + improves tap targets/caching.
lib/features/marketplace/presentation/screens/cart_screen.dart Wraps with web checkout resume listener.
lib/features/marketplace/presentation/controllers/manual_kyc_controller.dart Uses platform media picker for KYC image selection.
lib/features/marketplace/presentation/controllers/checkout_controller.dart Adds hosted checkout path for web + resume logic; defers Stripe settings init.
lib/features/marketplace/data/repositories/order_repository.dart Adds createCheckoutSession() API for hosted checkout.
lib/features/care/presentation/widgets/web_push_enable_banner.dart Adds web UI prompt to enable push (via FCM token).
lib/features/care/presentation/screens/medical_vault_screen.dart Uses platform media picker for record uploads.
lib/features/care/presentation/screens/care_screen.dart Adds web push banner and a11y/tap improvements (InkWell/Semantics).
lib/features/care/data/repositories/pet_care_repository.dart Routes care reminders through PlatformNotifications.
lib/features/auth/presentation/widgets/auth_widgets.dart Adds autofillHints support to auth fields.
lib/features/auth/presentation/screens/login_screen.dart Sets email/password autofill hints.
lib/features/auth/data/repositories/auth_repository.dart Clears FCM token on sign out before Supabase sign-out.
lib/core/widgets/pet_avatar.dart Adds web cache sizing for avatar images.
lib/core/widgets/app_shell.dart Adjusts web shell layout to use bottomNavigationBar (web tap reliability).
lib/core/services/stripe_init_service.dart Adds ensureStripeReady() helper to centralize Stripe settings init.
lib/core/services/notification_service.dart Adds push display channels/sound, tap routing payload support, and background init path.
lib/core/services/location_service.dart Enables web geolocator paths and adjusts timeouts.
lib/core/router.dart Adds router error screen, overlay dismissal on route change, and root redirects.
lib/core/platform/web_push_registration.dart Adds conditional export for JS web push registration bridge.
lib/core/platform/web_push_registration_web.dart Implements JS interop bridge to window.PetfolioPush.
lib/core/platform/web_push_registration_stub.dart Stub for non-web builds.
lib/core/platform/web_image_cache.dart Adds DPI-aware cache width helpers with web caps.
lib/core/platform/web_checkout_redirect.dart Conditional export for direct web redirect helper.
lib/core/platform/web_checkout_redirect_web.dart Implements window.location.href redirect helper.
lib/core/platform/web_checkout_redirect_stub.dart Stub for non-web builds.
lib/core/platform/web_app_url.dart Adds helper to build app URLs for hosted checkout redirects (currently uses hash).
lib/core/platform/platform_services.dart Barrel export for platform abstractions.
lib/core/platform/platform_payments.dart Adds useStripeHostedCheckout platform flag (web).
lib/core/platform/platform_notifications.dart Adds abstraction for notifications across web/io.
lib/core/platform/platform_notifications_web.dart Web implementation uses Supabase care_web_reminders.
lib/core/platform/platform_notifications_io.dart IO implementation schedules local notifications and syncs reminders to Supabase.
lib/core/platform/platform_location.dart Barrel exports for location services/providers.
lib/core/platform/media_picker.dart Conditional export for media picking on web/io.
lib/core/platform/media_picker_web.dart Web media picking implementation.
lib/core/platform/media_picker_io.dart IO media picking implementation.
lib/core/platform/care_fcm_reminder_sync.dart Upserts/deletes care reminders into Supabase for FCM dispatch.
lib/core/navigation/route_overlay_dismissal.dart Adds helper to dismiss popup routes on navigation changes.
lib/core/firebase/firebase_env.dart Adds Firebase env helpers (platform label, VAPID key access).
lib/core/firebase/fcm_token_repository.dart Adds Supabase persistence for FCM tokens.
lib/core/firebase/fcm_service.dart Adds core FCM lifecycle: permissions, token sync, routing, foreground handling.
lib/core/firebase/fcm_push_display.dart Shows FCM foreground messages via local notifications.
lib/core/firebase/fcm_message_router.dart Maps push payloads to app routes and chooses push vs go navigation.
lib/core/firebase/fcm_lifecycle.dart Adds a Riverpod-based lifecycle wrapper (appears unused now).
lib/core/firebase/fcm_background_handler.dart Adds background handler to show notifications and init Firebase/plugins.
ios/Runner.xcodeproj/project.pbxproj Bundles chat notification sound resource in iOS build.
firebase.json Adds FlutterFire/Firebase config artifact.
firebase-instructions.md Adds setup/deploy/runbook for Firebase FCM + Supabase integration.
android/settings.gradle.kts Adds Google Services Gradle plugin version.
android/app/src/main/AndroidManifest.xml Sets default FCM notification channel id meta-data.
android/app/google-services.json Adds Firebase Android config.
android/app/build.gradle.kts Applies Google Services plugin.
AGENTS.md Updates agent guidance with web/FCM conventions.
.gitignore Ignores Firebase Admin SDK JSON and Supabase FCM secrets env file.
.firebaserc Adds default Firebase project mapping.
.env.example Adds Firebase/FCM-related env vars and dispatch secret placeholder.
.cursorignore Reworks Cursor ignore rules (more aggressive platform/build/media ignores).
.cursor/settings.json Enables Cursor plugins (Stripe/Supabase/Firebase/modern web guidance).
.cursor/hooks/state/continual-learning.json Updates local Cursor hook state.
.cursor/hooks/state/continual-learning-index.json Updates local Cursor hook state index (machine-specific paths).
.claudeignore Adjusts Claude ignore patterns (removes html/jsx ignores).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/core/platform/web_app_url.dart Outdated
Comment on lines +11 to +14
if (kIsWeb) {
return '${Uri.base.origin}/#$normalized$query';
}
return '${Uri.base.origin}$normalized$query';
Comment on lines 2 to 6
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:flutter/foundation.dart';
import 'package:image_picker/image_picker.dart';
Comment thread lib/firebase_options.dart
Comment on lines +42 to +49
static const FirebaseOptions ios = FirebaseOptions(
apiKey: 'AIzaSyDW3jiVahlDqTey6aj0zsj9Z-Dj-kvamgE',
appId: '1:86798095066:android:5b5d6008f7ab957f68cbe3',
messagingSenderId: '86798095066',
projectId: 'petfolio-v1',
storageBucket: 'petfolio-v1.firebasestorage.app',
iosBundleId: 'com.example.petfolio',
);
Comment on lines +5 to +7
if (!await envFile.exists()) {
stderr.writeln('.env not found. Copy .env.example and set FIREBASE_VAPID_KEY.');
exitCode = 1;
Comment on lines +191 to +194
if (checkout_mode) {
if (!success_url || !cancel_url) {
return json({ error: 'success_url and cancel_url are required for checkout_mode' }, 400);
}
Comment thread lib/main.dart
Comment on lines +82 to +84
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler);
await FcmService.instance.initialize();
Comment on lines +1 to +5
{
"version": 1,
"files": {
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\ce1b2c8d-81a4-4639-90f8-3721e6c503a7\\ce1b2c8d-81a4-4639-90f8-3721e6c503a7.jsonl": 1779035133681,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\94643488-4659-4d0e-9545-49a79437f020\\94643488-4659-4d0e-9545-49a79437f020.jsonl": 1778967578761,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\36e3088e-0d5c-45e5-b1ba-d1054303de94\\36e3088e-0d5c-45e5-b1ba-d1054303de94.jsonl": 1779039991962,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\bced3497-a066-4257-b439-2b857e493c49\\bced3497-a066-4257-b439-2b857e493c49.jsonl": 1778888950579,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\80eedde5-7184-424c-b917-a680f1ff70a2\\80eedde5-7184-424c-b917-a680f1ff70a2.jsonl": 1778892745538,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\87c931dd-27e3-40aa-bdc6-3274831f9214\\87c931dd-27e3-40aa-bdc6-3274831f9214.jsonl": 1778958857308,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\60e1a481-cb4c-4ac2-aa03-bfae7cefa5fe\\60e1a481-cb4c-4ac2-aa03-bfae7cefa5fe.jsonl": 1778881486521,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\bb710a65-baaf-4764-9eae-dacedace3006\\bb710a65-baaf-4764-9eae-dacedace3006.jsonl": 1778786794129,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\274c391d-7a36-49d5-87be-4df8b522bd16\\274c391d-7a36-49d5-87be-4df8b522bd16.jsonl": 1778800364415,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\194eaf83-5b12-43e4-b1ea-318bbf90c26c\\194eaf83-5b12-43e4-b1ea-318bbf90c26c.jsonl": 1778954732395,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\25b68db3-c204-4def-aead-73ff3500c794\\25b68db3-c204-4def-aead-73ff3500c794.jsonl": 1778876459233,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\8c5433a9-d387-4e9b-ba3a-1e1e006c37bf\\8c5433a9-d387-4e9b-ba3a-1e1e006c37bf.jsonl": 1778856406418,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\e6552f8a-c6c0-4b71-b118-14f55640ae1f\\e6552f8a-c6c0-4b71-b118-14f55640ae1f.jsonl": 1778776581760,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\16628f4f-057e-4274-96e0-ec9ad3d893be\\16628f4f-057e-4274-96e0-ec9ad3d893be.jsonl": 1778882210597,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\0148be8a-b886-48f4-bdd3-67d076c8182c\\0148be8a-b886-48f4-bdd3-67d076c8182c.jsonl": 1778792789903,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\7abfd4c7-d454-4cf6-a391-333321a013ad\\7abfd4c7-d454-4cf6-a391-333321a013ad.jsonl": 1779058557683,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\5acfed98-7cbf-4420-ac3d-091356b8e44f\\5acfed98-7cbf-4420-ac3d-091356b8e44f.jsonl": 1778871687683,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\d7bd1b6a-f748-47f6-87ac-953246413613\\d7bd1b6a-f748-47f6-87ac-953246413613.jsonl": 1778799809267,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\2d86f00f-6bfb-451f-928c-ff0fea1f79d2\\2d86f00f-6bfb-451f-928c-ff0fea1f79d2.jsonl": 1779034182814,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\6460028d-51b8-402d-8b25-5fbcae4596f2\\6460028d-51b8-402d-8b25-5fbcae4596f2.jsonl": 1778961242286,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\88c2a075-4e77-4d24-81f3-b7ba5b774ac4\\88c2a075-4e77-4d24-81f3-b7ba5b774ac4.jsonl": 1778891774309,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\9ebdd98e-260d-475c-999c-dd06afa742cd\\9ebdd98e-260d-475c-999c-dd06afa742cd.jsonl": 1778802413316,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\5bead4b5-9471-461d-ab9a-957f4c1c2490\\5bead4b5-9471-461d-ab9a-957f4c1c2490.jsonl": 1778892105848,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\dab4e7c9-f531-4cb9-a593-62d5c029e54b\\dab4e7c9-f531-4cb9-a593-62d5c029e54b.jsonl": 1778879297617,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\8ea6431f-f572-411a-98e3-0dc5552c5a51\\8ea6431f-f572-411a-98e3-0dc5552c5a51.jsonl": 1778783272217,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\babe61d3-90ce-4696-be96-37e1e4e0f971\\babe61d3-90ce-4696-be96-37e1e4e0f971.jsonl": 1778891057278,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\09fd1bb0-4e5e-4e5d-a591-a22fac645ab3\\09fd1bb0-4e5e-4e5d-a591-a22fac645ab3.jsonl": 1778873095891
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\46b1bc04-342c-4e30-a6dd-b55acfed523f\\46b1bc04-342c-4e30-a6dd-b55acfed523f.jsonl": 1780583489178,
"C:\\Users\\syedr\\.cursor\\projects\\g-GitHub-petfolio\\agent-transcripts\\ce1b2c8d-81a4-4639-90f8-3721e6c503a7\\ce1b2c8d-81a4-4639-90f8-3721e6c503a7.jsonl": 1779013533682,
@syed-reza98 syed-reza98 changed the title Pwa PWA, FCM, and web Stripe checkout Jun 4, 2026
@rezwana-karim rezwana-karim merged commit c948b51 into main Jun 4, 2026
1 check passed
@rezwana-karim rezwana-karim deleted the pwa branch June 4, 2026 22:31
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.

3 participants