Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To turn a Flask app into a progressive web app (PWA), serve it over HTTPS, provide a web-app manifest, and register a service worker. Whatz the Good Word shows how those pieces can give a simple vocabulary game an app-like experience, including cached responses for offline use and a deployment stack built from Nginx, Gunicorn, systemd, and Certbot.

What is Whatz the Good Word?

Whatz the Good Word is a vocabulary game in which a player reads a clue and guesses the word. The interface offers three actions: check a guess, reveal the answer, or request a new clue. Mahboob Hussain’s DZone walkthrough describes taking an earlier Flask word game and adding progressive web app features. Read the walkthrough on DZone.

The example keeps its content model deliberately simple. Clues and answers are stored as pipe-delimited records in a flat file. When Flask starts, it loads those records into an array. The index route picks a random entry, separates its clue and answer, and sends the clue and entry index to the page; the index is kept in a hidden field for later requests.

What does a Flask app need to become a PWA?

  • HTTPS: The app must be served securely for the tutorial’s PWA setup. Hussain states, “The first requirement for a PWA is that it should be served over HTTPS.”
  • A web-app manifest: The JSON file describes the app to supporting browsers.
  • A service worker: The JavaScript worker is registered by the page and handles lifecycle and fetch events, including the chosen caching behavior.

In the example, both the manifest and service-worker script live in Flask’s static directory, so Flask serves them as static assets without a separate route. The page registers /wtgw/static/serviceworker.js with the scope /wtgw/. That scope matters: it limits which pages and requests the worker can control. If you change the app’s mount path, update the registration URL and scope to match your deployment.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How does the game handle guesses and new clues?

Check a guess

The Check action uses a jQuery AJAX GET request to send the hidden clue index and the player’s typed answer to Flask. The server compares the submission with the stored answer and returns either “You got it right!” or “Wrong Answer! Please try Again!!”. After a correct answer, the page hides the Check and Show Answer buttons.

Reveal the answer

Show Answer requests the stored answer from the server. The page displays it and hides the answer input and controls.

Request another clue

New Word Clue obtains a different random entry, clears the input, and restores the controls. Because this is a dynamic action, the service worker must not treat its response like a reusable page or asset.

How should the service worker cache Flask responses?

The walkthrough’s worker listens for install, activate, and fetch events and caches successful basic responses. Its key exception is the /wtgw/new endpoint: requests for a new clue bypass cache handling so the player does not repeatedly receive a previously cached clue. This illustrates a central design choice for Flask PWAs: cache stable resources where appropriate, but let changing or stateful endpoints reach the server.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

If a fetch fails and there is no cached response to use, the example returns: “You seem to be offline, please try after you’re online”. That fallback is a message, not a guarantee that every game action works offline. In particular, actions that need Flask to select or validate data still depend on a reachable server unless the app is designed to handle them locally.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

How does the example deploy Flask with Nginx and Gunicorn?

The production-style walkthrough places Nginx in front of Gunicorn and uses systemd to manage the app process. Nginx proxies requests under /wtgw/ to a Gunicorn Unix socket. The systemd unit starts Gunicorn with three workers and the Flask WSGI entry point wsgi:app.

  1. Use a domain name. The author uses a domain because the walkthrough’s Let’s Encrypt certificate setup is for domain names rather than bare IP addresses.
  2. Install Certbot with snap and request the Nginx configuration. The command shown is certbot --nginx.
  3. Configure Nginx to proxy the app path. Route /wtgw/ to the Gunicorn Unix socket used by the service.
  4. Run Gunicorn under systemd. The example uses three workers and wsgi:app; adapt the service and socket paths to your own installation.
  5. Check certificate renewal. The walkthrough includes a Certbot renewal dry run to verify the renewal setup.

HTTPS is part of the PWA requirements, so certificate installation and renewal are not incidental deployment details. A working reverse proxy and WSGI process make the Flask app available; TLS lets the browser load it securely and use the service-worker features described above.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.