Progressive Web App (PWA)
Loquent ships as a Progressive Web App. Users can install it to their home screen on Android and iOS, and get a standalone app experience without browser chrome.
What’s Included
Section titled “What’s Included”The PWA implementation adds four components:
- Web app manifest — defines app identity, icons, and display mode
- Service worker — caches assets with routing-aware strategies
- Offline fallback page — shown when the network is unavailable
- HTML meta tags — configure theme color, viewport, and iOS integration
Web App Manifest
Section titled “Web App Manifest”The manifest at public/manifest.json tells the browser how to install and display the app:
{ "name": "Loquent", "short_name": "Loquent", "display": "standalone", "theme_color": "#f59e0b", "background_color": "#fafafa", "start_url": "/", "scope": "/", "icons": [ { "src": "/icons/icon-192x192.png", "sizes": "192x192", "type": "image/png" }, { "src": "/icons/icon-512x512.png", "sizes": "512x512", "type": "image/png" }, { "src": "/icons/icon-512x512.png", "sizes": "512x512", "type": "image/png", "purpose": "maskable" } ]}Setting display to standalone removes browser chrome (address bar, tabs) when the app is launched from the home screen.
Service Worker Caching
Section titled “Service Worker Caching”The service worker at public/sw.js intercepts all GET requests and applies different caching strategies based on the request type:
| Request Pattern | Strategy | Why |
|---|---|---|
/api/* | Network-only | API data is authenticated and dynamic |
/auth/*, /login, /signup | Network-first | Auth must be fresh, cache as fallback |
Hashed assets (-[hash].js/wasm/css) | Cache-first | Content-hashed files are immutable |
| Static assets (images, fonts) | Stale-while-revalidate | Instant response, silent background update |
| Navigation requests | Network-first + offline fallback | Falls back to /offline.html |
Cache Versioning
Section titled “Cache Versioning”Caches are namespaced with a version prefix:
var CACHE_VERSION = "v1.0.0";var STATIC_CACHE = CACHE_VERSION + "::static";var PAGES_CACHE = CACHE_VERSION + "::pages";When you bump CACHE_VERSION, the service worker’s activate event deletes all caches from previous versions automatically.
Service Worker Registration
Section titled “Service Worker Registration”The service worker registers via an inline script in src/bases/client/client_app.rs:
const SW_REGISTER_SCRIPT: &str = r#"if("serviceWorker"in navigator){ navigator.serviceWorker.register("/sw.js",{scope:"/"}) .catch(function(e){console.warn("SW registration failed:",e)})}"#;This follows the same pattern as THEME_INIT_SCRIPT — inline JavaScript rendered in the HTML head.
Offline Fallback
Section titled “Offline Fallback”When a navigation request fails (no network and no cache), the service worker serves public/offline.html. This page:
- Displays a “You’re offline” message with a retry button
- Supports dark and light mode via
prefers-color-scheme - Uses Loquent’s amber accent (
#f59e0b) for branding - Is self-contained — no external dependencies
HTML Meta Tags
Section titled “HTML Meta Tags”Five meta tags in client_app.rs handle mobile integration:
Meta { name: "viewport", content: "width=device-width, initial-scale=1, viewport-fit=cover" }Meta { name: "theme-color", content: "#f59e0b" }Meta { name: "apple-mobile-web-app-capable", content: "yes" }Meta { name: "apple-mobile-web-app-status-bar-style", content: "default" }Meta { name: "apple-mobile-web-app-title", content: "Loquent" }The viewport-fit=cover value ensures the app fills the screen on devices with notches.
Dioxus Configuration
Section titled “Dioxus Configuration”Two changes in Dioxus.toml make PWA assets available:
[application]asset_dir = "public"
[web.watcher]watch_path = ["src", "public"]Without asset_dir = "public", the manifest, service worker, and icons would 404.
The icon set lives in public/icons/:
| File | Size | Use |
|---|---|---|
icon.svg | Source | Amber gradient with white “L” lettermark |
icon-192x192.png | 192×192 | Android home screen |
icon-512x512.png | 512×512 | Android splash screen, high-DPI |
apple-touch-icon.png | 180×180 | iOS home screen |
Testing Locally
Section titled “Testing Locally”- Run
dx serveand open Chrome DevTools - Go to Application → Manifest — verify app name, display mode, and icons
- Go to Application → Service Workers — confirm
sw.jsis registered - Check Application → Cache Storage —
v1.0.0::staticshould containoffline.html - Toggle Offline in the Service Workers panel, then navigate — the offline page should appear