lunx.docs
DocsPluginsplugin-pwa

@lunx/plugin-pwa

Zero-config Progressive Web App support. Generates a service worker, web app manifest, and offline cache strategy — making your Lunx app installable and offline-capable.

Installation

bash
npm install --save-dev @lunx/plugin-pwa
typescriptlunx.config.ts
import { defineConfig } from 'lunx'
import pwa from '@lunx/plugin-pwa'

export default defineConfig({
  framework: 'react',
  plugins: [
    pwa({
      name:            'My Lunx App',
      shortName:       'LunxApp',
      description:     'A blazing-fast application built with Lunx',
      themeColor:      '#2563eb',
      backgroundColor: '#ffffff',
      display:         'standalone',
      icons: [
        { src: '/icons/pwa-192x192.png', sizes: '192x192', type: 'image/png' },
        { src: '/icons/pwa-512x512.png', sizes: '512x512', type: 'image/png' },
        { src: '/icons/pwa-512x512.png', sizes: '512x512', type: 'image/png', purpose: 'maskable' },
      ],
    }),
  ],
})

What gets generated

After running lunx build, the plugin generates:

text
dist/
├── sw.js                    # Service worker (auto-registered)
├── manifest.webmanifest     # Web app manifest
├── icons/
   ├── pwa-192x192.png
   └── pwa-512x512.png
└── index.html               # Updated with manifest and meta tags

Caching strategies

Configure how different resource types are cached. The plugin supports four strategies inspired by Workbox — implemented natively without the Workbox dependency.

typescriptlunx.config.ts
pwa({
  name: 'My App',
  workbox: {
    // App shell — cache-first for instant loads
    navigateFallback: '/index.html',
    navigateFallbackDenylist: [/^\/api\//],

    // Runtime caching rules (applied in order)
    runtimeCaching: [
      {
        // API requests — network-first with 5s timeout
        urlPattern: /^\/api\//,
        handler: 'NetworkFirst',
        options: {
          cacheName: 'api-cache',
          networkTimeoutSeconds: 5,
          expiration: { maxEntries: 50, maxAgeSeconds: 300 },
        },
      },
      {
        // Images — cache-first, serve stale
        urlPattern: /\.(?:png|jpg|jpeg|svg|gif|webp)$/,
        handler: 'CacheFirst',
        options: {
          cacheName: 'image-cache',
          expiration: { maxEntries: 100, maxAgeSeconds: 30 * 24 * 60 * 60 },
        },
      },
      {
        // Google Fonts — stale-while-revalidate
        urlPattern: /^https:\/\/fonts\.googleapis\.com/,
        handler: 'StaleWhileRevalidate',
        options: { cacheName: 'google-fonts' },
      },
    ],
  },
})

Verifying PWA compliance

bash
# Build and preview
lunx build && lunx preview

# Open Chrome DevTools → Application → Service Workers
# Confirm: sw.js is registered and status is "activated"

# Run Lighthouse audit for PWA score
npx lighthouse http://localhost:4173 --only-categories=pwa --view

Plugin options

FieldTypeDefaultDescription
namestringFull app name shown in OS install prompts and splash screens.
shortNamestringShort app name (≤12 chars) for home screen icons.
themeColorstringBrowser chrome color and mobile status bar color.
backgroundColorstring'#ffffff'Splash screen background color before the app loads.
displaystring'standalone'Display mode: standalone | fullscreen | minimal-ui | browser.
iconsIcon[]Array of icon objects with src, sizes, type, and optional purpose ('maskable').
workboxWorkboxOptionsFine-grained caching strategy configuration.
injectRegisterstring'auto'Service worker registration method: auto | script | inline | null.
Maskable icons
Always provide a maskable icon variant. Android adaptive icons crop the icon to various shapes — without a maskable variant, the standard icon will be padded with white space, making it look broken on some Android launchers.