"""
HearthNet PWA Enhancement
Adds Progressive Web App support to the Gradio UI:
- Service worker for offline caching
- Web app manifest for installability
- Push notifications support
"""
from pathlib import Path
from fastapi import FastAPI
from fastapi.responses import FileResponse
def setup_pwa(app: FastAPI, static_dir: Path) -> None:
"""
Set up PWA support for HearthNet Gradio UI.
Args:
app: FastAPI application instance
static_dir: Directory where PWA files are served from
"""
# Serve manifest.json
@app.get("/manifest.json")
async def get_manifest():
manifest_path = Path(__file__).parent / "manifest.json"
if manifest_path.exists():
return FileResponse(manifest_path, media_type="application/manifest+json")
# Fallback manifest
return {
"name": "HearthNet",
"short_name": "HearthNet",
"description": "Local-first community AI mesh",
"start_url": "/",
"display": "standalone",
"theme_color": "#1e40af",
"background_color": "#ffffff",
"icons": [
{
"src": "/static/icon-192.png",
"sizes": "192x192",
"type": "image/png",
}
],
}
# Serve service worker
@app.get("/sw.js")
async def get_service_worker():
sw_path = Path(__file__).parent / "sw.js"
if sw_path.exists():
return FileResponse(sw_path, media_type="application/javascript")
return {"error": "Service worker not found"}
# Inject PWA meta tags into HTML
@app.middleware("http")
async def inject_pwa_headers(request, call_next):
response = await call_next(request)
# Only modify HTML responses
if "text/html" in response.headers.get("content-type", ""):
# Read body
body = b""
async for chunk in response.body_iterator:
body += chunk
# Inject PWA tags
pwa_tags = """
"""
# Insert before
if b"" in body:
body = body.replace(b"", pwa_tags.encode() + b"", 1)
# Create new response with modified content
from starlette.responses import Response as StarletteResponse
response = StarletteResponse(
content=body,
status_code=response.status_code,
headers=dict(response.headers),
media_type=response.media_type,
)
return response
print("✅ PWA support enabled")
print(" - Manifest: /manifest.json")
print(" - Service Worker: /sw.js")
print(" - Installable from mobile browsers")
__all__ = ["setup_pwa"]