I’d like to share some thoughts about developing mobile applications, including with Cordova or PWA technology.
I believe that the functionality provided by PWA development today is comprehensive enough to avoid having to develop for Cordova as well.
I believe that all the parts most closely related to mobile hardware are possible using HTML/JS.
I’d appreciate some thoughts on this; I probably haven’t thought of everything.
I’d be interested in hearing more about this. What are a couple of examples of native UX features have previously been hard to reproduce on a PWA, that can now be matched via HTML/JS?
Great place to develop new ideas !
I’m cooking something to be able to meteor create myapp --pwa ![]()
The idea: a Meteor scaffold flag that ships an app already passing Lighthouse PWA, with the modern Web APIs wired up out of the box — so we stop sending people to “go install jam:offline + pwa-kit + figure out a Workbox setup”.
Here’s a peek at what would land in the generated app:
Installable by default
public/manifest.webmanifestcomplete (icons 192/512/maskable, theme color, display=standalone, shortcuts, id)public/sw.jsregistered onMeteor.startupbeforeinstallpromptcaptured + reactive install button (with 7-day dismissal cooldown)- Live
display-modebadge (standalone / minimal-ui / fullscreen / window-controls-overlay / iOS standalone)
Offline-first with Workbox
- App shell precache, StaleWhileRevalidate for the bundle, CacheFirst for images/fonts
NavigationRoutewith a/offline.htmlfallback/sockjs/and/websocketcorrectly skipped — DDP never gets cached- Same-origin guards so
chrome-extension://requests don’t crashCache.put - Reactive
isOnlineindicator + “new version ready, reload” banner driven by SW lifecycle
Storage stack
- IndexedDB mirror of any reactive cursor:
mirrorCollectionToIdb(cursor, store) hydrateCollection(coll, store)at boot → Minimongo gets populated before DDP returns, so the UI renders instantly even offline- StorageManager helpers: live quota usage,
Request persistent storagebutton - Web Locks coordination between tabs (
withLock('sync', cb)) - BroadcastChannel
pwa-demoso two tabs talk without a server round-trip
Web Push out of the box
- VAPID keys generated and wired into
Meteor.settings - Server
push.subscribe/push.unsubscribe/push.sendmethods, with auto-pruning of 410 Gone endpoints - SW handles
push/notificationclick/pushsubscriptionchange - One-click “Enable notifications” → real OS notification
Meteor-specific quality of life
visibilitychange→Meteor.reconnect()if DDP is stale (Chrome aggressively throttles backgrounded standalone PWAs and the WebSocket can drop without surfacing fresh data until you reload — fixed)- DDP status badge in the UI
What’s next on the bench
- Passkeys / WebAuthn login handler (
Accounts.registerLoginHandler('webauthn', ...)) - View Transitions + Window Controls Overlay for the standalone titlebar
- Background Sync / Background Fetch for offline writes
- Generic Sensors, Web Speech, MediaRecorder — to start the Cordova-replacement story we’ve been discussing in #64577
The whole thing is being built and validated as a standalone reference app (Meteor 3.4 + Blaze, no jam:offline, pure web standards). Once the bench is green, the goal is to fold it into a meteor create --pwa flag and/or a dupontbertrand:pwa Atmosphere package
![]()
Very interesting.
Just a fast curiosity: I’m not sure if you want to include jam:offline as offline management or not.
Yes, I created a new example, notes-offline, as part of the rework of all meteor/examples.
We have announced them in the forum post: Revitalized Meteor Examples: Showcasing what Meteor can do today.
That example is a PWA and uses Meteor, Rspack, React, Mantine UI, jam:offline, jam:method, jam:pub-sub, jam:soft-delete, Zod, Workbox, LinguiJS, Mocha, ESLint, Prettier, and Playwright.
Live at: https://notes-offline.sandbox.galaxycloud.app
To check out the example app:
meteor create my-notes-offline --release 3.4.1 --example notes-offline
It provides another use case for Meteor nowadays, showcasing Rspack and Workbox integration as a way to automate SW generation. It also highlights community packages that have put a lot of effort into integrating great capabilities that work properly with native Meteor core concepts, like the jam:* family with jam:offline. It also includes extras as i18n integration wiht LinguiJs.
Native is really interesting area, and PWA/offline support is part of it. One of Meteor’s strengths from the early conception has been letting you focus on one stack, the web, to deploy apps across multiple platforms. This saves resources and lets you specialize in the web to unify the experience, not only for users, but also for you as a dev: unified dev environment, testing, benchmarking, JS/TS, etc.
We are heading into a time where Meteor can really focus more effort in this area, so all experimentation and shared knowledge is appreciated. Working on notes-offline was basically for that. Any other example using similar APIs is great to see, so everyone can be aware of the capabilities.
We’re talking about Cordova here, but CapacitorJS takes a different approach: its plugin API is designed to work uniformly across three targets, iOS, Android, and the web, calling native components on mobile and falling back to standard browser APIs when running in a web context. Working with CapacitorJS has effectively given us a single, consistent API to drive flows across devices, and its upcoming integration into Meteor is going to put that strength on full display.
About jam:offline, I asked about this because I looked into adopting it in my apps, but I found a problem.
In my apps, I often use the Decimal128 field type to work around the issue of numbers and precision in JS.
Unfortunately, jam:offline doesn’t support this data type and doesn’t allow me to implement it.
I also made a PR to fix the gap, I hope it will be evaluated ![]()