📱 PWA Principles & Best Practices
What if a website could be installed to a home screen, launch full-screen with its own icon, load instantly on the subway with no signal, and still be nothing more than HTML, CSS, and JavaScript served from a URL? That is a Progressive Web App — and in this lesson you'll learn exactly what makes one, so the next three lessons can show you how to build it.
Week 14 · Thursday: Progressive Web Apps · Lecture 1
🎯 Learning Objectives
By the end of this lesson, you will be able to:
- Define a PWA and explain the three qualities that describe one: reliable, fast, and installable
- Name the three technical pillars every PWA is built on — HTTPS, a web app manifest, and a service worker — and say what each provides
- Author a valid
manifest.jsonwith the required members a browser needs to offer installation - List the browser installability criteria and describe how the service worker "sits between" the app and the network
- Run a Lighthouse PWA audit and read its report to find what is missing
- Apply progressive-enhancement best practices so the app works for every user
Estimated Time: 55 minutes
Project: Write a complete web app manifest and sketch the installability checklist for a demo app.
In This Lesson
What Is a PWA?
A Progressive Web App (PWA) is a web app — built with the same HTML, CSS, and JavaScript you already know — that uses modern browser capabilities to deliver an experience close to a native mobile or desktop app. It can be installed to a device, run offline, and feel like a real app: full-screen, with its own icon, its own launch splash, and no browser address bar.
The word "progressive" is the key. A PWA is built with progressive enhancement: the core experience works in any browser, and each modern capability the browser supports layers on extra polish. An older browser that has never heard of a service worker still gets a perfectly functional website; a modern browser gets the installable, offline-capable app on top.
📖 Not a framework, not an app store
A PWA is not a library you install or a special file format. It is a set of practices and browser APIs applied to an ordinary website. There is no PWA compiler and no PWA app store — the "install" happens straight from the browser, and updates ship the moment you deploy, with no review queue.
Why they matter
PWAs bridge a real gap. Native apps are fast and installable but cost a lot to build twice (iOS and Android), must pass store review, and require users to commit to a download. Websites reach everyone instantly by URL but historically broke the moment the network did. PWAs give you one codebase that reaches every platform through a link and earns a home-screen icon:
| Traditional website | Native app | PWA | |
|---|---|---|---|
| Works offline | ❌ | ✅ | ✅ |
| Installable icon | ❌ | ✅ | ✅ |
| Reachable by URL | ✅ | ❌ | ✅ |
| No app-store review | ✅ | ❌ | ✅ |
| One codebase, every platform | ✅ | ❌ | ✅ |
The Three Qualities
Google's original framing describes a great PWA with three adjectives. They are worth memorizing because every technical decision you'll make maps back to one of them.
🛡️ Reliable
The app loads and stays usable regardless of network conditions — a strong signal, a flaky one, or none at all. It never shows the browser's dreaded "no internet" dinosaur. Reliability is delivered by the service worker caching the app's shell so a repeat visit works even with the radio off.
⚡ Fast
The app responds to interactions quickly and animates smoothly. Users abandon slow pages; research consistently shows conversions drop as load time climbs. A PWA gets its speed by serving cached assets instantly instead of re-downloading them on every visit.
✨ Engaging
The app feels like a natural part of the device. Once installed it launches from the home screen in its own window — no address bar, its own icon, a themed status bar — and can re-engage users through push notifications. This "app-like" feel comes from the web app manifest.
The Three Technical Pillars
Those three qualities rest on three concrete, non-negotiable technical requirements. If any one is missing, you do not have a PWA — the browser will not offer to install it.
secure origin"] A --> C["Web App Manifest
manifest.json"] A --> D["Service Worker
service-worker.js"] B --> E["Encrypts traffic & unlocks modern APIs"] C --> F["Metadata for install & app-like launch"] D --> G["Caching, offline, background tasks"]
1. HTTPS — a secure origin
A PWA must be served over HTTPS (the one exception is localhost during development). Two reasons: a service worker is a powerful man-in-the-middle over your network traffic, so the browser only allows it on a connection that itself cannot be tampered with; and many of the modern APIs a PWA relies on are gated behind a "secure context." Free certificates from Let's Encrypt, and automatic HTTPS from hosts like Netlify or Vercel, make this a solved problem.
2. Web App Manifest — the identity card
The manifest is a small JSON file that tells the browser who your app is: its name, its icons, what color to paint the toolbar, and how it should launch. Without it, the browser has no icon to put on the home screen and no name to show. We build one in full in the next section.
3. Service Worker — the engine
The service worker is a JavaScript file that runs in a separate background thread, has no access to the DOM, and acts as a programmable network proxy sitting between your pages and the network. It is what makes offline possible. Think of it as a receptionist stationed between your app and the internet:
The Web App Manifest
The manifest is a JSON file — conventionally named manifest.json or manifest.webmanifest — that you link from the <head> of every page. Here is a complete, realistic example with each member explained.
{
"name": "Weather Now",
"short_name": "Weather",
"description": "Fast, offline-capable local weather forecasts.",
"start_url": "/?source=pwa",
"scope": "/",
"display": "standalone",
"orientation": "portrait",
"background_color": "#0f172a",
"theme_color": "#3b82f6",
"icons": [
{
"src": "/icons/icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/icons/icon-512.png",
"sizes": "512x512",
"type": "image/png"
},
{
"src": "/icons/icon-maskable.png",
"sizes": "512x512",
"type": "image/png",
"purpose": "maskable"
}
]
}
Link it in your HTML <head>, and hint the theme color for browsers that read it before the manifest loads:
<link rel="manifest" href="/manifest.json">
<meta name="theme-color" content="#3b82f6">
The members that matter
| Member | Required? | What it does |
|---|---|---|
name | ✅ | Full app name, shown on the install prompt and splash screen |
short_name | Recommended | Short label used under the home-screen icon where space is tight |
start_url | ✅ | The URL that opens when the app is launched from its icon |
icons | ✅ | Home-screen and splash images; needs at least a 192px and a 512px PNG |
display | Recommended | How it launches: standalone, fullscreen, minimal-ui, or browser |
theme_color | Recommended | Color of the toolbar / status bar in the installed app |
background_color | Recommended | Splash-screen background shown while the app boots |
scope | Optional | The set of URLs considered "inside" the app |
💡 What "display: standalone" buys you
With "display": "standalone", the installed app opens in its own window with no browser address bar or tabs — the single change that most makes a website feel like a native app. Use fullscreen for immersive games, and minimal-ui when you still want minimal navigation controls.
📖 Maskable icons
Android may crop your icon into a circle, squircle, or rounded square. An icon marked "purpose": "maskable" includes a safe padding zone so nothing important gets clipped. Provide one alongside your standard icons to avoid an awkwardly cropped logo.
Installability & Lighthouse
The browser will only offer to install your app — or fire the beforeinstallprompt event — when a specific checklist is satisfied. These are the installability criteria:
- Served over HTTPS (or
localhost) - Has a linked web app manifest with
name/short_name, a validstart_url, adisplayofstandalone/fullscreen/minimal-ui, and icons including at least 192px and 512px - Registers a service worker with a
fetchhandler (so the app can respond when offline) - The user has shown some engagement with the page
Auditing with Lighthouse
Lighthouse is an automated auditing tool built into Chrome DevTools (open DevTools → Lighthouse tab) and available as a CLI. It scores Performance, Accessibility, Best Practices, SEO, and runs PWA-specific checks — telling you exactly which installability requirement is missing and why.
Example Lighthouse PWA findings
✔ Registers a service worker that controls page and start_url
✔ Web app manifest and service worker meet the installability requirements
✖ Does not provide a valid apple-touch-icon
✖ Manifest doesn't have a maskable icon
Treat a red mark as a to-do item, not a failure. Lighthouse turns "is this a real PWA?" from an opinion into a checklist you can drive to green.
Best Practices & Pitfalls
✅ Do
- Build with progressive enhancement — make the core content and features work without a service worker, then layer PWA capabilities on top
- Serve everything over HTTPS from the start
- Provide 192px and 512px icons, plus a maskable variant, so installs look sharp everywhere
- Give
start_urla tracking parameter (e.g.?source=pwa) so analytics can measure launches from the installed app - Run Lighthouse regularly and keep the PWA checks green
❌ Don't
- Don't treat "PWA" as a checkbox — a fast, reliable, well-designed app matters more than passing an audit
- Don't make offline support an afterthought bolted on at the end; design for intermittent connectivity from the start
- Don't forget the
<meta name="theme-color">tag; without it the toolbar color can look inconsistent - Don't assume every browser supports every API — always feature-detect (
if ('serviceWorker' in navigator)) before using it
⚠️ HTTPS is not optional
A service worker registration silently fails on plain http:// (except localhost). If your offline features "just don't work" in production, the first thing to check is that the site is genuinely served over HTTPS — including every asset it loads.
Practice & Quiz
🏋️ Exercise 1: Write a valid manifest
Goal: Author a manifest.json for a note-taking app called "QuickNotes" that will pass the installability check. It must launch standalone, use a blue theme, and include the two required icon sizes.
💡 Hint
The installability minimum is: name (and/or short_name), a valid start_url, a display of standalone, and an icons array containing at least a 192×192 and a 512×512 PNG.
✅ Solution
{
"name": "QuickNotes",
"short_name": "QuickNotes",
"start_url": "/?source=pwa",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#2563eb",
"icons": [
{ "src": "/icons/note-192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/icons/note-512.png", "sizes": "512x512", "type": "image/png" }
]
}
🏋️ Exercise 2: Read a Lighthouse report
Goal: A colleague says "the install button never appears." Lighthouse shows: HTTPS ✔, manifest ✔ with valid icons, but "Does not register a service worker that controls page and start_url" ✖. Which of the three pillars is missing, and what must you add?
✅ Solution
The service worker pillar is missing. HTTPS and the manifest are both present, but the browser will not offer installation until a service worker with a fetch handler is registered and controlling the start_url. Adding and registering service-worker.js (the topic of the next lesson) turns the check green and enables the install prompt.
🎯 Quick Quiz
Question 1: Which three technical pillars must a PWA have?
Question 2: On which origin is a service worker allowed to run without HTTPS?
Question 3: What does "display": "standalone" in the manifest do?
Summary
🎉 Key Takeaways
- A PWA is an ordinary web app enhanced to be installable, offline-capable, and app-like — no framework or app store required
- Great PWAs are reliable, fast, and engaging; every technique serves one of those goals
- Every PWA rests on three pillars: HTTPS, a web app manifest, and a service worker
- The manifest supplies name, icons,
start_url,display, andtheme_color; at minimum you need 192px and 512px icons - The service worker is a proxy that sits between the app and the network, and it is what unlocks the install prompt
- Lighthouse audits installability and tells you exactly what is missing
📚 Additional Resources
- web.dev — Progressive Web Apps
- MDN — Progressive web apps
- MDN — Web app manifest reference
- Chrome Developers — Lighthouse overview
🚀 What's Next?
You now know what makes a PWA and which pieces it needs. The engine that delivers reliability and offline support is the service worker — so the next lesson gets hands-on: Service Workers Setup, where you'll register one, walk through its install → activate → fetch lifecycle, and implement your first caching strategies.
🎉 Well done!
You can now explain a PWA to anyone and write a manifest that passes the install check. Time to build the engine that powers it.