Progressive Web App: Workflow and Considerations

My team of engineers created an Android app that integrates with ODK Collect, using intents to instantiate a Form, as well as Xform intents to retrieve data from our app. This approach has worked well for us for over 18 months.

We are in the process of re-writing our app (new business requirements), and are considering building a PWA. Our business folks would like a more "device agnostic" version of our app, where users could see our data outcomes on various platforms and devices (e.g. Android tablet, Android phone, web browser). Since we need to be able to render and submit existing ODK forms, we are considering this approach:

  • PWA user clicks on a button to launch an ODK form within a browser.
  • PWA creates a one-time use Public Access Link (PAL), and renders the form via the link within the PWA.
  • Once the PAL's form is submitted, revoke access to the PAL (hopefully limiting nefarious or duplicate submissions).

Some thoughts:

  • This works online. How do we / can we do this offline? Enketo references offline capabilities, but how?? We would like to consider ODK Web Forms (the wave of the future :wink:), but offline capabilities are way down on the roadmap.
  • If we incorporated ODK Central APIs, how could we mitigate offline experiences?
  • What other approaches to multi-platform, offline-capable would others recommend?

Thanks for any and all suggestions.

You could build a PWA that integrates either Enketo or WebForms (submission saving with WebForms is in the works, so if you wait a bit you'll have example code). If you use a serviceworker you can take care of making the app (= your web app bundle) offline in a straightforward manner.

But what to do with the submission data when offline is another matter; you'll have to save it to a browser-local DB (eg IndexedDB) and build some sync mechanism. I think that'll be the most challenging part, especially if your client apps are offline for long stretches of time (so you'll have network partitions around the clock, in distributed system terms) and can generate clashing data (eg Entity update conflicts) based on their respective diverging world views.

You could use a transparent ServiceWorker setup to this end - for the form/assets retrieval path, and even for the form submission (POST) path. But a more deliberate sync mechanism would probably be better; making it easier to deliberately precache forms and handle submissions.

I'd recommend the PWA route for ease of distribution. But it's worth appreciating that it's not as simple as "I know web sites so I know PWAs" - just like anything it requires a bit of domain expertise especially when it comes to handling app upgrades in combination with API versions, data format versions and a host of implicit mini-protocols and mini-formats that suddenly start to matter when a webapp is made offline-capable and generates data based on a detached world view :lab_coat: . With a PWA it's easy to step into distributed systems land with distributed systems problems unwittingly :laughing: The problems faced are the same as for an offline Android app, but the progressive nature of development of an offline PWA makes it all too easy to ignore certain realities.

1 Like

Enketo does have an offline mode which is requested through the URL structure. If you're using Public Access Links, you can replace the /single/ part of the URL with /x/. For regular authenticated form links, add /x/ after the /- part of the URL. This lets you access the Enketo Express PWA which saves form assets for offline use and can have an offline queue of completed submissions. These can be manually sent or are automatically attempted to be sent when a connection becomes available and Enketo is in the foreground.

We don't expose this mode explicitly through Central because we have found that it's a confusing user experience and that end users tend to forget to submit after having worked offline. With some minimal training, though, people have had great success with it.

This could be something you launch from your own custom PWA. If you want a more embedded experience, you would likely be looking at wrapping Enketo Core within your app, possibly taking inspiration from Enketo Express' PWA approach.

As @Nonsequitur describes, for anything that makes requests to the ODK Central API, you'd have to develop your own service worker layer which can make requests when online, store the response data, and serve it locally when offline.

Central is designed to detect and surface these kinds of conflicts so it's not something that a client would need to worry about.

3 Likes

Yes! You're right, I didn't mean to imply that. Central is great at handling the conflicts.
I merely wanted to convey that there'll be more opportunity for conflicts the more clients you have and the longer they are offline. Also depending, of course, on the nature of the survey and how intertwined the data is that those clients are submitting based on their respective world views, which diverge over time while offline.

2 Likes

We will be doing exactly the same in the coming months: a web app integrating web forms and syncing offline state when connectivity is restored.

Lets exchange info / notes about how things go!

There are loads of great libraries taking a local first approach to web development. I would advocate adopting one of them to avoid having to re-engineer a 'sync layer'.

Caching of requests via service workers only goes so far, and isn't as reliable as browser storage.

The planned long term goal for us would be submissions stored in PGLite via OPFS storage, then either:

  • electric-sql as the sync layer to a central postgres instance, with a trigger to update in Central.
  • when connectivity is restored, send locally stored submissions one by one.
1 Like

Hi @LN and all, I am one of the engineers on @KingBahb's team. Thank you for your input and insight, it's been really helpful for the work that we've been doing! This past sprint, we've set aside time to explore Enketo Express' PWA as well as ODK Central's API in tandem. After exploring the records-queue.js file - https://github.com/enketo/enketo/blob/main/packages/enketo-express/public/js/src/module/records-queue.js#L201 - as well as the uploadRecord function of the connection.js file - https://github.com/enketo/enketo/blob/main/packages/enketo-express/public/js/src/module/connection.js#L87 - we have two outstanding questions:

  1. Will all completed queued surveys be sent to ODK central when the user gets back online, or will the user need to visit each offline survey link that points to queued completed survey records in order for the surveys to be sent? To ask it another way, is there a way for ALL completed queued survey records to be sent to ODK Central regardless if they are from different survey links, or will the user need to visit each survey page when they are back online in order for Enketo Express to send the surveys in? In our testing of the Enketo Express PWA, we understand that survey records are saved to Enketo's IndexedDB database locally under the recordName schema, and then the record is removed once the survey has been successfully submitted. In our research, we are noticing that you will need to visit each survey link manually in order for completed surveys from that specific survey link in order for them to be uploaded. Is this how it was designed to be?

  2. You mentioned wrapping Enketo Core into our app for a more embedded experience - something that we are interested in having. Would this allow us to use Enketo Express' survey queuing, encryption, and upload functions to ODK Central?

We look forward to your reply, and thank you again for helping us out with this!

Yes, in typical usage through a web browser, every page needs to be visited to trigger submission. Maybe there'd be a way for a wrapper app to load the pages without displaying them and trigger submission that way? I'm not entirely sure what that would look like. The only Enketo-based PWAs I've seen wrap Enketo Core, not Enketo Express. I think each Enketo Express form link link would also have to be visited while offline to download the form definition and related assets.

No, all of those are in Express. It's intended to be a standalone service but also a reference app for other Enketo Core usage.

If you're considering wrapping Enketo Core, you may want to think about going straight to ODK Web Forms as its bounds are fairly similar. It's still pre-release but evolving quickly. You can see supported functionality here and our ordered backlog here. If there is specific functionality missing for your use case, we can use that as prioritization input.

1 Like