├── .node-version ├── CODEOWNERS ├── .gitattributes ├── .npmrc ├── docs ├── .gitignore ├── pages │ ├── about.mdx │ ├── _meta.json │ ├── get-started.mdx │ ├── offline-fallbacks.mdx │ ├── tips.mdx │ └── index.mdx ├── public │ └── favicons │ │ ├── favicon.ico │ │ ├── apple-icon.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon-96x96.png │ │ ├── ms-icon-70x70.png │ │ ├── apple-icon-57x57.png │ │ ├── apple-icon-60x60.png │ │ ├── apple-icon-72x72.png │ │ ├── apple-icon-76x76.png │ │ ├── ms-icon-144x144.png │ │ ├── ms-icon-150x150.png │ │ ├── ms-icon-310x310.png │ │ ├── mstile-150x150.png │ │ ├── android-icon-36x36.png │ │ ├── android-icon-48x48.png │ │ ├── android-icon-72x72.png │ │ ├── android-icon-96x96.png │ │ ├── apple-icon-114x114.png │ │ ├── apple-icon-120x120.png │ │ ├── apple-icon-144x144.png │ │ ├── apple-icon-152x152.png │ │ ├── apple-icon-180x180.png │ │ ├── android-icon-144x144.png │ │ ├── android-icon-192x192.png │ │ ├── apple-icon-precomposed.png │ │ ├── browserconfig.xml │ │ ├── safari-pinned-tab.svg │ │ └── manifest.json ├── next.config.js ├── next-env.d.ts ├── README.md ├── tsconfig.json ├── package.json └── theme.config.tsx ├── vercel.json ├── .gitpod.yml ├── .prettierrc.cjs ├── examples ├── cookie │ ├── .eslintrc.json │ ├── public │ │ ├── favicon.ico │ │ ├── icons │ │ │ ├── icon-512x512.png │ │ │ ├── apple-touch-icon.png │ │ │ └── android-chrome-192x192.png │ │ └── manifest.json │ ├── next.config.js │ ├── README.md │ ├── package.json │ └── pages │ │ ├── login.js │ │ ├── index.js │ │ └── _document.js ├── minimal │ ├── .eslintrc.json │ ├── lighthouse.pdf │ ├── public │ │ ├── favicon.ico │ │ ├── icons │ │ │ ├── icon-512x512.png │ │ │ ├── apple-touch-icon.png │ │ │ └── android-chrome-192x192.png │ │ └── manifest.json │ ├── next.config.js │ ├── pages │ │ ├── index.js │ │ └── _document.js │ ├── package.json │ ├── README.md │ └── index.js ├── next-13 │ ├── .eslintrc.json │ ├── lighthouse.pdf │ ├── public │ │ ├── favicon.ico │ │ ├── icons │ │ │ ├── icon-512x512.png │ │ │ ├── apple-touch-icon.png │ │ │ └── android-chrome-192x192.png │ │ └── manifest.json │ ├── next.config.js │ ├── pages │ │ ├── about.js │ │ ├── index.js │ │ └── _document.js │ ├── package.json │ └── README.md ├── lifecycle │ ├── .eslintrc.json │ ├── public │ │ ├── favicon.ico │ │ ├── icons │ │ │ ├── icon-512x512.png │ │ │ ├── apple-touch-icon.png │ │ │ └── android-chrome-192x192.png │ │ └── manifest.json │ ├── next.config.js │ ├── package.json │ ├── README.md │ └── pages │ │ ├── _document.js │ │ └── index.js ├── next-image │ ├── .eslintrc.json │ ├── public │ │ ├── favicon.ico │ │ ├── icons │ │ │ ├── icon-512x512.png │ │ │ ├── apple-touch-icon.png │ │ │ └── android-chrome-192x192.png │ │ └── manifest.json │ ├── next.config.js │ ├── pages │ │ ├── about.js │ │ ├── index.js │ │ └── _document.js │ ├── package.json │ ├── README.md │ └── images │ │ └── nextjs-dark.svg ├── web-push │ ├── .eslintrc.json │ ├── public │ │ ├── favicon.ico │ │ ├── icons │ │ │ ├── icon-512x512.png │ │ │ ├── apple-touch-icon.png │ │ │ └── android-chrome-192x192.png │ │ └── manifest.json │ ├── next.config.js │ ├── package.json │ ├── pages │ │ ├── api │ │ │ └── notification.js │ │ ├── _document.js │ │ └── index.js │ ├── README.md │ └── worker │ │ └── index.js ├── custom-ts-worker │ ├── .eslintrc.json │ ├── public │ │ ├── favicon.ico │ │ ├── icons │ │ │ ├── icon-512x512.png │ │ │ ├── apple-touch-icon.png │ │ │ └── android-chrome-192x192.png │ │ └── manifest.json │ ├── next.config.js │ ├── worker │ │ ├── util.ts │ │ └── index.ts │ ├── next-env.d.ts │ ├── pages │ │ ├── index.tsx │ │ └── _document.tsx │ ├── package.json │ ├── tsconfig.json │ ├── README.md │ └── types │ │ └── service-worker.d.ts ├── custom-worker │ ├── .eslintrc.json │ ├── public │ │ ├── favicon.ico │ │ ├── icons │ │ │ ├── icon-512x512.png │ │ │ ├── apple-touch-icon.png │ │ │ └── android-chrome-192x192.png │ │ └── manifest.json │ ├── next.config.js │ ├── worker │ │ ├── util.js │ │ └── index.js │ ├── pages │ │ ├── index.js │ │ └── _document.js │ ├── package.json │ └── README.md ├── cache-on-front-end-nav │ ├── .eslintrc.json │ ├── public │ │ ├── favicon.ico │ │ ├── icons │ │ │ ├── icon-512x512.png │ │ │ ├── apple-touch-icon.png │ │ │ └── android-chrome-192x192.png │ │ └── manifest.json │ ├── next.config.js │ ├── worker │ │ └── index.js │ ├── pages │ │ ├── a.js │ │ ├── b.js │ │ ├── index.js │ │ ├── _app.js │ │ └── _document.js │ ├── package.json │ └── README.md ├── next-i18next │ ├── vercel.json │ ├── public │ │ ├── favicon.ico │ │ ├── icons │ │ │ ├── icon-512x512.png │ │ │ ├── apple-touch-icon.png │ │ │ └── android-chrome-192x192.png │ │ ├── locales │ │ │ ├── en │ │ │ │ ├── second-page.json │ │ │ │ ├── footer.json │ │ │ │ └── common.json │ │ │ └── de │ │ │ │ ├── second-page.json │ │ │ │ ├── footer.json │ │ │ │ └── common.json │ │ ├── manifest.json │ │ └── app.css │ ├── next-env.d.ts │ ├── pages │ │ ├── _app.tsx │ │ ├── second-page.tsx │ │ ├── _document.tsx │ │ └── index.tsx │ ├── components │ │ ├── Header.tsx │ │ └── Footer.tsx │ ├── next-utils.config.js │ ├── @types │ │ └── i18next.d.ts │ ├── next.config.js │ ├── tsconfig.json │ ├── next-i18next.config.js │ └── package.json ├── app-dir │ ├── public │ │ ├── favicon.ico │ │ ├── icons │ │ │ ├── icon-512x512.png │ │ │ ├── apple-touch-icon.png │ │ │ └── android-chrome-192x192.png │ │ └── manifest.json │ ├── .vscode │ │ └── settings.json │ ├── next-env.d.ts │ ├── app │ │ ├── layout.tsx │ │ └── page.tsx │ ├── next.config.js │ ├── package.json │ ├── .gitignore │ ├── tsconfig.json │ └── readme.md ├── offline-fallback │ ├── public │ │ ├── favicon.ico │ │ ├── icons │ │ │ ├── icon-512x512.png │ │ │ ├── apple-touch-icon.png │ │ │ └── android-chrome-192x192.png │ │ ├── static │ │ │ └── images │ │ │ │ └── fallback.png │ │ └── manifest.json │ ├── .eslintrc.js │ ├── next.config.js │ ├── pages │ │ ├── fallback.js │ │ ├── index.js │ │ └── _document.js │ ├── package.json │ ├── README.md │ └── service-worker.js ├── offline-fallback-v2 │ ├── public │ │ ├── favicon.ico │ │ ├── icons │ │ │ ├── icon-512x512.png │ │ │ ├── apple-touch-icon.png │ │ │ └── android-chrome-192x192.png │ │ ├── static │ │ │ └── images │ │ │ │ └── fallback.png │ │ └── manifest.json │ ├── .eslintrc.js │ ├── pages │ │ ├── _offline.js │ │ ├── index.js │ │ └── _document.js │ ├── next.config.js │ ├── package.json │ └── README.md └── custom-worker-webpack │ ├── public │ ├── favicon.ico │ ├── icons │ │ ├── icon-512x512.png │ │ ├── apple-touch-icon.png │ │ └── android-chrome-192x192.png │ └── manifest.json │ ├── .eslintrc.js │ ├── util │ └── index.js │ ├── pages │ ├── index.js │ └── _document.js │ ├── next.config.js │ ├── package.json │ ├── worker │ └── index.js │ └── README.md ├── commitlint.config.cjs ├── pnpm-workspace.yaml ├── .husky ├── commit-msg └── pre-commit ├── packages ├── next-pwa │ ├── README.md │ ├── package.json │ ├── fallback.js │ ├── register.js │ ├── build-custom-worker.js │ └── build-fallback-worker.js ├── config-prettier │ ├── index.js │ └── package.json └── eslint-config-custom │ ├── index.js │ └── package.json ├── .npmignore ├── .vscode ├── extensions.json └── settings.json ├── .eslintrc.cjs ├── .changeset ├── config.json └── README.md ├── .prettierignore ├── .gitignore ├── turbo.json ├── syncpack.config.cjs ├── .github ├── workflows │ ├── build-examples.yml │ └── npm-publish.yml └── renovate.json ├── LICENSE └── package.json /.node-version: -------------------------------------------------------------------------------- 1 | 18 -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @ImBIOS -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | .next 2 | node_modules 3 | -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { "github": { "silent": true } } 2 | -------------------------------------------------------------------------------- /.gitpod.yml: -------------------------------------------------------------------------------- 1 | tasks: 2 | - init: pnpm install 3 | -------------------------------------------------------------------------------- /.prettierrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ...require("config-prettier"), 3 | }; 4 | -------------------------------------------------------------------------------- /examples/cookie/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /examples/minimal/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /examples/next-13/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /examples/lifecycle/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /examples/next-image/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /examples/web-push/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /commitlint.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { extends: ["@commitlint/config-conventional"] }; 2 | -------------------------------------------------------------------------------- /examples/custom-ts-worker/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /examples/custom-worker/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - "docs" 3 | - "packages/*" 4 | - "examples/*" 5 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | pnpm commitlint --edit 5 | -------------------------------------------------------------------------------- /examples/cache-on-front-end-nav/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /examples/next-i18next/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "github": { 3 | "silent": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /packages/next-pwa/README.md: -------------------------------------------------------------------------------- 1 | # `@imbios/next-pwa` 2 | 3 | Next.js plugin to add PWA support 4 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | pnpm lint-staged 5 | -------------------------------------------------------------------------------- /docs/pages/about.mdx: -------------------------------------------------------------------------------- 1 | # About 2 | 3 | This is the about page! This page is shown on the navbar. 4 | -------------------------------------------------------------------------------- /examples/minimal/lighthouse.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/minimal/lighthouse.pdf -------------------------------------------------------------------------------- /examples/next-13/lighthouse.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/next-13/lighthouse.pdf -------------------------------------------------------------------------------- /docs/public/favicons/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/favicon.ico -------------------------------------------------------------------------------- /docs/public/favicons/apple-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/apple-icon.png -------------------------------------------------------------------------------- /examples/app-dir/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/app-dir/public/favicon.ico -------------------------------------------------------------------------------- /examples/cookie/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/cookie/public/favicon.ico -------------------------------------------------------------------------------- /examples/minimal/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/minimal/public/favicon.ico -------------------------------------------------------------------------------- /examples/next-13/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/next-13/public/favicon.ico -------------------------------------------------------------------------------- /examples/web-push/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/web-push/public/favicon.ico -------------------------------------------------------------------------------- /docs/public/favicons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/favicon-16x16.png -------------------------------------------------------------------------------- /docs/public/favicons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/favicon-32x32.png -------------------------------------------------------------------------------- /docs/public/favicons/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/favicon-96x96.png -------------------------------------------------------------------------------- /docs/public/favicons/ms-icon-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/ms-icon-70x70.png -------------------------------------------------------------------------------- /examples/lifecycle/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/lifecycle/public/favicon.ico -------------------------------------------------------------------------------- /examples/next-image/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/next-image/public/favicon.ico -------------------------------------------------------------------------------- /docs/public/favicons/apple-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/apple-icon-57x57.png -------------------------------------------------------------------------------- /docs/public/favicons/apple-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/apple-icon-60x60.png -------------------------------------------------------------------------------- /docs/public/favicons/apple-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/apple-icon-72x72.png -------------------------------------------------------------------------------- /docs/public/favicons/apple-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/apple-icon-76x76.png -------------------------------------------------------------------------------- /docs/public/favicons/ms-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/ms-icon-144x144.png -------------------------------------------------------------------------------- /docs/public/favicons/ms-icon-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/ms-icon-150x150.png -------------------------------------------------------------------------------- /docs/public/favicons/ms-icon-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/ms-icon-310x310.png -------------------------------------------------------------------------------- /docs/public/favicons/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/mstile-150x150.png -------------------------------------------------------------------------------- /examples/custom-worker/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/custom-worker/public/favicon.ico -------------------------------------------------------------------------------- /examples/next-i18next/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/next-i18next/public/favicon.ico -------------------------------------------------------------------------------- /docs/public/favicons/android-icon-36x36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/android-icon-36x36.png -------------------------------------------------------------------------------- /docs/public/favicons/android-icon-48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/android-icon-48x48.png -------------------------------------------------------------------------------- /docs/public/favicons/android-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/android-icon-72x72.png -------------------------------------------------------------------------------- /docs/public/favicons/android-icon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/android-icon-96x96.png -------------------------------------------------------------------------------- /docs/public/favicons/apple-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/apple-icon-114x114.png -------------------------------------------------------------------------------- /docs/public/favicons/apple-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/apple-icon-120x120.png -------------------------------------------------------------------------------- /docs/public/favicons/apple-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/apple-icon-144x144.png -------------------------------------------------------------------------------- /docs/public/favicons/apple-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/apple-icon-152x152.png -------------------------------------------------------------------------------- /docs/public/favicons/apple-icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/apple-icon-180x180.png -------------------------------------------------------------------------------- /docs/public/favicons/android-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/android-icon-144x144.png -------------------------------------------------------------------------------- /docs/public/favicons/android-icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/android-icon-192x192.png -------------------------------------------------------------------------------- /examples/app-dir/public/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/app-dir/public/icons/icon-512x512.png -------------------------------------------------------------------------------- /examples/cookie/public/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/cookie/public/icons/icon-512x512.png -------------------------------------------------------------------------------- /examples/custom-ts-worker/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/custom-ts-worker/public/favicon.ico -------------------------------------------------------------------------------- /examples/minimal/public/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/minimal/public/icons/icon-512x512.png -------------------------------------------------------------------------------- /examples/next-13/public/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/next-13/public/icons/icon-512x512.png -------------------------------------------------------------------------------- /examples/offline-fallback/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/offline-fallback/public/favicon.ico -------------------------------------------------------------------------------- /docs/public/favicons/apple-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/docs/public/favicons/apple-icon-precomposed.png -------------------------------------------------------------------------------- /examples/lifecycle/public/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/lifecycle/public/icons/icon-512x512.png -------------------------------------------------------------------------------- /examples/next-13/next.config.js: -------------------------------------------------------------------------------- 1 | const withPWA = require("@imbios/next-pwa")({ 2 | dest: "public", 3 | }); 4 | 5 | module.exports = withPWA(); 6 | -------------------------------------------------------------------------------- /examples/offline-fallback-v2/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/offline-fallback-v2/public/favicon.ico -------------------------------------------------------------------------------- /examples/web-push/public/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/web-push/public/icons/icon-512x512.png -------------------------------------------------------------------------------- /examples/app-dir/public/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/app-dir/public/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /examples/cache-on-front-end-nav/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/cache-on-front-end-nav/public/favicon.ico -------------------------------------------------------------------------------- /examples/cookie/public/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/cookie/public/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /examples/custom-worker-webpack/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/custom-worker-webpack/public/favicon.ico -------------------------------------------------------------------------------- /examples/minimal/public/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/minimal/public/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /examples/next-13/public/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/next-13/public/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /examples/next-i18next/public/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/next-i18next/public/icons/icon-512x512.png -------------------------------------------------------------------------------- /examples/next-image/next.config.js: -------------------------------------------------------------------------------- 1 | const withPWA = require("@imbios/next-pwa")({ 2 | dest: "public", 3 | }); 4 | 5 | module.exports = withPWA(); 6 | -------------------------------------------------------------------------------- /examples/next-image/public/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/next-image/public/icons/icon-512x512.png -------------------------------------------------------------------------------- /examples/web-push/next.config.js: -------------------------------------------------------------------------------- 1 | const withPWA = require("@imbios/next-pwa")({ 2 | dest: "public", 3 | }); 4 | 5 | module.exports = withPWA(); 6 | -------------------------------------------------------------------------------- /examples/web-push/public/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/web-push/public/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /examples/custom-ts-worker/next.config.js: -------------------------------------------------------------------------------- 1 | const withPWA = require("@imbios/next-pwa")({ 2 | dest: "public", 3 | }); 4 | 5 | module.exports = withPWA(); 6 | -------------------------------------------------------------------------------- /examples/custom-worker/next.config.js: -------------------------------------------------------------------------------- 1 | const withPWA = require("@imbios/next-pwa")({ 2 | dest: "public", 3 | }); 4 | 5 | module.exports = withPWA(); 6 | -------------------------------------------------------------------------------- /examples/custom-worker/public/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/custom-worker/public/icons/icon-512x512.png -------------------------------------------------------------------------------- /examples/lifecycle/public/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/lifecycle/public/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /examples/next-image/public/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/next-image/public/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /packages/config-prettier/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | trailingComma: "es5", 3 | tabWidth: 2, 4 | semi: true, 5 | singleQuote: false, 6 | }; 7 | -------------------------------------------------------------------------------- /examples/app-dir/public/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/app-dir/public/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /examples/cache-on-front-end-nav/next.config.js: -------------------------------------------------------------------------------- 1 | const withPWA = require("@imbios/next-pwa")({ 2 | dest: "public", 3 | }); 4 | 5 | module.exports = withPWA(); 6 | -------------------------------------------------------------------------------- /examples/cookie/public/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/cookie/public/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /examples/custom-ts-worker/public/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/custom-ts-worker/public/icons/icon-512x512.png -------------------------------------------------------------------------------- /examples/custom-worker/public/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/custom-worker/public/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /examples/minimal/public/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/minimal/public/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /examples/next-13/public/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/next-13/public/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /examples/next-i18next/public/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/next-i18next/public/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /examples/offline-fallback/public/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/offline-fallback/public/icons/icon-512x512.png -------------------------------------------------------------------------------- /examples/lifecycle/public/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/lifecycle/public/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /examples/offline-fallback-v2/public/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/offline-fallback-v2/public/icons/icon-512x512.png -------------------------------------------------------------------------------- /examples/web-push/public/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/web-push/public/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /examples/cache-on-front-end-nav/public/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/cache-on-front-end-nav/public/icons/icon-512x512.png -------------------------------------------------------------------------------- /examples/custom-ts-worker/public/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/custom-ts-worker/public/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /examples/custom-worker-webpack/public/icons/icon-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/custom-worker-webpack/public/icons/icon-512x512.png -------------------------------------------------------------------------------- /examples/next-i18next/public/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/next-i18next/public/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /examples/next-image/public/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/next-image/public/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /examples/offline-fallback/public/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/offline-fallback/public/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /examples/offline-fallback/public/static/images/fallback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/offline-fallback/public/static/images/fallback.png -------------------------------------------------------------------------------- /examples/custom-worker/public/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/custom-worker/public/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /examples/offline-fallback-v2/public/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/offline-fallback-v2/public/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /examples/offline-fallback-v2/public/static/images/fallback.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/offline-fallback-v2/public/static/images/fallback.png -------------------------------------------------------------------------------- /examples/cache-on-front-end-nav/public/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/cache-on-front-end-nav/public/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /examples/custom-ts-worker/public/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/custom-ts-worker/public/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /examples/custom-worker-webpack/public/icons/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/custom-worker-webpack/public/icons/apple-touch-icon.png -------------------------------------------------------------------------------- /examples/offline-fallback/public/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/offline-fallback/public/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /packages/config-prettier/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "config-prettier", 3 | "version": "0.0.0", 4 | "private": true, 5 | "main": "index.js", 6 | "license": "MIT" 7 | } 8 | -------------------------------------------------------------------------------- /docs/next.config.js: -------------------------------------------------------------------------------- 1 | const withNextra = require("nextra")({ 2 | theme: "nextra-theme-docs", 3 | themeConfig: "./theme.config.tsx", 4 | }); 5 | 6 | module.exports = withNextra(); 7 | -------------------------------------------------------------------------------- /examples/offline-fallback-v2/public/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/offline-fallback-v2/public/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /examples/cache-on-front-end-nav/public/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/cache-on-front-end-nav/public/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /examples/custom-worker-webpack/public/icons/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ImBIOS/next-pwa/HEAD/examples/custom-worker-webpack/public/icons/android-chrome-192x192.png -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | package-lock.json 3 | yarn.lock 4 | yarn-error.log 5 | examples/ 6 | .gitignore 7 | .gitattributes 8 | .github/ 9 | CHANGELOG.md 10 | LICENSE 11 | docs/ 12 | -------------------------------------------------------------------------------- /examples/app-dir/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.tsdk": "../../node_modules/.pnpm/typescript@4.9.5/node_modules/typescript/lib", 3 | "typescript.enablePromptUseWorkspaceTsdk": true 4 | } -------------------------------------------------------------------------------- /examples/lifecycle/next.config.js: -------------------------------------------------------------------------------- 1 | const withPWA = require("@imbios/next-pwa")({ 2 | dest: "public", 3 | register: false, 4 | skipWaiting: false, 5 | }); 6 | 7 | module.exports = withPWA(); 8 | -------------------------------------------------------------------------------- /examples/next-i18next/public/locales/en/second-page.json: -------------------------------------------------------------------------------- 1 | { 2 | "h1": "A second page, to demonstrate routing", 3 | "back-to-home": "Back to home", 4 | "title": "Second page | next-i18next" 5 | } 6 | -------------------------------------------------------------------------------- /examples/custom-ts-worker/worker/util.ts: -------------------------------------------------------------------------------- 1 | export function util() { 2 | console.log("Hello from util."); 3 | console.log("es6+ syntax test:"); 4 | let foo = { message: "working" }; 5 | console.log(foo?.message); 6 | } 7 | -------------------------------------------------------------------------------- /examples/next-i18next/public/locales/de/second-page.json: -------------------------------------------------------------------------------- 1 | { 2 | "h1": "Eine zweite Seite, um das Routing zu demonstrieren", 3 | "back-to-home": "Zurück zur Hauptseite", 4 | "title": "Zweite Seite | next-i18next" 5 | } 6 | -------------------------------------------------------------------------------- /examples/offline-fallback/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: "next/core-web-vitals", 3 | parserOptions: { 4 | babelOptions: { 5 | presets: [require.resolve("next/babel")], 6 | }, 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /examples/custom-worker-webpack/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: "next/core-web-vitals", 3 | parserOptions: { 4 | babelOptions: { 5 | presets: [require.resolve("next/babel")], 6 | }, 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /examples/offline-fallback-v2/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: "next/core-web-vitals", 3 | parserOptions: { 4 | babelOptions: { 5 | presets: [require.resolve("next/babel")], 6 | }, 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "dbaeumer.vscode-eslint", 4 | "nhoizey.gremlins", 5 | "wix.vscode-import-cost", 6 | "esbenp.prettier-vscode", 7 | "unifiedjs.vscode-mdx" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /docs/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /examples/minimal/next.config.js: -------------------------------------------------------------------------------- 1 | const withPWA = require("@imbios/next-pwa")({ 2 | // pwa output folder 3 | // dest: '.next/pwa' 4 | // 5 | // Other configurations: 6 | // ... 7 | }); 8 | 9 | module.exports = withPWA(); 10 | -------------------------------------------------------------------------------- /examples/custom-worker/worker/util.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = () => { 4 | console.log("Hello from util."); 5 | console.log("es6+ syntax test:"); 6 | let foo = { message: "working" }; 7 | console.log(foo?.message); 8 | }; 9 | -------------------------------------------------------------------------------- /examples/next-i18next/public/locales/en/footer.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "This is a non-page component that requires its own namespace", 3 | "helpLocize": "With using <1>locize you directly support the future of <3>i18next." 4 | } 5 | -------------------------------------------------------------------------------- /examples/app-dir/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /packages/eslint-config-custom/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ["next/core-web-vitals", "turbo", "prettier"], 3 | parserOptions: { 4 | babelOptions: { 5 | presets: [require.resolve("next/babel")], 6 | }, 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /examples/custom-worker-webpack/util/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = () => { 4 | console.log("Hello from util."); 5 | console.log("es6+ syntax test:"); 6 | let foo = { message: "working" }; 7 | console.log(foo?.message); 8 | }; 9 | -------------------------------------------------------------------------------- /examples/next-i18next/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /examples/custom-ts-worker/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /examples/app-dir/app/layout.tsx: -------------------------------------------------------------------------------- 1 | export default function RootLayout({ 2 | children, 3 | }: { 4 | children: React.ReactNode; 5 | }) { 6 | return ( 7 | 8 | 9 | {children} 10 | 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | // This tells ESLint to load the config from the package `eslint-config-custom` 4 | extends: ["custom"], 5 | settings: { 6 | next: { 7 | rootDir: ["examples/*/"], 8 | }, 9 | }, 10 | }; 11 | -------------------------------------------------------------------------------- /examples/next-i18next/public/locales/de/footer.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Dies ist eine Nicht-Seitenkomponente, die einen eigenen Namespace erfordert", 3 | "helpLocize": "Wenn Sie <1>locize einsetzen, unterstützen Sie direkt die Zukunft von <3>i18next." 4 | } 5 | -------------------------------------------------------------------------------- /examples/offline-fallback/next.config.js: -------------------------------------------------------------------------------- 1 | const withPWA = require("@imbios/next-pwa")({ 2 | dest: "public", 3 | swSrc: "service-worker.js", 4 | }); 5 | 6 | module.exports = withPWA({ 7 | images: { 8 | domains: ["source.unsplash.com"], 9 | }, 10 | }); 11 | -------------------------------------------------------------------------------- /examples/minimal/pages/index.js: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | 3 | const Index = () => ( 4 | <> 5 | 6 | next-pwa example 7 | 8 |

Next.js + PWA = AWESOME!

9 | 10 | ); 11 | 12 | export default Index; 13 | -------------------------------------------------------------------------------- /examples/custom-worker/pages/index.js: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | 3 | const Index = () => ( 4 | <> 5 | 6 | next-pwa example 7 | 8 |

Next.js + PWA = AWESOME!

9 | 10 | ); 11 | 12 | export default Index; 13 | -------------------------------------------------------------------------------- /examples/custom-ts-worker/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | 3 | const Index = () => ( 4 | <> 5 | 6 | next-pwa example 7 | 8 |

Next.js + PWA = AWESOME!

9 | 10 | ); 11 | 12 | export default Index; 13 | -------------------------------------------------------------------------------- /examples/app-dir/next.config.js: -------------------------------------------------------------------------------- 1 | const withPWA = require("@imbios/next-pwa")({ 2 | dest: "public", 3 | }); 4 | 5 | /** @type {import("next").NextConfig} */ 6 | module.exports = withPWA({ 7 | reactStrictMode: true, 8 | experimental: { 9 | appDir: true, 10 | }, 11 | }); 12 | -------------------------------------------------------------------------------- /examples/custom-worker-webpack/pages/index.js: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | 3 | const Index = () => ( 4 | <> 5 | 6 | next-pwa example 7 | 8 |

Next.js + PWA = AWESOME!

9 | 10 | ); 11 | 12 | export default Index; 13 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # @imbios/next-pwa Docs 2 | 3 | ## Local Development 4 | 5 | First, run `pnpm i` to install the dependencies. 6 | 7 | Then, run `pnpm dev` to start the development server and visit localhost:3000. 8 | 9 | ## License 10 | 11 | This project is licensed under the MIT License. 12 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.defaultFormatter": "esbenp.prettier-vscode", 3 | // disable when disturbing styling on save with className sorter 4 | "editor.formatOnSave": true, 5 | "editor.codeActionsOnSave": { 6 | "source.fixAll": true, 7 | "source.organizeImports": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /docs/public/favicons/browserconfig.xml: -------------------------------------------------------------------------------- 1 | 2 | #ffffff -------------------------------------------------------------------------------- /examples/next-13/pages/about.js: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | import Link from "next/link"; 3 | 4 | const About = () => ( 5 | <> 6 | 7 | next-pwa example 8 | 9 |

