webapp-astro-pwa
Version:
A ready-to-use Astro component library for adding Progressive Web App (PWA) support to your Astro projects. This package provides drop-in components and utilities for manifest injection, service worker registration, install prompts, and more. Includes a w
822 lines (633 loc) β’ 23.6 kB
Markdown
# WebApp Astro PWA
A ready-to-use Astro component library for adding Progressive Web App (PWA) support to your Astro projects. This package provides drop-in components and utilities for manifest injection, service worker registration, install prompts, and more. Includes a web push management panel seamlessly integrated with Firebase. Fully support Astro 5
## π¦ Supercharge Your Astro App with PWA!
Boost your Astro projectβs performance and user experience by enabling Progressive Web App (PWA) features. With WebApp Astro PWA, your site loads faster, works offline, and can be installed directly to usersβ devicesβjust like a native app.
- **Faster Load Times:** Assets are cached for instant loading, even on slow or unreliable networks.
- **Offline Support:** Your app remains accessible and functional without an internet connection.
- **Installable Experience:** Users can add your app to their home screen for quick access, increasing engagement and retention.
- **Native-like Feel:** Deliver a seamless, app-like experience with push notifications, background sync, and more.
**Empower your Astro project with PWA capabilities and stand out with a modern, high-performance web app!**
## β¨ Features
- **Easy PWA Integration**: Add PWA support to any Astro project with minimal setup.
- **Customizable Install UI**: Includes install button, popover, and installation messages.
- **Manifest & Meta Tags**: Auto-injects manifest and meta tags from config.
- **Service Worker**: Bundles and registers a Workbox-powered service worker.
- **Configurable Strategies**: Choose caching strategies and assets via `pwa.config.json`.
- **TypeScript Support**: Fully typed for safer integration.
## π Project Structure
Your project will include the following files and folders:
```text
/
βββ index.ts
βββ src/
β βββ PWA.astro
β βββ PWABtn.astro
β βββ PWASetupWindow.astro
β βββ types.ts
β βββ manifest_imgs/
β βββ Firebase.astro
β βββ LoginPanel.astro
β βββ NotificationBtn.astro
β βββ SendPushPage.astro
β βββ firebaseConfig.ts
β βββ firebaseUtils.ts
β βββ PushApiPage.ts
β βββ pwa/
β βββ bundle-sw.mjs
β βββ index.ts
β βββ PoweredWebAppBuilder.ts
β βββ setup.js
β βββ sw.js
β βββ utilities.ts
β βββ workbox.config.cjs
β βββ view/
β βββ PopoverSupport.ts
β βββ js
β β βββ popover.min.js
β β βββ popover.min.js.map
β βββ components/
β β βββ InstallationMessage.astro
β β βββ InstallationPage.astro
β β βββ InstallBtn.astro
β β βββ MetaServiceWorker.astro
β β βββ ServiceWorkerRegistration.astro
β βββ utils/
β βββ EventHandler.ts
β βββ PWAInstallPrompt.ts
β βββ PWASetup.ts
β βββ SWUtils.ts
β βββ utilities.ts
βββ pwa.config.json
βββ package.json
βββ setup.js
βββ README.md
```
## π οΈ Installation
```sh
npm install webapp-astro-pwa
```
After install, the setup script will automatically add a `generateAndBundleSW` script to your project's `package.json`.
## β‘ BASIC Usage
### Enable Web App possibilities and features across your entire Astro app
To enable PWA features across your entire Astro app, import the `PWA` component and place it inside your main layoutβs `<head>` section. This will inject the manifest, meta tags, and register the service worker automatically.
```astro
// new code added
import { PWA } from "webapp-astro-pwa";
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="generator" content={Astro.generator} />
<title>Astro Basics</title>
<!-- new code added -->
<PWA />
</head>
```
Next Open your `astro.config.mjs` (or `astro.config.ts`) at your astro project and add the following
```js
// filepath: astro.config.mjs
import { defineConfig } from "astro/config";
// new code added
import PoweredWebAppBuilder from "webapp-astro-pwa/pwa";
export default defineConfig({
integrations: [
// new code added
PoweredWebAppBuilder({}),
...
],
});
```
Next, build your application using the command:
```sh
npm run dev
```
This will generate the service worker file at
/
βββ src/
βββ ap/
βββ sw.js
enabling your app to function as a web app with offline capabilities (even if itβs not yet installable as a PWA still you don't have manifest file). By default, files will be stored in the browserβs Cache Storage under the name static-assets. You can change this name in the configuration to manage cache versions and control how assets are cached and updated. This approach gives you flexibility and full control over your appβs offline experience.
```js
// filepath: astro.config.mjs
import { defineConfig } from 'astro/config';
// new code added
import PoweredWebAppBuilder from "webapp-astro-pwa/pwa";
export default defineConfig({
integrations: [
// this line changed
PoweredWebAppBuilder({
"cacheAssets": "static-assets_v2",
}),
...
]
});
```
## 𧨠Usage AS PWA
**Important:**
When your application is running as a PWA, you may sometimes need to remove and re-add the service worker file (`sw.js`) for changes to take effect. Browsers aggressively cache service workers, so after making updates to your service worker or its configuration, clear the old service worker or unregister it to ensure users receive the latest version.
Force update of service worker file default `false`
```js
// filepath: astro.config.mjs
import { defineConfig } from 'astro/config';
import PoweredWebAppBuilder from "webapp-astro-pwa/pwa";
export default defineConfig({
integrations: [
PoweredWebAppBuilder({
// this line changed
"forceUpdate": true,
}),
...
]
});
```
### β‘οΈ External Options
#### Choose Strategy
You can also choose a file fetching strategy for your PWA. Available options are: `CacheFirst`, `CacheOnly`, `NetworkFirst`, `NetworkOnly`, and `StaleWhileRevalidate` (the default is `StaleWhileRevalidate`).
For more details about these strategies, see the [Workbox documentation](https://developer.chrome.com/docs/workbox/modules/workbox-strategies).
```js
// filepath: astro.config.mjs
import { defineConfig } from 'astro/config';
import PoweredWebAppBuilder from "webapp-astro-pwa/pwa";
export default defineConfig({
integrations: [
// this line changed
PoweredWebAppBuilder({
"strategy": "CacheFirst",
}),
...
]
});
```
#### Enable Workbox logs
- `"disableDevLogs": true` β enables or disables Workbox logs in the console. Set to `true` to turn off Workbox logging, or `false` to see Workbox logs during development. Default `true`
```js
// filepath: astro.config.mjs
import { defineConfig } from 'astro/config';
import PoweredWebAppBuilder from "webapp-astro-pwa/pwa";
export default defineConfig({
integrations: [
// this line changed
PoweredWebAppBuilder({
"disableDevLogs": false,
}),
...
]
});
```
#### Adding Custom Scripts to the Service Worker
You can extend your service worker with additional custom scripts using the `scripts` option in your `astro.config.mjs` (or `astro.config.ts`). This allows you to modularize your service worker logicβfor example, to add push notifications, analytics, or custom caching strategiesβby importing extra files via `importScripts`.
##### How to Use
Add a `scripts` array to your `PoweredWebAppBuilder` configuration. Each entry should be a path (relative to your project root or `public/`) to a JavaScript file you want to include in the service worker.
```js
// filepath: astro.config.mjs
import { defineConfig } from "astro/config";
import PoweredWebAppBuilder from "webapp-astro-pwa/pwa";
export default defineConfig({
integrations: [
PoweredWebAppBuilder({
// ...other options...
scripts: [
"http://example.com/src/assets/js.js/custom-sw-script.js",
"http://example.com/src/assets/js.js/analytics-sw.js",
],
}),
],
});
```
All scripts listed will be injected at the top of your generated `sw.js` using `importScripts`:
```js
// In the generated sw.js
importScripts(
"http://example.com/src/assets/js.js/custom-sw-script.js",
"http://example.com/src/assets/js.js/analytics-sw.js"
);
// ...rest of the service worker code...
```
**Tip:**
Use this feature to keep your service worker code clean and maintainable by splitting advanced logic into separate files.
### π£ Minimal Requirements for PWA in Astro
To make your Astro project installable as a Progressive Web App (PWA) and automatically generate a manifest file during build, update your `astro.config.mjs` (or `astro.config.ts`) as follows:
#### 1. Set the Required Options
- `isManifest: true` β ensures the manifest is used - default `false`.
- `createManifest: true` β instructs the builder to generate the manifest file - default `false`.
- `manifestPath: "manifest.json"` β specifies the path where the manifest will be created - default `manifest.json`.
- `manifest` β the basic manifest info.
- `icons` β table of icons for add to component in head.
#### 2. Add Basic settings
Add the following to your configuration for minimal PWA support:
```js
// filepath: astro.config.mjs
import { defineConfig } from "astro/config";
import PoweredWebAppBuilder from "webapp-astro-pwa/pwa";
export default defineConfig({
integrations: [
PoweredWebAppBuilder({
isManifest: true,
createManifest: true,
manifestPath: "manifest.json",
manifest: {
name: "My PWA Example",
short_name: "PWAExample",
description: "A simple Progressive Web App example.",
start_url: "/",
display: "standalone",
theme_color: "#8936FF",
icons: [
{
sizes: "512x512",
src: "node_modules/webapp-astro-pwa/src/manifest_imgs/icon512x512.png",
type: "image/png",
},
{
sizes: "192x192",
src: "node_modules/webapp-astro-pwa/src/manifest_imgs/icon192x192.png",
type: "image/png",
},
],
},
icons: [
{
rel: "icon",
type: "png",
sizes: "512x512",
href: "/webapp-astro-pwa/src/manifest_imgs/icon512x512.png",
},
{
rel: "apple-touch-icon",
type: "png",
sizes: "192x192",
href: "/webapp-astro-pwa/src/manifest_imgs/icon512x512.png",
},
],
}),
],
});
```
##### What this does
- **Enables installation** of your app as a PWA on supported devices.
- **Automatically generates** the manifest file at the specified path after building your project.
- \*\*Injects basic manifest and icons.
After updating your configuration, rebuild your application. The manifest file will be created automatically, and your app will be ready for installation as a PWA.
#### 3. Extend with Meta Information
For a complete PWA experience and optimal support on all platforms, add the following meta tags to your configuration. These tags improve installability, appearance, and integration on both Android and iOS devices:
```js
// filepath: astro.config.mjs
import { defineConfig } from "astro/config";
import PoweredWebAppBuilder from "webapp-astro-pwa/pwa";
export default defineConfig({
integrations: [
PoweredWebAppBuilder({
isManifest: true,
createManifest: true,
manifestPath: "manifest.json",
manifest: {
name: "My PWA Example",
short_name: "PWAExample",
description: "A simple Progressive Web App example.",
start_url: "/",
display: "standalone",
theme_color: "#8936FF",
icons: [
{
sizes: "512x512",
src: "node_modules/webapp-astro-pwa/src/manifest_imgs/icon512x512.png",
type: "image/png",
},
{
sizes: "192x192",
src: "node_modules/webapp-astro-pwa/src/manifest_imgs/icon192x192.png",
type: "image/png",
},
],
},
icons: [
{
rel: "icon",
type: "png",
sizes: "512x512",
href: "/webapp-astro-pwa/src/manifest_imgs/icon512x512.png",
},
{
rel: "apple-touch-icon",
type: "png",
sizes: "192x192",
href: "/webapp-astro-pwa/src/manifest_imgs/icon512x512.png",
},
],
// ...table with mete information ...
meta: [
{
name: "mobile-web-app-capable",
content: "yes",
},
{
name: "apple-mobile-web-app-capable",
content: "yes",
},
{
name: "application-name",
content: "PWAExample",
},
{
name: "apple-mobile-web-app-title",
content: "PWAExample",
},
{
name: "theme-color",
content: "#8936FF",
},
{
name: "msapplication-navbutton-color",
content: "#8936FF",
},
{
name: "apple-mobile-web-app-status-bar-style",
content: "black-translucent",
},
{
name: "viewport",
content: "width=device-width, initial-scale=1, shrink-to-fit=no",
},
{
name: "msapplication-starturla",
content: "/",
},
],
}),
],
});
```
### ποΈ Additional Install Button
To enable extra installation prompts, add the following to your configuration:
- `isInstallBtnVisible: true` β ensures the additional installation is used - default `false`.
```js
// filepath: astro.config.mjs
import { defineConfig } from 'astro/config';
import PoweredWebAppBuilder from "webapp-astro-pwa/pwa";
export default defineConfig({
integrations: [
// this line changed
PoweredWebAppBuilder({
"isInstallBtnVisible": true,
}),
...
]
});
```
There are two options for displaying the install prompt:
Popup Modal: Use <PWASetupWindow /> to show a modal that blocks the page until the user interacts with the install prompt.
Simple Button: Use <PWABtn /> to add a standalone install button anywhere in your app.
Note: Not all browsers support the PWA install prompt. For unsupported browsers, a notification will be shown with instructions to install the PWA using the standard browser menu.
Import and use the main components in your Astro pages/layouts:
```astro
import { PWA, PWABtn, PWASetupWindow } from "webapp-astro-pwa";
<PWA /> <!-- Injects manifest/meta and registers service worker -->
<PWASetupWindow
title="Install Our App"
description="Get the best experience by installing our app."
btnText="Install"
btnBackground="#4361ee"
background="#fff"
hideSvg={false}
/>
```
Or, for a simple install button:
```astro
<PWABtn btnText="Install App" btnBackground="#3a0ca3" hideSvg={false} />
```
### Enabling Web Push Notifications
You can easily enable web push notifications in your Astro PWA project using the `notification` option in the `PoweredWebAppBuilder` configuration. This allows your application to request user permission for push notifications and manage subscriptions for web push messages.
#### How to Enable
Add the following options to your `astro.config.mjs` (or `astro.config.ts`):
```js
import { defineConfig } from "astro/config";
import PoweredWebAppBuilder from "webapp-astro-pwa/pwa";
// https://astro.build/config
export default defineConfig({
integrations: [
PoweredWebAppBuilder({
notification: true, // Enables web push notifications (default: false)
saveSubscriptionPath: "path_to_server_for_save_subscription", // API endpoint to save push subscriptions
applicationServerKey: "key_client_side", // VAPID public key for push notifications
notificationBtn: true, // Enables the button to request notification permission (default: false)
}),
],
});
```
#### Option Details
- **notification**:
Set to `true` to enable web push notifications. By default, this is `false`. When enabled, your app will request user permission to receive push notifications and handle push subscription logic.
- **saveSubscriptionPath**:
The server endpoint where user push subscriptions will be sent and stored. This should point to your backend API that manages push subscribers.
- **notificationBtn**:
Enables the button to request notification permission
- **applicationServerKey**:
The VAPID public key used for authenticating push messages on the client side. This key is required for subscribing users to push notifications.
**Note:**
Make sure your backend is set up to handle and store push subscriptions at the specified `saveSubscriptionPath`, and that you generate a valid VAPID key pair for secure push messaging.
### π¦ Notification Button Component
```astro
<NotificationBtn
style={{ color: "black" }}
/>
```
| Prop | Type | Description |
| ---------------------- | -------- | ------------------------------------------------------------- |
| `notificationBtn` | `bool` | Enables the notification permission button (default: `false`) |
| `btnText` | `string` | Text displayed on the button |
| `style` | `object` | Inline styles for the button |
| `responsiveStyles` | `object` | Media query-specific style overrides |
| `variables.matchMedia` | `string` | Media query string (e.g., `(max-width: 768px)`) |
| `variables.styles` | `object` | Style object for the media query |
## With these options enabled, your PWA will be ready to request notification permissions and manage web push subscriptions, allowing you to send real-time updates directly to your users. Thanks to this option, you can send simple web push notifications with an icon, body, title, and URL.
### π Web Push Notifications with Firebase and Astro (Full Integration Guide)
βοΈ Firebase Setup
1. Create a Firebase Project
Go to the Firebase Console
Click βAdd projectβ
Follow on-screen instructions to create a new Firebase project
2. Enable Firestore
Go to Firestore Database in the Firebase console
Click βCreate Databaseβ
Choose βStart in production modeβ or βTest modeβ
3. Copy Firebase Config to Astro
Copy your Firebase config object (firebaseConfig) from the Firebase console
Add it to astro.config.mjs:
```js
export default defineConfig({
firebaseConfig: {
apiKey: "<yor api key>",
authDomain: "<authDomain key>",
projectId: "<your project id>",
storageBucket: "<your storage bucket>",
messagingSenderId: "<your messagingSenderId>",
appId: "<your appId>",
measurementId: "<you measurementId>",
},
});
```
4. Firestore Security Rules
Go to Firestore β Rules and use the following rule set:
```js
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read: if request.auth != null;
allow write: if request.resource.data.keys().hasOnly(['token']) &&
request.resource.data.token is string &&
request.resource.data.token.size() <= 340;
}
}
}
```
### π Web Push Certificates (VAPID Key)
Generate a New VAPID Key
Go to Firebase Console β Project Settings β Cloud Messaging
Scroll to Web Push certificates
Click "Generate Key Pair"
Copy the Public Key and add it in astro.config.mjs:
```js
export default defineConfig({
vapidKey: "<your_generated_public_key>",
});
```
### π Firebase Service Account Key
Create and Use a Service Account Key
In Firebase Console β Settings β Cloud Messaging
Click βManage service accountβ
Go to the Google Cloud Console and create a key
Download the generated JSON file
Add the contents to astro.config.mjs:
```js
export default defineConfig({
fcmServiceAccountKey: {
type: "service_account",
project_id: "abcdefgh",
private_key_id: "...",
private_key: "-----BEGIN PRIVATE KEY-----\n....\n-----END PRIVATE KEY-----\n",
client_email: "...",
client_id: "...",
...
}
});
```
### π Astro Project Setup
1. Install Node Adapter
```bash
npx astro add node
```
### 2. Configure Astro for Node Hosting
In astro.config.mjs:
```bash
import node from "@astrojs/node";
export default defineConfig({
adapter: node(),
});
```
### π Auth Setup
Set up authentication credentials for your push panel:
```env
AUTH_USER="<your_login>"
AUTH_PASS="<your_password>"
```
### π Page Setup
Create sendpush.astro
```astro
import { SendPushPage } from "webapp-astro-pwa";
<SendPushPage />
```
Create login.astro
```astro
import { LoginPanel } from "webapp-astro-pwa";
<LoginPanel />
```
Create API Endpoint: pages/pushapi.ts
```ts
import getData from "webapp-astro-pwa";
export const prerender = false;
export async function GET(context: APIContext) {
return await getData(context);
}
```
### β
Testing Your Setup
Visit http://<your_web_app>/sendpush
Log in using AUTH_USER and AUTH_PASS
Youβll be redirected to the push notification panel
## Start sending Web Push notifications to users!
### π Summary
β
Firebase with Firestore and FCM
β
Astro setup with Node adapter
β
Web push button integration
β
Admin panel with login
β
Push notification panel ready
### Configure Your PWA
Edit [`pwa.config.json`](pwa.config.json) at the root of your project to customize manifest, icons, meta tags, caching strategy, and more.
Example:
```json
{
"isInstallBtnVisible": true,
"createManifest": true,
"cacheAssets": "static-assets",
"disableDevLogs": true,
"isManifest": true,
"manifestPath": "manifest.json",
"strategy": "CacheFirst",
"manifest": {
/* ... */
},
"icons": [
/* ... */
],
"meta": [
/* ... */
]
}
```
## π§© Components
- [`PWA`](src/PWA.astro): Injects manifest/meta and registers the service worker.
- [`PWABtn`](src/PWABtn.astro): Standalone install button.
- [`PWASetupWindow`](src/PWASetupWindow.astro): Full install popover with customizable UI.
## βοΈ Service Worker
To (re)generate and bundle your service worker, run:
```sh
npm run generateAndBundleSW
```
This uses Workbox and your config to inject the manifest and bundle the service worker to `public/sw.js`.
## π TypeScript
Type definitions for configuration and component props are available in [`src/types.ts`](src/types.ts).
## π License
MIT
## πββοΈ Contributing
Feel free to open issues or PRs for improvements and bug fixes.
- [GitHub](https://github.com/aondodawid/WebApp-Astro-PWA/issues)
## π Further Reading
- [Astro Documentation](https://docs.astro.build/)
- [MDN: Progressive Web Apps](https://developer.mozilla.org/docs/Web/Progressive_web_apps)
- [Workbox](https://developer.chrome.com/docs/workbox/)