Building PWAs with Faststrap
Faststrap provides a production-safe PWA baseline through add_pwa():
- Manifest generation (
/manifest.json) - Service worker route (
/sw.js) - Automatic service worker registration
- Offline fallback route (
/offline) - Runtime caching for better resilience
Accessibility note:
- Faststrap keeps mobile zoom enabled by default (width=device-width, initial-scale=1).
Quick Start
from fasthtml.common import FastHTML
from faststrap import add_bootstrap, add_pwa
app = FastHTML()
add_bootstrap(app)
add_pwa(
app,
name="My App",
short_name="MyApp",
theme_color="#0d6efd",
icon_path="/assets/icon.png",
)
Icon note:
- Use a square PNG icon for icon_path when you want reliable install behavior across iOS and Chromium browsers.
- PwaMeta() and add_pwa() share the same default icon path, /assets/icon.png, so direct meta usage and manifest generation stay aligned.
What add_pwa() Configures
- Injects required PWA/mobile meta tags.
- Serves a generated
manifest.json. - Serves a robust service worker script at
/sw.js. - Injects service worker registration code into app headers.
- Serves
/offlinepage (enabled by default). - Respects
scopefor scoped deployments (for example/myapp/sw.js).
Default Offline/Caching Strategy
The built-in service worker uses:
- Install: tolerant pre-cache (
Promise.allSettled) so one failed URL does not break install. - Navigation requests: network-first with cache fallback, then
/offline. - Static assets (
css,js,images, fonts): stale-while-revalidate. - Other GET requests: network-first with runtime cache write-through.
This is a practical baseline for production apps that need reliable offline fallback behavior.
Advanced Configuration
add_pwa() now supports cache controls:
add_pwa(
app,
cache_name="myapp-cache",
cache_version="v2026-02-23",
pre_cache_urls=(
"/health",
"/assets/logo.png",
),
)
cache_name: prefix for cache storagecache_version: version suffix for cache invalidation on deploypre_cache_urls: additional URLs to pre-cache
Faststrap still pre-caches its core defaults and /offline.
Background Sync Foundation (Opt-in)
Faststrap includes a lightweight background sync scaffold that you can enable without committing to a queue implementation yet:
enable_background_sync: enables service workersyncevent hooksbackground_sync_tag: tag used when registering sync tasks
This is intentionally a foundation layer for v0.6.x work; request queue persistence/replay is still application-defined.
Route-Aware Cache Policies (Opt-in)
You can define route prefix policies in the generated service worker:
add_pwa(
app,
route_cache_policies={
"/api/public/": "stale-while-revalidate",
"/assets/": "cache-first",
},
)
Supported strategies:
network-firststale-while-revalidatecache-first
Push Foundation (Opt-in)
Enable push event scaffolding in the generated service worker:
This adds push and notificationclick handlers with safe defaults.
When to Use a Custom Service Worker
Use a custom sw.js when you need:
- fine-grained API caching rules
- background sync
- push notifications
- per-route cache policies
In that case:
- pass
service_worker=Falsetoadd_pwa() - mount your own
/sw.jsroute
Mobile Components
Faststrap also includes mobile-oriented UI components:
BottomNav,BottomNavItemSheetInstallPrompt
API Reference
faststrap.pwa.core.PwaMeta(name=None, short_name=None, theme_color='#ffffff', background_color='#ffffff', description=None, icon_path=_DEFAULT_ICON_PATH, icon_192=None, icon_512=None, manifest_path='/manifest.json')
Generate PWA meta tags and link elements.
These tags are essential for: - Installing the app on mobile home screens - Setting the theme color of the browser bar - Defining icons for different platforms (iOS/Android)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str | None
|
Full name of the application |
None
|
short_name
|
str | None
|
Short name for home screen (12 chars max recommended) |
None
|
theme_color
|
str
|
Color of the browser toolbar |
'#ffffff'
|
background_color
|
str
|
Background color for splash screen |
'#ffffff'
|
description
|
str | None
|
Description of the app |
None
|
icon_path
|
str
|
Path to the main icon (should be square, ideally 512x512) |
_DEFAULT_ICON_PATH
|
icon_192
|
str | None
|
Optional dedicated 192x192 icon path |
None
|
icon_512
|
str | None
|
Optional dedicated 512x512 icon path |
None
|
manifest_path
|
str
|
URL path to the manifest file |
'/manifest.json'
|
Returns:
| Type | Description |
|---|---|
tuple[Any, ...]
|
Tuple of FastHTML Meta and Link elements |
Source code in src/faststrap/pwa/core.py
faststrap.pwa.core.add_pwa(app, name='Faststrap App', short_name='Faststrap', description='A Progressive Web App built with Faststrap', theme_color='#ffffff', background_color='#ffffff', icon_path=_DEFAULT_ICON_PATH, icon_192=None, icon_512=None, display='standalone', start_url='/', scope='/', service_worker=True, offline_page=True, cache_name='faststrap-app', cache_version='v1', pre_cache_urls=None, use_cdn=None, enable_background_sync=False, background_sync_tag='faststrap-background-sync', route_cache_policies=None, enable_push=False, default_push_title='Faststrap Notification')
Enable PWA capabilities for the FastHTML app.
This helper:
1. Injects PWA meta tags into app headers
2. Serves a generated manifest.json
3. Serves a standard sw.js Service Worker (if enabled)
4. serves an /offline route (if enabled)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
app
|
Any
|
FastHTML application instance |
required |
name
|
str
|
App name |
'Faststrap App'
|
short_name
|
str
|
App short name |
'Faststrap'
|
description
|
str
|
App description |
'A Progressive Web App built with Faststrap'
|
theme_color
|
str
|
Theme color |
'#ffffff'
|
background_color
|
str
|
Splash screen background color |
'#ffffff'
|
icon_path
|
str
|
Path to icon file |
_DEFAULT_ICON_PATH
|
icon_192
|
str | None
|
Optional dedicated 192x192 icon path for the manifest and touch icon |
None
|
icon_512
|
str | None
|
Optional dedicated 512x512 icon path for the manifest/tile icon |
None
|
display
|
str
|
Display mode (standalone, fullscreen, minimal-ui, browser) |
'standalone'
|
start_url
|
str
|
URL to open on launch |
'/'
|
scope
|
str
|
Scope of the PWA |
'/'
|
service_worker
|
bool
|
Enable automatic Service Worker |
True
|
offline_page
|
bool
|
Enable automatic /offline route |
True
|
cache_name
|
str
|
Service worker cache name prefix |
'faststrap-app'
|
cache_version
|
str
|
Cache version suffix used for cache invalidation |
'v1'
|
pre_cache_urls
|
Sequence[str] | None
|
Optional extra URLs to precache (in addition to defaults) |
None
|
use_cdn
|
bool | None
|
Force CDN-aware precache defaults; when omitted this is auto-detected |
None
|
enable_background_sync
|
bool
|
Enable Background Sync foundation hooks |
False
|
background_sync_tag
|
str
|
Tag used for Background Sync registrations |
'faststrap-background-sync'
|
route_cache_policies
|
dict[str, str] | None
|
Optional route prefix -> strategy mapping values: "network-first", "stale-while-revalidate", "cache-first" |
None
|
enable_push
|
bool
|
Enable push notification service worker handlers |
False
|
default_push_title
|
str
|
Fallback push notification title |
'Faststrap Notification'
|
Source code in src/faststrap/pwa/core.py
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 | |