About

10 | Home 11 | 12 | ); 13 | 14 | export default About; 15 | -------------------------------------------------------------------------------- /examples/next-image/pages/about.js: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | import Link from "next/link"; 3 | 4 | const About = () => ( 5 | <> 6 | 7 | next-pwa example 8 | 9 |

About

10 | Home 11 | 12 | ); 13 | 14 | export default About; 15 | -------------------------------------------------------------------------------- /examples/cookie/next.config.js: -------------------------------------------------------------------------------- 1 | const withPWA = require("@imbios/next-pwa")({ 2 | dest: "public", 3 | dynamicStartUrl: true, // this is same as default value 4 | dynamicStartUrlRedirect: "/login", // recommend to config this for best user experience if your start-url redirects on first load 5 | }); 6 | 7 | module.exports = withPWA(); 8 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json", 3 | "changelog": "@changesets/changelog-github", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "public", 8 | "baseBranch": "master", 9 | "updateInternalDependencies": "patch", 10 | "ignore": [] 11 | } 12 | -------------------------------------------------------------------------------- /examples/next-13/pages/index.js: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | import Link from "next/link"; 3 | 4 | const Index = () => ( 5 | <> 6 | 7 | next-pwa example 8 | 9 |

Next.js + PWA = AWESOME!

10 | About 11 | 12 | ); 13 | 14 | export default Index; 15 | -------------------------------------------------------------------------------- /packages/eslint-config-custom/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eslint-config-custom", 3 | "version": "0.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "dependencies": { 7 | "eslint-config-next": "13.4.13", 8 | "eslint-config-prettier": "8.10.0", 9 | "eslint-config-turbo": "1.10.12" 10 | }, 11 | "private": true 12 | } 13 | -------------------------------------------------------------------------------- /examples/offline-fallback/pages/fallback.js: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | 3 | const Fallback = () => ( 4 | <> 5 | 6 | next-pwa example 7 | 8 |

This is offline fallback page

9 |

When offline, any route will fallback to this page

10 | 11 | ); 12 | 13 | export default Fallback; 14 | -------------------------------------------------------------------------------- /examples/offline-fallback-v2/pages/_offline.js: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | 3 | const Fallback = () => ( 4 | <> 5 | 6 | next-pwa example 7 | 8 |

This is offline fallback page

9 |

When offline, any page route will fallback to this page

10 | 11 | ); 12 | 13 | export default Fallback; 14 | -------------------------------------------------------------------------------- /examples/cache-on-front-end-nav/worker/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | self.addEventListener("message", async (event) => { 4 | if (event.data && event.data.action === "CACHE_NEW_ROUTE") { 5 | caches.open("others").then((cache) => 6 | cache.match(event.source.url).then((res) => { 7 | if (res === undefined) { 8 | return cache.add(event.source.url); 9 | } 10 | }) 11 | ); 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /examples/next-i18next/pages/_app.tsx: -------------------------------------------------------------------------------- 1 | import type { AppProps } from "next/app"; 2 | import { appWithTranslation } from "next-i18next"; 3 | // import nextI18NextConfig from '../next-i18next.config.js' 4 | 5 | const MyApp = ({ Component, pageProps }: AppProps) => ( 6 | 7 | ); 8 | 9 | // https://github.com/i18next/next-i18next#unserializable-configs 10 | export default appWithTranslation(MyApp /*, nextI18NextConfig */); 11 | -------------------------------------------------------------------------------- /docs/pages/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "index": "Introduction", 3 | "get-started": "Get Started", 4 | "usage": "Usage", 5 | "offline-fallbacks": "Offline Fallbacks", 6 | "configuration": "Configuration", 7 | "tips": "Tips", 8 | "about": { 9 | "title": "About", 10 | "type": "page" 11 | }, 12 | "contact": { 13 | "title": "Contact ↗", 14 | "type": "page", 15 | "href": "https://twitter.com/imamdev_", 16 | "newWindow": true 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .next/ 2 | .turbo/ 3 | dist/ 4 | node_modules/ 5 | .changeset/ 6 | coverage/ 7 | dist/ 8 | storybook-static/ 9 | pnpm-lock.yaml 10 | yarn-error.log 11 | 12 | **/public/precache.*.*.js 13 | **/public/sw.js 14 | **/public/workbox-*.js 15 | **/public/worker-*.js 16 | **/public/fallback-*.js 17 | **/public/precache.*.*.js.map 18 | **/public/sw.js.map 19 | **/public/workbox-*.js.map 20 | **/public/worker-*.js.map 21 | **/public/fallback-*.js 22 | 23 | .turbo 24 | .dccache 25 | -------------------------------------------------------------------------------- /examples/custom-worker-webpack/next.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | 3 | const withPWA = require("@imbios/next-pwa")({ 4 | dest: "public", 5 | customWorkerWebpack(config) { 6 | return { 7 | ...config, 8 | resolve: { 9 | ...config.resolve, 10 | alias: { 11 | ...config.resolve.alias, 12 | "@util": path.resolve(__dirname, "./util"), 13 | }, 14 | }, 15 | }; 16 | }, 17 | }); 18 | 19 | module.exports = withPWA(); 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | yarn-error.log 3 | .next/ 4 | .env 5 | .env.*local 6 | 7 | **/public/precache.*.*.js 8 | **/public/sw.js 9 | **/public/workbox-*.js 10 | **/public/worker-*.js 11 | **/public/fallback-*.js 12 | **/public/precache.*.*.js.map 13 | **/public/sw.js.map 14 | **/public/workbox-*.js.map 15 | **/public/worker-*.js.map 16 | **/public/fallback-*.js 17 | 18 | examples/**/yarn.lock 19 | examples/**/package-lock.json 20 | examples/**/pnpm-lock.yaml 21 | 22 | .turbo 23 | .dccache 24 | -------------------------------------------------------------------------------- /examples/next-image/pages/index.js: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | import Link from "next/link"; 3 | import Image from "next/image"; 4 | 5 | import nextjsDark from "../images/nextjs-dark.svg"; 6 | 7 | const Index = () => ( 8 | <> 9 | 10 | next-pwa example 11 | 12 |

Next.js + PWA = AWESOME!

13 | 14 | About 15 | 16 | ); 17 | 18 | export default Index; 19 | -------------------------------------------------------------------------------- /examples/offline-fallback-v2/next.config.js: -------------------------------------------------------------------------------- 1 | const withPWA = require("@imbios/next-pwa")({ 2 | dest: "public", 3 | fallbacks: { 4 | image: "/static/images/fallback.png", 5 | // document: '/other-offline', // if you want to fallback to a custom page other than /_offline 6 | // font: '/static/font/fallback.woff2', 7 | // audio: ..., 8 | // video: ..., 9 | }, 10 | }); 11 | 12 | module.exports = withPWA({ 13 | images: { 14 | domains: ["source.unsplash.com"], 15 | }, 16 | }); 17 | -------------------------------------------------------------------------------- /examples/app-dir/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-app-dir", 3 | "private": true, 4 | "scripts": { 5 | "dev": "next dev", 6 | "build": "next build", 7 | "start": "next start" 8 | }, 9 | "dependencies": { 10 | "next": "13.3.2-canary.7", 11 | "react": "18.2.0", 12 | "react-dom": "18.2.0", 13 | "@imbios/next-pwa": "latest" 14 | }, 15 | "devDependencies": { 16 | "@types/node": "18.16.3", 17 | "@types/react": "18.0.35", 18 | "typescript": "4.9.5" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "globalDependencies": ["**/.env.*local"], 4 | "pipeline": { 5 | "build": { 6 | "outputs": [".next/**", "!.next/cache/**"], 7 | "env": [ 8 | "WEB_PUSH_EMAIL", 9 | "NEXT_PUBLIC_WEB_PUSH_PUBLIC_KEY", 10 | "WEB_PUSH_PRIVATE_KEY" 11 | ], 12 | "dependsOn": ["^build"] 13 | }, 14 | "lint": {}, 15 | "test": { 16 | "dependsOn": ["^build"] 17 | }, 18 | "clean": {} 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /examples/cache-on-front-end-nav/pages/a.js: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | import Link from "next/link"; 3 | 4 | const A = () => ( 5 | <> 6 | 7 | next-pwa example | Route a 8 | 9 |

This is route /a

10 |

11 | Go to Home 12 |

13 |

14 | Go to route /a 15 |

16 |

17 | Go to route /b 18 |

19 | 20 | ); 21 | 22 | export default A; 23 | -------------------------------------------------------------------------------- /examples/cache-on-front-end-nav/pages/b.js: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | import Link from "next/link"; 3 | 4 | const B = () => ( 5 | <> 6 | 7 | next-pwa example | Route b 8 | 9 |

This is route /b

10 |

11 | Go to Home 12 |

13 |

14 | Go to route /a 15 |

16 |

17 | Go to route /b 18 |

19 | 20 | ); 21 | 22 | export default B; 23 | -------------------------------------------------------------------------------- /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /examples/cache-on-front-end-nav/pages/index.js: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | import Link from "next/link"; 3 | 4 | const Index = () => ( 5 | <> 6 | 7 | next-pwa example | Home 8 | 9 |

Next.js + PWA = AWESOME!

10 |

11 | Go to Home 12 |

13 |

14 | Go to route /a 15 |

16 |

17 | Go to route /b 18 |

19 | 20 | ); 21 | 22 | export default Index; 23 | -------------------------------------------------------------------------------- /examples/app-dir/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env*.local 29 | 30 | # vercel 31 | .vercel 32 | 33 | # typescript 34 | *.tsbuildinfo 35 | next-env.d.ts 36 | -------------------------------------------------------------------------------- /examples/next-13/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-next-13", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "@imbios/next-pwa": "latest", 6 | "next": "13.3.2-canary.7", 7 | "react": "18.2.0", 8 | "react-dom": "18.2.0" 9 | }, 10 | "devDependencies": { 11 | "eslint": "8.30.0", 12 | "eslint-config-next": "13.3.0" 13 | }, 14 | "license": "MIT", 15 | "main": "index.js", 16 | "private": true, 17 | "scripts": { 18 | "build": "next build", 19 | "dev": "next", 20 | "start": "next start" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/lifecycle/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-lifecycle", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "@imbios/next-pwa": "latest", 6 | "next": "13.3.2-canary.7", 7 | "react": "18.2.0", 8 | "react-dom": "18.2.0" 9 | }, 10 | "devDependencies": { 11 | "eslint": "8.30.0", 12 | "eslint-config-next": "13.3.0" 13 | }, 14 | "license": "MIT", 15 | "main": "index.js", 16 | "private": true, 17 | "scripts": { 18 | "build": "next build", 19 | "dev": "next", 20 | "start": "next start" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/next-image/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-next-image", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "@imbios/next-pwa": "latest", 6 | "next": "13.3.2-canary.7", 7 | "react": "18.2.0", 8 | "react-dom": "18.2.0" 9 | }, 10 | "devDependencies": { 11 | "eslint": "8.30.0", 12 | "eslint-config-next": "13.3.0" 13 | }, 14 | "license": "MIT", 15 | "main": "index.js", 16 | "private": true, 17 | "scripts": { 18 | "build": "next build", 19 | "dev": "next", 20 | "start": "next start" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/next-i18next/components/Header.tsx: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | import type { FC } from "react"; 3 | 4 | type Props = { 5 | heading: string; 6 | title: string; 7 | }; 8 | 9 | export const Header: FC = ({ heading, title }) => ( 10 | <> 11 | 12 | {title} 13 | 14 |

15 | next-i18next 16 |
17 |

18 |

{heading}

19 | 20 | 21 | 22 | 23 | ); 24 | -------------------------------------------------------------------------------- /examples/cookie/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@imbios/next-pwa", 3 | "short_name": "@imbios/next-pwa", 4 | "display": "standalone", 5 | "orientation": "portrait", 6 | "theme_color": "#FFFFFF", 7 | "background_color": "#FFFFFF", 8 | "start_url": "/", 9 | "icons": [ 10 | { 11 | "src": "/icons/android-chrome-192x192.png", 12 | "sizes": "192x192", 13 | "type": "image/png", 14 | "purpose": "any maskable" 15 | }, 16 | { 17 | "src": "/icons/icon-512x512.png", 18 | "sizes": "512x512", 19 | "type": "image/png" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /examples/custom-worker-webpack/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "next-pwa", 3 | "short_name": "next-pwa", 4 | "display": "standalone", 5 | "orientation": "portrait", 6 | "theme_color": "#FFFFFF", 7 | "background_color": "#FFFFFF", 8 | "start_url": "/", 9 | "icons": [ 10 | { 11 | "src": "/icons/android-chrome-192x192.png", 12 | "sizes": "192x192", 13 | "type": "image/png", 14 | "purpose": "any maskable" 15 | }, 16 | { 17 | "src": "/icons/icon-512x512.png", 18 | "sizes": "512x512", 19 | "type": "image/png" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /examples/custom-worker/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-custom-worker", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "@imbios/next-pwa": "latest", 6 | "babel-loader": "8.2.5", 7 | "next": "13.3.2-canary.7", 8 | "react": "18.2.0", 9 | "react-dom": "18.2.0" 10 | }, 11 | "devDependencies": { 12 | "eslint": "8.30.0", 13 | "eslint-config-next": "13.3.0" 14 | }, 15 | "license": "MIT", 16 | "main": "index.js", 17 | "private": true, 18 | "scripts": { 19 | "build": "next build", 20 | "dev": "next", 21 | "start": "next start" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/offline-fallback-v2/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-offline-fallback-v2", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "@imbios/next-pwa": "latest", 6 | "babel-loader": "8.2.5", 7 | "eslint": "8.30.0", 8 | "eslint-config-next": "13.3.0", 9 | "next": "13.3.2-canary.7", 10 | "react": "18.2.0", 11 | "react-dom": "18.2.0", 12 | "sharp": "0.30.7" 13 | }, 14 | "license": "MIT", 15 | "main": "index.js", 16 | "private": true, 17 | "scripts": { 18 | "build": "next build", 19 | "dev": "next", 20 | "start": "next start" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/offline-fallback/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-offline-fallback", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "@imbios/next-pwa": "latest", 6 | "next": "13.3.2-canary.7", 7 | "react": "18.2.0", 8 | "react-dom": "18.2.0", 9 | "sharp": "0.30.7" 10 | }, 11 | "devDependencies": { 12 | "eslint": "8.30.0", 13 | "eslint-config-next": "13.3.0" 14 | }, 15 | "license": "MIT", 16 | "main": "index.js", 17 | "private": true, 18 | "scripts": { 19 | "build": "next build", 20 | "dev": "next", 21 | "start": "next start" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/app-dir/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@imbios/next-pwa", 3 | "short_name": "@imbios/next-pwa", 4 | "display": "standalone", 5 | "orientation": "portrait", 6 | "theme_color": "#FFFFFF", 7 | "background_color": "#FFFFFF", 8 | "start_url": "/", 9 | "icons": [ 10 | { 11 | "src": "/icons/android-chrome-192x192.png", 12 | "sizes": "192x192", 13 | "type": "image/png", 14 | "purpose": "any maskable" 15 | }, 16 | { 17 | "src": "/icons/icon-512x512.png", 18 | "sizes": "512x512", 19 | "type": "image/png" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /examples/cookie/README.md: -------------------------------------------------------------------------------- 1 | # next-pwa - cookie example 2 | 3 | [TOC] 4 | 5 | This example demonstrates how to use `next-pwa` with cookies. No special configuration needed with version 3+, enjoy🎉. 6 | 7 | ## Usage 8 | 9 | [![Open in Gitpod](https://img.shields.io/badge/Open%20In-Gitpod.io-%231966D2?style=for-the-badge&logo=gitpod)](https://gitpod.io/#https://github.com/shadowwalker/next-pwa/) 10 | 11 | ```bash 12 | cd examples/cookie 13 | yarn install 14 | yarn build 15 | yarn start 16 | ``` 17 | 18 | ## Recommend `.gitignore` 19 | 20 | ``` 21 | **/public/workbox-*.js 22 | **/public/sw.js 23 | ``` 24 | -------------------------------------------------------------------------------- /examples/lifecycle/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@imbios/next-pwa", 3 | "short_name": "@imbios/next-pwa", 4 | "display": "standalone", 5 | "orientation": "portrait", 6 | "theme_color": "#FFFFFF", 7 | "background_color": "#FFFFFF", 8 | "start_url": "/", 9 | "icons": [ 10 | { 11 | "src": "/icons/android-chrome-192x192.png", 12 | "sizes": "192x192", 13 | "type": "image/png", 14 | "purpose": "any maskable" 15 | }, 16 | { 17 | "src": "/icons/icon-512x512.png", 18 | "sizes": "512x512", 19 | "type": "image/png" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /examples/minimal/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@imbios/next-pwa", 3 | "short_name": "@imbios/next-pwa", 4 | "display": "standalone", 5 | "orientation": "portrait", 6 | "theme_color": "#FFFFFF", 7 | "background_color": "#FFFFFF", 8 | "start_url": "/", 9 | "icons": [ 10 | { 11 | "src": "/icons/android-chrome-192x192.png", 12 | "sizes": "192x192", 13 | "type": "image/png", 14 | "purpose": "any maskable" 15 | }, 16 | { 17 | "src": "/icons/icon-512x512.png", 18 | "sizes": "512x512", 19 | "type": "image/png" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /examples/next-13/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@imbios/next-pwa", 3 | "short_name": "@imbios/next-pwa", 4 | "display": "standalone", 5 | "orientation": "portrait", 6 | "theme_color": "#FFFFFF", 7 | "background_color": "#FFFFFF", 8 | "start_url": "/", 9 | "icons": [ 10 | { 11 | "src": "/icons/android-chrome-192x192.png", 12 | "sizes": "192x192", 13 | "type": "image/png", 14 | "purpose": "any maskable" 15 | }, 16 | { 17 | "src": "/icons/icon-512x512.png", 18 | "sizes": "512x512", 19 | "type": "image/png" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /examples/next-image/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@imbios/next-pwa", 3 | "short_name": "@imbios/next-pwa", 4 | "display": "standalone", 5 | "orientation": "portrait", 6 | "theme_color": "#FFFFFF", 7 | "background_color": "#FFFFFF", 8 | "start_url": "/", 9 | "icons": [ 10 | { 11 | "src": "/icons/android-chrome-192x192.png", 12 | "sizes": "192x192", 13 | "type": "image/png", 14 | "purpose": "any maskable" 15 | }, 16 | { 17 | "src": "/icons/icon-512x512.png", 18 | "sizes": "512x512", 19 | "type": "image/png" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /examples/web-push/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@imbios/next-pwa", 3 | "short_name": "@imbios/next-pwa", 4 | "display": "standalone", 5 | "orientation": "portrait", 6 | "theme_color": "#FFFFFF", 7 | "background_color": "#FFFFFF", 8 | "start_url": "/", 9 | "icons": [ 10 | { 11 | "src": "/icons/android-chrome-192x192.png", 12 | "sizes": "192x192", 13 | "type": "image/png", 14 | "purpose": "any maskable" 15 | }, 16 | { 17 | "src": "/icons/icon-512x512.png", 18 | "sizes": "512x512", 19 | "type": "image/png" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": false, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmit": true, 10 | "incremental": true, 11 | "esModuleInterop": true, 12 | "module": "esnext", 13 | "moduleResolution": "node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "jsx": "preserve" 17 | }, 18 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], 19 | "exclude": ["node_modules"] 20 | } 21 | -------------------------------------------------------------------------------- /examples/custom-ts-worker/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@imbios/next-pwa", 3 | "short_name": "@imbios/next-pwa", 4 | "display": "standalone", 5 | "orientation": "portrait", 6 | "theme_color": "#FFFFFF", 7 | "background_color": "#FFFFFF", 8 | "start_url": "/", 9 | "icons": [ 10 | { 11 | "src": "/icons/android-chrome-192x192.png", 12 | "sizes": "192x192", 13 | "type": "image/png", 14 | "purpose": "any maskable" 15 | }, 16 | { 17 | "src": "/icons/icon-512x512.png", 18 | "sizes": "512x512", 19 | "type": "image/png" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /examples/custom-worker/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@imbios/next-pwa", 3 | "short_name": "@imbios/next-pwa", 4 | "display": "standalone", 5 | "orientation": "portrait", 6 | "theme_color": "#FFFFFF", 7 | "background_color": "#FFFFFF", 8 | "start_url": "/", 9 | "icons": [ 10 | { 11 | "src": "/icons/android-chrome-192x192.png", 12 | "sizes": "192x192", 13 | "type": "image/png", 14 | "purpose": "any maskable" 15 | }, 16 | { 17 | "src": "/icons/icon-512x512.png", 18 | "sizes": "512x512", 19 | "type": "image/png" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /examples/next-i18next/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@imbios/next-pwa", 3 | "short_name": "@imbios/next-pwa", 4 | "display": "standalone", 5 | "orientation": "portrait", 6 | "theme_color": "#FFFFFF", 7 | "background_color": "#FFFFFF", 8 | "start_url": "/", 9 | "icons": [ 10 | { 11 | "src": "/icons/android-chrome-192x192.png", 12 | "sizes": "192x192", 13 | "type": "image/png", 14 | "purpose": "any maskable" 15 | }, 16 | { 17 | "src": "/icons/icon-512x512.png", 18 | "sizes": "512x512", 19 | "type": "image/png" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /examples/offline-fallback/pages/index.js: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | import Image from "next/image"; 3 | 4 | const Index = () => ( 5 | <> 6 | 7 | next-pwa example 8 | 9 |

Next.js + PWA = AWESOME!

10 |

Routes not cached will fallback to /_offline page

11 |

Following image will fallback to placeholder when offline

12 | random cat 18 | 19 | ); 20 | 21 | export default Index; 22 | -------------------------------------------------------------------------------- /examples/offline-fallback/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@imbios/next-pwa", 3 | "short_name": "@imbios/next-pwa", 4 | "display": "standalone", 5 | "orientation": "portrait", 6 | "theme_color": "#FFFFFF", 7 | "background_color": "#FFFFFF", 8 | "start_url": "/", 9 | "icons": [ 10 | { 11 | "src": "/icons/android-chrome-192x192.png", 12 | "sizes": "192x192", 13 | "type": "image/png", 14 | "purpose": "any maskable" 15 | }, 16 | { 17 | "src": "/icons/icon-512x512.png", 18 | "sizes": "512x512", 19 | "type": "image/png" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /examples/cache-on-front-end-nav/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-cache-on-front-end-nav", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "@imbios/next-pwa": "latest", 6 | "babel-loader": "8.2.5", 7 | "next": "13.3.2-canary.7", 8 | "react": "18.2.0", 9 | "react-dom": "18.2.0" 10 | }, 11 | "devDependencies": { 12 | "eslint": "8.30.0", 13 | "eslint-config-next": "13.3.0" 14 | }, 15 | "license": "MIT", 16 | "main": "index.js", 17 | "private": true, 18 | "scripts": { 19 | "build": "next build", 20 | "dev": "next", 21 | "start": "next start" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/cookie/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-cookie", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "@imbios/next-pwa": "latest", 6 | "js-cookie": "3.0.1", 7 | "next": "13.3.2-canary.7", 8 | "next-cookies": "2.0.3", 9 | "react": "18.2.0", 10 | "react-dom": "18.2.0" 11 | }, 12 | "devDependencies": { 13 | "eslint": "8.30.0", 14 | "eslint-config-next": "13.3.0" 15 | }, 16 | "license": "MIT", 17 | "main": "index.js", 18 | "private": true, 19 | "scripts": { 20 | "build": "next build", 21 | "dev": "next", 22 | "start": "next start" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/custom-worker-webpack/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-custom-worker-webpack", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "@imbios/next-pwa": "latest", 6 | "babel-loader": "8.2.5", 7 | "next": "13.3.2-canary.7", 8 | "react": "18.2.0", 9 | "react-dom": "18.2.0" 10 | }, 11 | "devDependencies": { 12 | "eslint": "8.30.0", 13 | "eslint-config-next": "13.3.0" 14 | }, 15 | "license": "MIT", 16 | "main": "index.js", 17 | "private": true, 18 | "scripts": { 19 | "build": "next build", 20 | "dev": "next", 21 | "start": "next start" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/offline-fallback-v2/pages/index.js: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | import Image from "next/image"; 3 | 4 | const Index = () => ( 5 | <> 6 | 7 | next-pwa example 8 | 9 |

Next.js + PWA = AWESOME!

10 |

Routes not cached will fallback to /_offline page

11 |

Following image will fallback to placeholder when offline

12 | random cat 18 | 19 | ); 20 | 21 | export default Index; 22 | -------------------------------------------------------------------------------- /examples/offline-fallback-v2/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@imbios/next-pwa", 3 | "short_name": "@imbios/next-pwa", 4 | "display": "standalone", 5 | "orientation": "portrait", 6 | "theme_color": "#FFFFFF", 7 | "background_color": "#FFFFFF", 8 | "start_url": "/", 9 | "icons": [ 10 | { 11 | "src": "/icons/android-chrome-192x192.png", 12 | "sizes": "192x192", 13 | "type": "image/png", 14 | "purpose": "any maskable" 15 | }, 16 | { 17 | "src": "/icons/icon-512x512.png", 18 | "sizes": "512x512", 19 | "type": "image/png" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /examples/cache-on-front-end-nav/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@imbios/next-pwa", 3 | "short_name": "@imbios/next-pwa", 4 | "display": "standalone", 5 | "orientation": "portrait", 6 | "theme_color": "#FFFFFF", 7 | "background_color": "#FFFFFF", 8 | "start_url": "/", 9 | "icons": [ 10 | { 11 | "src": "/icons/android-chrome-192x192.png", 12 | "sizes": "192x192", 13 | "type": "image/png", 14 | "purpose": "any maskable" 15 | }, 16 | { 17 | "src": "/icons/icon-512x512.png", 18 | "sizes": "512x512", 19 | "type": "image/png" 20 | } 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /docs/pages/get-started.mdx: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | > If you are new to `next.js` or `react.js` at all, you may want to first checkout [learn next.js](https://nextjs.org/learn/basics/create-nextjs-app) or [next.js document](https://nextjs.org/docs/getting-started). Then start from [a simple example](https://github.com/ImBIOS/next-pwa/tree/master/examples/next-13) or [progressive-web-app example in next.js repository](https://github.com/vercel/next.js/tree/canary/examples/progressive-web-app). 4 | 5 | ```sh 6 | pnpm add @imbios/next-pwa 7 | # or 8 | yarn add @imbios/next-pwa 9 | # or 10 | npm install @imbios/next-pwa 11 | ``` 12 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "next-pwa-docs", 3 | "description": "@imbios/next-pwa documentation", 4 | "version": "0.0.1", 5 | "author": "Imamuzzaki Abu Salam ", 6 | "dependencies": { 7 | "next": "13.4.13", 8 | "nextra": "2.10.0", 9 | "nextra-theme-docs": "2.10.0", 10 | "react": "18.2.0", 11 | "react-dom": "18.2.0" 12 | }, 13 | "devDependencies": { 14 | "@types/node": "18.17.4", 15 | "typescript": "4.9.5" 16 | }, 17 | "license": "MIT", 18 | "scripts": { 19 | "build": "next build", 20 | "dev": "next dev", 21 | "start": "next start" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/cookie/pages/login.js: -------------------------------------------------------------------------------- 1 | import Head from "next/head"; 2 | import { useRouter } from "next/router"; 3 | import Cookies from "js-cookie"; 4 | 5 | const Login = () => { 6 | const router = useRouter(); 7 | 8 | const handleLoginClick = () => { 9 | Cookies.set("user", "FakeUserID-0527VND927SDF", { expires: 30 }); 10 | router.replace("/"); 11 | }; 12 | 13 | return ( 14 | <> 15 | 16 | Login | next-pwa example 17 | 18 |

Login Page

19 | 20 | 21 | ); 22 | }; 23 | 24 | export default Login; 25 | -------------------------------------------------------------------------------- /examples/custom-ts-worker/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-custom-ts-worker", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "@imbios/next-pwa": "latest", 6 | "babel-loader": "8.2.5", 7 | "next": "13.3.2-canary.7", 8 | "react": "18.2.0", 9 | "react-dom": "18.2.0" 10 | }, 11 | "devDependencies": { 12 | "@types/react": "18.0.35", 13 | "eslint": "8.30.0", 14 | "eslint-config-next": "13.3.0", 15 | "typescript": "4.9.5" 16 | }, 17 | "license": "MIT", 18 | "main": "index.js", 19 | "private": true, 20 | "scripts": { 21 | "build": "next build", 22 | "dev": "next", 23 | "start": "next start" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/web-push/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-web-push", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "@imbios/next-pwa": "latest", 6 | "babel-loader": "8.2.5", 7 | "next": "13.3.2-canary.7", 8 | "react": "18.2.0", 9 | "react-dom": "18.2.0", 10 | "web-push": "3.5.0" 11 | }, 12 | "devDependencies": { 13 | "eslint": "8.30.0", 14 | "eslint-config-next": "13.3.0" 15 | }, 16 | "license": "MIT", 17 | "main": "index.js", 18 | "private": true, 19 | "scripts": { 20 | "build": "next build", 21 | "dev": "next", 22 | "start": "next start", 23 | "vapid": "web-push generate-vapid-keys" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/minimal/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-minimal", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "@imbios/next-pwa": "latest", 6 | "cross-env": "7.0.3", 7 | "fastify": "3.29.0", 8 | "fastify-compress": "4.1.0", 9 | "next": "13.3.2-canary.7", 10 | "react": "18.2.0", 11 | "react-dom": "18.2.0" 12 | }, 13 | "devDependencies": { 14 | "eslint": "8.30.0", 15 | "eslint-config-next": "13.3.0" 16 | }, 17 | "license": "MIT", 18 | "main": "index.js", 19 | "private": true, 20 | "scripts": { 21 | "build": "next build", 22 | "dev": "node ./index.js", 23 | "start": "cross-env NODE_ENV=production node ./index.js" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/app-dir/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "strict": false, 8 | "forceConsistentCasingInFileNames": true, 9 | "noEmit": true, 10 | "incremental": true, 11 | "esModuleInterop": true, 12 | "module": "esnext", 13 | "moduleResolution": "node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "jsx": "preserve", 17 | "plugins": [ 18 | { 19 | "name": "next" 20 | } 21 | ] 22 | }, 23 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], 24 | "exclude": ["node_modules"] 25 | } 26 | -------------------------------------------------------------------------------- /examples/custom-ts-worker/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true, 4 | "alwaysStrict": true, 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "isolatedModules": true, 8 | "jsx": "preserve", 9 | "lib": ["dom", "es2017"], 10 | "module": "esnext", 11 | "moduleResolution": "node", 12 | "noEmit": true, 13 | "noFallthroughCasesInSwitch": true, 14 | "noUnusedLocals": true, 15 | "noUnusedParameters": true, 16 | "resolveJsonModule": true, 17 | "skipLibCheck": true, 18 | "strict": true, 19 | "target": "esnext", 20 | "incremental": true 21 | }, 22 | "exclude": ["node_modules"], 23 | "include": ["**/*.ts", "**/*.tsx"] 24 | } 25 | -------------------------------------------------------------------------------- /examples/next-i18next/next-utils.config.js: -------------------------------------------------------------------------------- 1 | const pc = require("picocolors"); 2 | 3 | const nextUtilsConfig = () => { 4 | const trueEnv = ["true", "1", "yes"]; 5 | const esmExternals = trueEnv.includes( 6 | process.env?.NEXTJS_ESM_EXTERNALS ?? "false" 7 | ); 8 | const tsconfigPath = process.env.NEXTJS_TSCONFIG_PATH 9 | ? process.env.NEXTJS_TSCONFIG_PATH 10 | : "./tsconfig.json"; 11 | 12 | // eslint-disable-next-line no-console 13 | console.warn( 14 | `${pc.green("warn -")} experimental.esmExternals is ${ 15 | esmExternals ? "enabled" : "disabled" 16 | }` 17 | ); 18 | return { 19 | esmExternals, 20 | tsconfigPath, 21 | }; 22 | }; 23 | 24 | module.exports = { 25 | loadCustomBuildParams: nextUtilsConfig, 26 | }; 27 | -------------------------------------------------------------------------------- /syncpack.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | customTypes: [], 3 | dependencyTypes: [ 4 | "dev", 5 | "overrides", 6 | "peer", 7 | "pnpmOverrides", 8 | "prod", 9 | "resolutions", 10 | "workspace", 11 | ], 12 | filter: ".", 13 | indent: " ", 14 | semverGroups: [], 15 | semverRange: "", 16 | sortAz: [ 17 | "contributors", 18 | "dependencies", 19 | "devDependencies", 20 | "keywords", 21 | "peerDependencies", 22 | "resolutions", 23 | "scripts", 24 | ], 25 | sortFirst: ["name", "description", "version", "author"], 26 | source: [ 27 | "package.json", 28 | "docs/package.json", 29 | "examples/*/package.json", 30 | "packages/*/package.json", 31 | ], 32 | versionGroups: [], 33 | }; 34 | -------------------------------------------------------------------------------- /examples/next-i18next/@types/i18next.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * If you want to enable locale keys typechecking and enhance IDE experience. 3 | * 4 | * Requires `resolveJsonModule:true` in your tsconfig.json. 5 | * 6 | * @link https://www.i18next.com/overview/typescript 7 | */ 8 | import "i18next"; 9 | 10 | import type common from "../public/locales/en/common.json"; 11 | import type footer from "../public/locales/en/footer.json"; 12 | import type secondPage from "../public/locales/en/second-page.json"; 13 | 14 | interface I18nNamespaces { 15 | common: typeof common; 16 | footer: typeof footer; 17 | "second-page": typeof secondPage; 18 | } 19 | 20 | declare module "i18next" { 21 | interface CustomTypeOptions { 22 | defaultNS: "common"; 23 | resources: I18nNamespaces; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/custom-worker/worker/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // To disable all workbox logging during development, you can set self.__WB_DISABLE_DEV_LOGS to true 4 | // https://developers.google.com/web/tools/workbox/guides/configure-workbox#disable_logging 5 | // 6 | // self.__WB_DISABLE_DEV_LOGS = true 7 | 8 | const util = require("./util"); 9 | 10 | util(); 11 | 12 | // listen to message event from window 13 | self.addEventListener("message", (event) => { 14 | // HOW TO TEST THIS? 15 | // Run this in your browser console: 16 | // window.navigator.serviceWorker.controller.postMessage({command: 'log', message: 'hello world'}) 17 | // OR use next-pwa injected workbox object 18 | // window.workbox.messageSW({command: 'log', message: 'hello world'}) 19 | console.log(event.data); 20 | }); 21 | -------------------------------------------------------------------------------- /examples/custom-worker-webpack/worker/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | // To disable all workbox logging during development, you can set self.__WB_DISABLE_DEV_LOGS to true 4 | // https://developers.google.com/web/tools/workbox/guides/configure-workbox#disable_logging 5 | // 6 | // self.__WB_DISABLE_DEV_LOGS = true 7 | 8 | const util = require("@util"); 9 | 10 | util(); 11 | 12 | // listen to message event from window 13 | self.addEventListener("message", (event) => { 14 | // HOW TO TEST THIS? 15 | // Run this in your browser console: 16 | // window.navigator.serviceWorker.controller.postMessage({command: 'log', message: 'hello world'}) 17 | // OR use next-pwa injected workbox object 18 | // window.workbox.messageSW({command: 'log', message: 'hello world'}) 19 | console.log(event.data); 20 | }); 21 | -------------------------------------------------------------------------------- /examples/next-i18next/next.config.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | const { i18n } = require("./next-i18next.config.js"); 3 | 4 | // You can remove the following 2 lines when integrating our example. 5 | const { loadCustomBuildParams } = require("./next-utils.config"); 6 | const { esmExternals = false, tsconfigPath } = loadCustomBuildParams(); 7 | 8 | // TODO: Work on the Typescript support 9 | // @ts-expect-error 10 | const withPWA = require("@imbios/next-pwa")({ 11 | dest: "public", 12 | }); 13 | 14 | /** @type {import('next').NextConfig} */ 15 | const nextConfig = withPWA({ 16 | experimental: { 17 | esmExternals, // https://nextjs.org/blog/next-11-1#es-modules-support 18 | }, 19 | i18n, 20 | reactStrictMode: true, 21 | typescript: { 22 | tsconfigPath, 23 | }, 24 | }); 25 | 26 | module.exports = nextConfig; 27 | -------------------------------------------------------------------------------- /examples/next-i18next/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "compilerOptions": { 4 | "target": "esnext", 5 | "lib": ["dom", "dom.iterable", "esnext"], 6 | "baseUrl": ".", 7 | "allowJs": true, 8 | "skipLibCheck": true, 9 | "strict": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "noEmit": true, 12 | "esModuleInterop": true, 13 | "module": "esnext", 14 | "moduleResolution": "node", 15 | "resolveJsonModule": true, 16 | "isolatedModules": true, 17 | "jsx": "preserve", 18 | "incremental": true 19 | }, 20 | "include": [ 21 | "next-env.d.ts", 22 | "**/*.ts", 23 | "**/*.tsx", 24 | "**/*.js", 25 | "**/*.jsx", 26 | "**/*.cjs", 27 | "**/*.mjs" 28 | ], 29 | "exclude": ["**/node_modules", "**/.*/"] 30 | } 31 | -------------------------------------------------------------------------------- /packages/next-pwa/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@imbios/next-pwa", 3 | "description": "Next.js with PWA, powered by workbox.", 4 | "version": "1.1.1", 5 | "author": "Imamuzzaki Abu Salam ", 6 | "dependencies": { 7 | "babel-loader": "8.3.0", 8 | "clean-webpack-plugin": "4.0.0", 9 | "globby": "11.1.0", 10 | "terser-webpack-plugin": "5.3.9", 11 | "workbox-webpack-plugin": "6.6.1", 12 | "workbox-window": "6.6.1" 13 | }, 14 | "devDependencies": { 15 | "webpack": "5.88.2" 16 | }, 17 | "keywords": [ 18 | "nextjs", 19 | "pwa", 20 | "service-worker", 21 | "web", 22 | "workbox" 23 | ], 24 | "license": "MIT", 25 | "main": "index.js", 26 | "peerDependencies": { 27 | "next": ">=9.0.0" 28 | }, 29 | "resolutions": { 30 | "@typescript-eslint/eslint-plugin": "5.62.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /examples/next-image/README.md: -------------------------------------------------------------------------------- 1 | # next-pwa - next-image example 2 | 3 | [TOC] 4 | 5 | This example demonstrates best practices to serve your images through `next.js` built-in image serving feature. 6 | 7 | For best performance, put images in it's own folder other than `public`. This will prevent duplicate precaching entries in the `sw.js` service worker script. Then `import Image from 'next/image'` to use the `Image` component provided from `next.js` in your app. 8 | 9 | ## Usage 10 | 11 | [![Open in Gitpod](https://img.shields.io/badge/Open%20In-Gitpod.io-%231966D2?style=for-the-badge&logo=gitpod)](https://gitpod.io/#https://github.com/shadowwalker/next-pwa/) 12 | 13 | ```bash 14 | cd examples/next-image 15 | yarn install 16 | yarn build 17 | yarn start 18 | ``` 19 | 20 | ## Recommend `.gitignore` 21 | 22 | ``` 23 | **/public/workbox-*.js 24 | **/public/sw.js 25 | ``` 26 | -------------------------------------------------------------------------------- /examples/next-i18next/next-i18next.config.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | /** 4 | * @type {import('next-i18next').UserConfig} 5 | */ 6 | module.exports = { 7 | // https://www.i18next.com/overview/configuration-options#logging 8 | debug: process.env.NODE_ENV === "development", 9 | i18n: { 10 | defaultLocale: "en", 11 | locales: ["en", "de"], 12 | }, 13 | /** To avoid issues when deploying to some paas (vercel...) */ 14 | localePath: 15 | typeof window === "undefined" 16 | ? require("path").resolve("./public/locales") 17 | : "/locales", 18 | 19 | reloadOnPrerender: process.env.NODE_ENV === "development", 20 | 21 | /** 22 | * @link https://github.com/i18next/next-i18next#6-advanced-configuration 23 | */ 24 | // saveMissing: false, 25 | // strictMode: true, 26 | // serializeConfig: false, 27 | // react: { useSuspense: false } 28 | }; 29 | -------------------------------------------------------------------------------- /docs/public/favicons/safari-pinned-tab.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/minimal/README.md: -------------------------------------------------------------------------------- 1 | # next-pwa - minimal example 2 | 3 | [TOC] 4 | 5 | This example demonstrates how to use `next-pwa` plugin to turn a `next.js` based web application into a progressive web application easily. 6 | 7 | It uses `fastify` as a custom server in order to serve `sw.js` and `precache` script statically, and it contains minimal icon set and a `manifest.json` in static folder. The example also features full offline support and full (all 100) scores on lighthouse report. 8 | 9 | > [Check out the lighthouse summary](https://github.com/shadowwalker/next-pwa/blob/master/examples/minimal/lighthouse.pdf), or run the test your self. 10 | 11 | ## Usage 12 | 13 | [![Open in Gitpod](https://img.shields.io/badge/Open%20In-Gitpod.io-%231966D2?style=for-the-badge&logo=gitpod)](https://gitpod.io/#https://github.com/shadowwalker/next-pwa/) 14 | 15 | ```bash 16 | cd examples/minimal 17 | yarn install 18 | yarn build 19 | yarn start 20 | ``` 21 | -------------------------------------------------------------------------------- /examples/next-i18next/components/Footer.tsx: -------------------------------------------------------------------------------- 1 | import pkg from "next-i18next/package.json"; 2 | import { useTranslation, Trans } from "next-i18next"; 3 | import type { FC } from "react"; 4 | 5 | export const Footer: FC = () => { 6 | const { t } = useTranslation("footer"); 7 | 8 | return ( 9 |
10 |

{t("description")}

11 |

next-i18next v{pkg.version}

12 |

19 | 20 | With using 21 | 22 | locize 23 | 24 | you directly support the future of 25 | 26 | i18next 27 | 28 | . 29 | 30 |

31 |
32 | ); 33 | }; 34 | -------------------------------------------------------------------------------- /examples/next-i18next/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "example-next-i18next", 3 | "version": "1.0.0", 4 | "dependencies": { 5 | "@imbios/next-pwa": "latest", 6 | "i18next": "22.4.14", 7 | "next": "13.3.2-canary.7", 8 | "next-i18next": "13.2.2", 9 | "react": "18.2.0", 10 | "react-dom": "18.2.0", 11 | "react-i18next": "12.2.0" 12 | }, 13 | "devDependencies": { 14 | "@types/node": "18.16.3", 15 | "@types/react": "18.0.35", 16 | "@types/react-dom": "18.0.11", 17 | "eslint-config-next": "13.3.0", 18 | "picocolors": "1.0.0", 19 | "rimraf": "5.0.0", 20 | "typescript": "4.9.5" 21 | }, 22 | "license": "MIT", 23 | "main": "index.js", 24 | "scripts": { 25 | "build": "next build", 26 | "clean": "rimraf .next", 27 | "dev": "next", 28 | "nuke:install": "rimraf ./node_modules ./package-lock.json", 29 | "start": "next start -p ${PORT:=3000}", 30 | "typecheck": "tsc --project ./tsconfig.json --noEmit" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /.github/workflows/build-examples.yml: -------------------------------------------------------------------------------- 1 | name: Build Examples 2 | 3 | on: 4 | push: 5 | branches: [master, develop] 6 | pull_request: 7 | branches: [master, develop] 8 | 9 | jobs: 10 | build: 11 | name: Build Example 12 | timeout-minutes: 15 13 | runs-on: ubuntu-latest 14 | # TODO: Setup Environment Variables in Repository Settings 15 | env: 16 | TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} 17 | TURBO_TEAM: ${{ secrets.TURBO_TEAM }} 18 | steps: 19 | - name: 📂 Checkout 20 | uses: actions/checkout@v3 21 | - name: 📦 Install PNPM 22 | uses: pnpm/action-setup@v2 23 | with: 24 | version: 8 25 | - name: 📦 Install Node.js 26 | uses: actions/setup-node@v3 27 | with: 28 | node-version-file: .node-version 29 | cache: "pnpm" 30 | - name: 📦 Install Dependencies 31 | run: pnpm install 32 | - name: 📦 Build Example 33 | run: pnpm run build 34 | # - name: 🧪 Test Example 35 | # run: pnpm run test 36 | -------------------------------------------------------------------------------- /examples/next-13/README.md: -------------------------------------------------------------------------------- 1 | # next-pwa - next.js 9+ example 2 | 3 | [TOC] 4 | 5 | This example demonstrates how to use `next-pwa` plugin to turn a `next.js` based web application into a progressive web application easily. 6 | 7 | Thanks to **Next.js 9+**, we can use `public` folder to serve static files from root url path. It cuts the need to write custom server only to serve those files. Therefore the setup is more easy and concise. We can use `next.config.js` to config `next-pwa` to generates service worker and precache files into `public` folder. 8 | 9 | > [Check out the lighthouse summary](https://github.com/shadowwalker/next-pwa/blob/master/examples/next-9/lighthouse.pdf), or run the test your self. 10 | 11 | ## Usage 12 | 13 | [![Open in Gitpod](https://img.shields.io/badge/Open%20In-Gitpod.io-%231966D2?style=for-the-badge&logo=gitpod)](https://gitpod.io/#https://github.com/shadowwalker/next-pwa/) 14 | 15 | ```bash 16 | cd examples/next-9 17 | yarn install 18 | yarn build 19 | yarn start 20 | ``` 21 | 22 | ## Recommend `.gitignore` 23 | 24 | ``` 25 | **/public/workbox-*.js 26 | **/public/sw.js 27 | ``` 28 | -------------------------------------------------------------------------------- /examples/next-i18next/public/locales/en/common.json: -------------------------------------------------------------------------------- 1 | { 2 | "h1": "A simple example", 3 | "change-locale": "Change locale to \"{{changeTo}}\"", 4 | "to-second-page": "To second page", 5 | "error-with-status": "A {{statusCode}} error occurred on server", 6 | "error-without-status": "An error occurred on the server", 7 | "title": "Home | next-i18next", 8 | "blog": { 9 | "appDir": { 10 | "question": "Are you using the new Next.js 13 app directory?", 11 | "answer": "Then check out <1>this blog post.", 12 | "link": "https://locize.com/blog/next-13-app-dir-i18n/" 13 | }, 14 | "optimized": { 15 | "question": "Do you like to unleash some super powers to have all side optimized translations?", 16 | "answer": "Then you may have a look at <1>this blog post.", 17 | "link": "https://locize.com/blog/next-i18next/" 18 | }, 19 | "ssg": { 20 | "question": "Do you want to use SSG (next export)?", 21 | "answer": "Then you may have a look at <1>this blog post.", 22 | "link": "https://locize.com/blog/next-i18n-static/" 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /examples/web-push/pages/api/notification.js: -------------------------------------------------------------------------------- 1 | const webPush = require("web-push"); 2 | 3 | webPush.setVapidDetails( 4 | `mailto:${process.env.WEB_PUSH_EMAIL}`, 5 | process.env.NEXT_PUBLIC_WEB_PUSH_PUBLIC_KEY, 6 | process.env.WEB_PUSH_PRIVATE_KEY 7 | ); 8 | 9 | const Notification = (req, res) => { 10 | if (req.method == "POST") { 11 | const { subscription } = req.body; 12 | 13 | webPush 14 | .sendNotification( 15 | subscription, 16 | JSON.stringify({ 17 | title: "Hello Web Push", 18 | message: "Your web push notification is here!", 19 | }) 20 | ) 21 | .then((response) => { 22 | res.writeHead(response.statusCode, response.headers).end(response.body); 23 | }) 24 | .catch((err) => { 25 | if ("statusCode" in err) { 26 | res.writeHead(err.statusCode, err.headers).end(err.body); 27 | } else { 28 | console.error(err); 29 | res.statusCode = 500; 30 | res.end(); 31 | } 32 | }); 33 | } else { 34 | res.statusCode = 405; 35 | res.end(); 36 | } 37 | }; 38 | 39 | export default Notification; 40 | -------------------------------------------------------------------------------- /examples/app-dir/app/page.tsx: -------------------------------------------------------------------------------- 1 | import { Metadata } from "next"; 2 | 3 | /** Add your relevant code here for the issue to reproduce */ 4 | export default function Home() { 5 | return

PWA 💖 Next.js

; 6 | } 7 | 8 | const APP_NAME = "next-pwa example"; 9 | const APP_DESCRIPTION = "This is an example of using next-pwa plugin"; 10 | 11 | export const metadata: Metadata = { 12 | title: "PWA 💖 Next.js", 13 | description: APP_DESCRIPTION, 14 | twitter: { 15 | card: "summary_large_image", 16 | creator: "@imamdev_", 17 | images: "https://example.com/og.png", 18 | }, 19 | applicationName: APP_NAME, 20 | appleWebApp: { 21 | capable: true, 22 | title: APP_NAME, 23 | statusBarStyle: "default", 24 | }, 25 | formatDetection: { 26 | telephone: false, 27 | }, 28 | themeColor: "#FFFFFF", 29 | viewport: 30 | "minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no, viewport-fit=cover", 31 | manifest: "/manifest.json", 32 | icons: [ 33 | { rel: "apple-touch-icon", url: "/icons/apple-touch-icon.png" }, 34 | { rel: "shortcut icon", url: "/favicon.ico" }, 35 | ], 36 | keywords: ["nextjs", "pwa", "next-pwa"], 37 | }; 38 | -------------------------------------------------------------------------------- /docs/public/favicons/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@imbios/next-pwa Documentation", 3 | "short_name": "@imbios/next-pwa Docs", 4 | "icons": [ 5 | { 6 | "src": "/android-icon-36x36.png", 7 | "sizes": "36x36", 8 | "type": "image/png", 9 | "density": "0.75" 10 | }, 11 | { 12 | "src": "/android-icon-48x48.png", 13 | "sizes": "48x48", 14 | "type": "image/png", 15 | "density": "1.0" 16 | }, 17 | { 18 | "src": "/android-icon-72x72.png", 19 | "sizes": "72x72", 20 | "type": "image/png", 21 | "density": "1.5" 22 | }, 23 | { 24 | "src": "/android-icon-96x96.png", 25 | "sizes": "96x96", 26 | "type": "image/png", 27 | "density": "2.0" 28 | }, 29 | { 30 | "src": "/android-icon-144x144.png", 31 | "sizes": "144x144", 32 | "type": "image/png", 33 | "density": "3.0" 34 | }, 35 | { 36 | "src": "/android-icon-192x192.png", 37 | "sizes": "192x192", 38 | "type": "image/png", 39 | "density": "4.0" 40 | } 41 | ], 42 | "theme_color": "#000000", 43 | "background_color": "#000000", 44 | "display": "standalone" 45 | } 46 | -------------------------------------------------------------------------------- /examples/web-push/README.md: -------------------------------------------------------------------------------- 1 | # next-pwa - web push example 2 | 3 | [TOC] 4 | 5 | This example demonstrates how to use `next-pwa` plugin to implement web push with custom worker. 6 | 7 | **NOTE** 8 | 9 | In real world, you may want to send the subscription data to your server once user agree to subscribe web push. Store the data associate with the user. So that you can initiate a web push notification from your server to the specific users. 10 | 11 | ## Usage 12 | 13 | [![Open in Gitpod](https://img.shields.io/badge/Open%20In-Gitpod.io-%231966D2?style=for-the-badge&logo=gitpod)](https://gitpod.io/#https://github.com/shadowwalker/next-pwa/) 14 | 15 | ```bash 16 | cd examples/web-push 17 | yarn install 18 | yarn vapid 19 | ``` 20 | 21 | Create a `.env` file, and put the public key generated from the previous steps 22 | 23 | ``` 24 | WEB_PUSH_EMAIL=user@example.com 25 | WEB_PUSH_PRIVATE_KEY= 26 | NEXT_PUBLIC_WEB_PUSH_PUBLIC_KEY= 27 | ``` 28 | 29 | Build and start 30 | 31 | ```bash 32 | yarn build 33 | yarn start 34 | ``` 35 | 36 | ## Recommend `.gitignore` 37 | 38 | ``` 39 | **/public/workbox-*.js 40 | **/public/sw.js 41 | **/public/worker-*.js 42 | ``` 43 | -------------------------------------------------------------------------------- /examples/next-i18next/public/locales/de/common.json: -------------------------------------------------------------------------------- 1 | { 2 | "h1": "Ein einfaches Beispiel", 3 | "change-locale": "Sprache wechseln zu \"{{changeTo}}\"", 4 | "to-second-page": "Zur zweiten Seite", 5 | "error-with-status": "Auf dem Server ist ein Fehler ({{statusCode}}) aufgetreten", 6 | "error-without-status": "Auf dem Server ist ein Fehler aufgetreten", 7 | "title": "Hauptseite | next-i18next", 8 | "blog": { 9 | "appDir": { 10 | "question": "Verwendest du das neue Next.js 13 mit app directory?", 11 | "answer": "Dann schau dir <1>diesen Blogbeitrag an.", 12 | "link": "https://locize.com/blog/next-13-app-dir-i18n/" 13 | }, 14 | "optimized": { 15 | "question": "Möchtest du einige Superkräfte entfesseln, um für alle Seiten optimierte Übersetzungen zu haben?", 16 | "answer": "Dann schaue dir vielleicht <1>diesen Blogbeitrag an.", 17 | "link": "https://locize.com/blog/next-i18next-de/" 18 | }, 19 | "ssg": { 20 | "question": "Möchtest du SSG (next export) verwenden?", 21 | "answer": "Dann schaue dir vielleicht <1>diesen Blogbeitrag an.", 22 | "link": "https://locize.com/blog/next-i18n-statisch/" 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.github/workflows/npm-publish.yml: -------------------------------------------------------------------------------- 1 | name: Node.js Package 2 | 3 | on: 4 | release: 5 | types: [created] 6 | 7 | concurrency: ${{ github.workflow }}-${{ github.ref }} 8 | 9 | jobs: 10 | publish-npm: 11 | name: Publish to NPM 12 | timeout-minutes: 15 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: 📂 Checkout 16 | uses: actions/checkout@v3 17 | - name: 📦 Install PNPM 18 | uses: pnpm/action-setup@v2 19 | with: 20 | version: 8 21 | - name: 📦 Install Node.js 22 | uses: actions/setup-node@v3 23 | with: 24 | cache: "pnpm" 25 | node-version-file: .node-version 26 | registry-url: https://registry.npmjs.org/ 27 | scope: "@imbios" 28 | - name: 📦 Install Dependencies 29 | run: pnpm install 30 | - name: Publish to npm 31 | id: changesets 32 | uses: changesets/action@v1 33 | with: 34 | # This expects you to have a script called publish-packages which does a build for your packages and calls changeset publish 35 | publish: pnpm publish-packages 36 | env: 37 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 38 | NPM_TOKEN: ${{secrets.NPM_AUTOMATION_TOKEN}} 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 ShadowWalker w@weiw.io 4 | Copyright (c) 2023 Imamuzzaki Abu Salam imamuzzaki@gmail.com 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /examples/next-i18next/pages/second-page.tsx: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | import type { GetServerSideProps, InferGetServerSidePropsType } from "next"; 3 | 4 | import { useTranslation } from "next-i18next"; 5 | import { serverSideTranslations } from "next-i18next/serverSideTranslations"; 6 | 7 | import { Header } from "../components/Header"; 8 | import { Footer } from "../components/Footer"; 9 | 10 | type Props = { 11 | // Add custom props here 12 | }; 13 | 14 | const SecondPage = ( 15 | _props: InferGetServerSidePropsType 16 | ) => { 17 | const { t } = useTranslation(["common", "second-page"]); 18 | 19 | return ( 20 | <> 21 |
22 |
23 | 24 | 25 | 26 |
27 |