CWA vs PWA

Understanding the differences between Containerized Web Apps and Progressive Web Apps, and when to use each.

Overview

PWAs and CWAs are complementary technologies. Both use standard HTML, CSS, and JavaScript. PWAs run in the browser with progressive enhancement. CWAs run inside a native container that renders content using the platform's built-in WebView component (WKWebView / WebKit on iOS, Android WebView on Android) — the same rendering engines used by Safari and Chrome. The CWA container adds a permission-gated JavaScript bridge for native device APIs, while the content itself remains standard web content within the WebView sandbox. The same codebase can serve both — detect the bridge at runtime and unlock extra features.

Side-by-Side Comparison

FeaturePWACWA
Rendering Engine Browser engine (varies) Platform WebView (WKWebView/WebKit on iOS, Android WebView on Android)
Content Type HTML / CSS / JS HTML / CSS / JS only (no native code)
Distribution Browser install prompt / URL LoadSites container app
App Discovery URL or app store listing Enter domain in LoadSites
Installation Service Worker + manifest.json loadsites.app.manifest + ZIP bundle
Camera MediaDevices API (limited) Full native camera + gallery
Biometrics WebAuthn (limited) Face ID / Touch ID / fingerprint
Haptics Vibration API (basic) Impact, notification, custom duration
Push Notifications Web Push API (free, browser-managed) LoadSites Cloud relay (requires license)
Geolocation Geolocation API Native GPS with watch
Share Web Share API (some browsers) Native share sheet (all platforms)
Clipboard Clipboard API (with permission) Read/write clipboard
Offline Support Service Worker cache Entire app bundled locally as ZIP
Updates Service Worker lifecycle Manifest version check + ZIP swap
Storage IndexedDB, localStorage Bridge storage (native, persistent, scoped)
Multi-App per Domain One PWA per scope Multiple apps via manifest apps[]
Sandboxing Browser same-origin policy Domain + appId scoped storage + permissions
Bundle Size No limit (fetched on demand) 50 MB max ZIP
Network Info Network Information API (limited) Real-time status + type changes
Device Info Navigator API (limited) Platform, model, OS version

When to Use CWA

CWA is the better choice when your app needs:

When to Use PWA

PWA is the better choice when:

Can You Use Both?

Yes. A single web app can be both a PWA and a CWA simultaneously. Detect the container at runtime and progressively enhance:

if (window.LoadSites) {
  // Running inside CWA container — use native APIs
  LoadSites.haptics.impact('medium');
  LoadSites.camera.takePhoto().then(handlePhoto);
} else if ('serviceWorker' in navigator) {
  // Running as PWA — use Web APIs
  navigator.vibrate(100);
  navigator.mediaDevices.getUserMedia({ video: true }).then(handleStream);
}

This pattern lets you maintain a single codebase that delivers the best experience on each platform. PWA users get a functional app, CWA users get enhanced native features.

Platform Compliance

Unlike PWAs, CWA apps are distributed through a native container app (LoadSites) available on the Apple App Store and Google Play. LoadSites complies with platform guidelines by rendering all CWA content exclusively through the system's native WebView (WKWebView / WebKit on iOS, as required by Apple Guideline 2.5.6). CWA bundles contain only static web assets (HTML, CSS, JavaScript, images, fonts). No native executable code, bytecode, or binaries are downloaded or executed. The bridge API is permission-gated, sandboxed, and does not expose raw platform APIs to loaded content.

See Compliance & Security for full details on Apple App Store and Google Play policy alignment.

Migrating a PWA to CWA

  1. Keep your PWA — No need to remove your manifest.json or service worker. CWA works alongside PWA.
  2. Create a CWA manifest — Add loadsites.app.manifest to your domain root. See Manifest Spec.
  3. Bundle your build output — ZIP your dist/ or build/ folder and host it.
  4. Add bridge detection — Check for window.LoadSites and use native APIs where available.
  5. Test in LoadSites — Enter your domain in the LoadSites app and verify everything works.