A lightweight, standalone package to integrate full PWA features into Remix 💿

Overview
remix-pwa

Remix PWA

PWA integration & support for Remix

stars issues License

Remix PWA is a lightweight, standalone npm package that adds full Progressive Web App support to Remix 💿 .

Features

  • Integrates Progressive Web App (PWA) features into Remix including offline support, caching, installability on Native devices and more.
  • Automatic caching for build files and static files.
  • Implements a network-first strategy for loader & action calls (i.e Gets a fresh request each time when online, and proceeds to an older fallback when offline)
  • Safely handles uncached loader calls without affecting other sections of the site (i.e Throws user to nearest Error boundary without disrupting Service Workers)
  • PWA client-side utilities that comes bundled with your App to give you more options and freedom while building the PWA of tomorrow.
  • Server-side utilities to simplify a lot of PWA backend for you. Developing would be more exciting!

Table Of Content

Getting Started

Installation

To integrate PWA features into your Remix App with remix-pwa, run the following command:

npx remix-pwa@latest

During installation, you would be required to choose the current language you are using with your Remix project, JavaScript or TypeScript. Make sure to pick "yes" to run npm install after the installation

Deployment

To build and deploy your Remix PWA App, simply run the command:

npm run build

at build time and then, you can host it on any hosting providers you prefer.

Upgrade Guide

To upgrade to a newer version of remix-pwa, simply run these two commands one after the other

# Uninstall remix-pwa to remove it from your package.json (if present. If not, skip this command)
npm rm -D remix-pwa

# Use npx to integrate PWA features without modifying your dependencies
npx remix-pwa@latest

and you can continue with your PWA

Setting up your PWA

After installing remix-pwa, link the manifest file in order to get installability feature of PWA as well as app characteristics and other features. To do that, simply add the following block of code to the head in your root file above the <Links /> tag:

<link rel="manifest" href="/resources/manifest.json" />

To run your app, simply run the command:

npm run dev

And voila! You are now ready to use your PWA!

If you want to lay you hands on demo icons and favicons for your PWA, remix-pwa got you covered with sample icons. Simply delete the favicon.ico in your public folder and add the following links to your root file, above the <Links /> tag.

API Documentation

Client APIs

Client APIs are a set of asynchronous functions that are to be run on the client only and never on the server.

They can be triggered by DOM events (click, hover, keypress, etc.) like other functions, but in order to trigger window events that happen at the start of a page lifecycle, e.g page "load" event, it is highly recommended to use these functions in a React's useEffect hook.

Type annonations:

Almost all Client APIs return a promise object (type ReturnObject) that consists of two properties: status and message. The status key is a string that would either be "success" or "bad". remix-pwa is set up by default, with error-catching procedures for these APIs. You can still set up your custom responses (to display a particluar UI for example, if the particular API isn't supported in the user's browser) in case of an error or a successful request with the status response. The message key is a default message string that accompanies the status in case of a pass or fail.

interface ReturnObject {
  status: "success" | "bad",
  message: string;
}

Check Connectivity

checkConnectivity(online: () => void, offline: () => void): Promise<ReturnObject>

This function is used to check wether a user is online or offline and execute a function accordingly. It could be used to update a state, display a particular UI or send a particular response to the server.

import { checkConnectivity } from "~/utils/client/pwa-utils.client";

const online = () => {
  //..Do something for online state
}

const offline = () => {
  //..Do something for offline state
}

useEffect(() => {
  // The `console.log` method returns an object with a status of "success" if online and a pass message or a status of "bad" and a fail message if offline
  checkConnectivity(online, offline).then(data => console.log(data)) 
}, [])

Copy text to Clipboard

copyText(text: string) => Promise<ReturnObject>

The Clipboard API is a method used to access the clipboard of a device, native or web, and write to it. This function can be triggered by DOM events, i.e "click", "hover", etc. or window events i.e "load", "scroll", etc.

import { copyText } from "~/utils/client/pwa-utils.client";

<button onClick={() => copyText("Test String")}>Copy to Clipboard</button>

WakeLock API

WakeLock() => Promise<ReturnObject>

🚨 This is still an experimental feature! Some browsers like FireFox would not work with this feature! 🚨

The WakeLock API is a function that when fired, is used to keep the screen of a device on at all times even when idle. It is usually fired when an app is started or when a particular route that needs screen-time is loaded (e.g A video app that has a watch-video route)

import { WakeLock } from "~/utils/client/pwa-utils.client";

useEffect(() => {
  WakeLock() // triggers the Wakelock api
}, [])

App Badges

addBadge(numberCount: number) => Promise<ReturnObject>

removeBadge() => Promise<ReturnObject>

The badge API is used by installed web apps to set an application-wide badge, shown in an "operating-system-specific" place associated with the application (such as the shelf or home screen or taskbar).

The badge API makes it easy to silently notify the user that there is new activity that might require their attention, or to indicate a small amount of information, such as an unread count (e.g unread messages).

The addBadge function takes a number as an argument (displays the number of notification) while the removeBadge function doesn't take any argument.

import { addBadge, removeBadge } from "~/utils/client/pwa-utils.client";

// used to clear away all notification badges
removeBadge()

//used to add a badge to the installed App
addBadge(3); // sets a new notification badge with 3 indicated notifications 

FullScreen Toggle

EnableFullScreenMode() => Promise<ReturnObject>

ExitFullScreenMode() => Promise<ReturnObject>

The Full Screen feature is an additional utility you can integrate into your app while building your PWA, EnableFullScreenMode() enables an App to cover the entire breadth and width of the scree at the tap of a button and the ExitFullScreenMode() exits full-screen mode. They both don't take any arguments and can be invoked like any other normal function.

import { EnableFullScreenMode, ExitFullScreenMode } from "~/utils/client/pwa-utils.client";

// Enable full-screen at the click of a button
<button onClick={EnableFullScreenMode}>Enable Full-Screen mode</button>

//Exit full-screen mode
<button onClick={ExitFullScreenMode}>Exit Full-Screen Mode</button>

(Client) Notification API

SendNotification(title: string, option: NotificationOptions) => Promise<ReturnObject>

// Interface `NotificationOptions`
interface NotificationOptions {
  body: string | "Notification body";
  badge?: string;
  icon?: string;
  silent: boolean | false;
  image?: string
}

The SendNotification API is a client-only function driven only by the Notifications API, it is different from the Push API which is another API handled and executed by the server (arriving to remix-pwa soon). The SendNotification function is executed by the client and takes in two arguments, one is the title of the notification and that's the top header (Title) of the notification your user would see. The second option is an object that would contain additional options for the API.

The first key for the NotificationsObject argument is the body and that is a required argument. The body is the main content of your notification that would contain the details of what you want to pass to the user. The badge argument is an optional argument and it's the image URL string of the Notification badge, and it's what the user would see when there is no space for the Notifivcation content to show. It is recommended to use a 96px by 96px square image for the badge. The next argument is the icon argument which is the image that would be displayed alongside your Notification. The image parameter is a string argument (url of your image) and is used to display an image along with your notification. The final argument is the silent parameter and it's a boolean argument (true or false) that is required, it is used to determine wether a notification should be sent silently regardless of the device's settings, it is by default set to false.

The Notification API can take values from the server (e.g loader) or from the client but it must be called and executed on the client side. We are working on adding the Push API that allows you to execute a Notification API together with the Push API on the server side in response to anything (for example, when a message is sent to a user in a messaging App).

This API is fully stable and is setup comepletely for your use cases including Notification permissions, however, we are working on adding more API options so that you can have the maximum custom experience!

import { SendNotification } from "~/utils/client/pwa-utils.client";

const options = {
  body: "Hello, take a break and drink some water! 💧", // required
  badge: "/icons/notification-badge.png", // not required
  icon: "/icons/app-icon.png", // not required
  silent: false, // required
  image: "/images/Nature.png" // NEW! Not required
}

let minutes = 30

// executed in several ways
setTimeout(() => {
  SendNotification("Workout App", options)
}, minutes * 60 * 1000)

// another method of execution
<button onClick={() => SendNotification("Exercise Tracker App", options)}>Take a break!</button>

Visibility State

Visibility (isVisible: () => void, notVisible: () => void): Promise<ResponseObject>

This utility is used to get wether a document is visible or is minimized (or in the background, etc). It takes two functions as its parameter, one for a visible state, and the other for an invisible state. A common use case for this is to stop a process (e.g video playing, downloading process, etc) when the app is minimized or to run a process only when the App is minimized.

import { Visibility } from "~/utils/client/pwa-utils.client";

const documentVisible = () => {
  //..do something
}

const documentInvisible = () => {
  //..do something else
}

const state = document.visibilityState

// Monitor visibility and keep firing the function on visibility change
useEffect(() => {
  Visibiliy(documentVisible, documentInvisible)
}, [state])

Copy Images to Clipboard

copyImage(url: string) => Promise<ResponseObject>

This is a modified version of the Copy Text to Clipboard API. It is used to easily copy images to your device's clipboard, it starts by taking the url of the image (e.g Passed through the src of an image tag) then fetching the image behind-scenes and finally copying the blob to your device's clipboard.

import { copyImage } from "~/utils/client/pwa-utils.client";

// Getting an image frame via React's ref hook.
const frameRef = useRef<HTMLImageElement>(null!)

// Accessing the `src` attribute and copying it to the clipboard.
<button onClick={() => copyImage(frameRef.current.src)}>📋 Copy Image to Clipboard</button>

Web Share API

File Web Share API

WebShareFile(title: string, data: any[], text: string) => Promise<ResponseObject>

The File Web Share API is an asynchronous method used to share files from your PWA to other apps. It takes in 3 arguments, title seen as the title of your shared response, text which is the body of your shared message (You can set a default value in app/utils/client/pwa-utils.client.ts) and finally the data which an array that contains the files to share. It returns a ResponseObject promise.

import { WebShareFile } from "~/utils/client/pwa-utils.client";

const files = ["File1.txt", "File2.svg"]

const SendFile = async () => {
  await WebShareFile("My Remix PWA", files, "A text file and an SVG file")
  
  // Do something or Trigger something else
}

Link Web Share API

WebShareLink(url: string, title: string, text: string) => Promise<ResponseObject>

This is a modified Web Share method used to serve links from your file (e.g A blog app) to other supported apps on your device. It is similar to the File Web Share API except it accepts a url instead of files.

import { WebShareLink } from "~/utils/client/pwa-utils.client";

const data = useLoaderData()

<button onClick={() => WebShareLink(data.param, data.title, data.description)}>Share Post</button>

Misc. Web Share API

WebShare(data: any): Promise<ResponseObject>

The Miscellaneous Webs Share Api is intended to be a simple Web Share Api that should be used if you intend to send something a bit more loose and simple compared to files & URLs.

I would advise against using this API except when the other two don't meet your data criteria. As this is loosely typed and could cause errors when used with heavy, technical data.

import { WebShare } from "~/utils/client/pwa-utils.client";

<button onClick={() => WebShare("Hello, I am a volatile API!")}>Share loose data</button>

(Back to Top)

Server API

Push Notification API

PushNotification(content: PushObject, delay: number = 0) => Promise<void>

interface PushObject {
  title: string;
  body: string;
  icon?: string;
  badge?: string;
  dir?: string;
  image?: string;
  silent?: boolean;
}

This is a server API. All Server APIs are to be run in the server (i.e Loaders, Actions & .server files)

Push Notification API is finally here (with some updates)! Push Notification API is used to by the server to generate Notifications for the user. It is used when you want to push a notification that is triggered by events from outside the App (e.g A message is sent to your user from another user's app, in a messaging app). It takes in quite a lot of arguments, a content argument which is an object containing methods to style your notification. The title property is the title of your Notification, the body is for the main text of the notification and the delay is an optional argument used to set the delay (in seconds) between the event happening and the server triggering the notification. It has a default value of zero.

To reference the other properties of PushObject, check out the properties section of this MDN doc.

Setting up and using remix-pwa first-ever server utility requires some steps to be functional, let's break them down:

  1. After installing remix-pwa, if you intend to use the Push API, run the command:
npx web-push generate-vapid-keys

You would get two keys in your console, a PRIVATE key and a PUBLIC key. Keep your PRIVATE key safe!

  1. Create a .env file, and save your keys using the variable name VAPID_PUBLIC_KEY for the public key and VAPID_PRIVATE_KEYfor the private key.

Add the following line of code in entry.server.ts:

import "dotenv/config"

Don't forget to add the .env file to your .gitignore file

  1. You can finally use the basic Web Push API in your server!
import { PushNotification } from "~/utils/server/pwa-utils.server.ts

export const action: ActionFunction = async ({ request }) => {
  // Get request and perform other operations
  
  await PushNotification({
    title: "Remix PWA",
    body: "A server generated text body."
  }, 1)
}

(Back to Top)

Hang On tight! We are working on bringing more awesome features to you amazing folks.

Going Deeper

Want to upgrade your PWA utilities? Or need a bit of tips and hints on how to customize your PWA? Want to make a prduction-ready PWA with Remix? This is your section! Let's get down to the nitty-gritty of remix-pwa.

Customizing your PWA manifest

One thing you might have noticed is that your manifest.json file is stored as a route and not a public, static file. This is due to an advantage of Remix and Remix PWA. By making our manifest a route, we allow developers to customise a PWA based on a user-to-user preference!

Allow me to break that down. If you open your manifest file located in app/routes/resources, you would notice that the manifest is stored inside a loader function that returns the manifest as a json object. Now if you wanted to customise the manifest based on user preference instead of a static file, how would we do it? Let's look at a simple scenario to answer that question:

We have a database hosted on an external platform and we are using Prisma as our database ORM, we save our user's color preferences in a table called User and we want to give the PWA the same feel as the website. The last thing we want to do is give our user's default color scheme for the app and custom schemes for the site. That's poor UX.

To solve this issue, we can simply import our PrismaClient into our manifest route's loader and interact with our db from there. Allowing us to get the preferences and set them as our PWA's theme and background color (for more info on themes and background-color, refer to MDN Docs)

export let loader: LoaderFunction = async () => {
  const preference = await prismaClient().user.findUnique({
    where: {
      username: "[email protected]"
    },
    include: {
      themePreference,
      bgPreference
    }
  })
  
  return json(
    {
      background_color: preference.bgPreference,
      theme_color: preference.themePreference,
      // ..Rest of the manifest
    }
  )
}

We got our user, we got their preference, we make them happy!

Upgrading your PWA manifest

Our manifest is quite simple and default, the name of the app is something that you would change, same as the theme color and other json fields depending on your taste and App's needs. But how about we add more to our manifest instead?

In v0.6.0, we created a new field in our manifest known as shortcuts and they do exactly what they say. They allow us to navigate to certain, specified pages (routes) directly from outside our App. I won't cover the fields used in the shortcuts and what they are meant to do, I would however, drop this wonderful article by Microsoft Azure that explains the shortcut aspect of the manifest well.

Another thing you would love to edit is the icons field in the manifest, we used default Remix icons for those but you would not want to. Instead replace the icons in /icons folder and specify their sizes. You could use Sketch or Figma to design and resize icons. You could also delete the default favicon.ico that comes with Remix.

This section is till WIP 🚧

(Back to Top)

Roadmap

Want to see proposed features and bug fixes? Or do you want to propose an idea/bug fix for remix-pwa and want to view the current roadmap? Check out remix-pwa Roadmap and see what lies in wait for us!

Contributing

Thank you for your interest in contributing 🙂 . The contribution guidelines and process of submitting Pull Requests are available in the CONTRIBUTING.md. Awaiting your PR 😉 !

Support

If you want to get help on an issue or have a question, you could either open an issue or you could ask your questions in the Official Remix's Discord Server where there are a lot of helpful people to help you out.

Authors

  • Abdur-Rahman Fashola (aka @ShafSpecs)

  • Special thanks to jacob-ebey for his contribution and help with the creation of remix-pwa!

See (todo: CONTRIBUTORS.md) for the list of awesome remix-pwa contributors!

License

This project is licensed under the MIT License - see the LICENSE.md file for details.

Comments
  • Not able to install

    Not able to install

    Issue

    Ran following: yarn add esbuild yarn add remix-pwa

    (also tried npm for both after running into this issue. Same issues`

    Output:

    error app/node_modules/remix-pwa: Command failed.
    Exit code: 1
    Command: npm run start
    Arguments: 
    Directory: app/node_modules/remix-pwa
    Output:
    > [email protected] start
    > node --loader ts-node/esm .\cli.ts
    
    (node:7497) ExperimentalWarning: --experimental-loader is an experimental feature. This feature could change at any time
    (Use `node --trace-warnings ...` to show where the warning was created)
    app/node_modules/ts-node/dist-raw/node-esm-resolve-implementation.js:383
        throw new ERR_MODULE_NOT_FOUND(
              ^
    CustomError: Cannot find module 'app/node_modules/remix-pwa/.cli.ts' imported from app/node_modules/remix-pwa/
        at finalizeResolution (app/node_modules/ts-node/dist-raw/node-esm-resolve-implementation.js:383:11)
        at moduleResolve (app/node_modules/ts-node/dist-raw/node-esm-resolve-implementation.js:818:10)
        at Object.defaultResolve (app/node_modules/ts-node/dist-raw/node-esm-resolve-implementation.js:929:11)
        at resolve (app/node_modules/ts-node/src/esm.ts:163:38)
        at ESMLoader.resolve (node:internal/modules/esm/loader:530:30)
        at ESMLoader.getModuleJob (node:internal/modules/esm/loader:251:18)
        at ESMLoader.import (node:internal/modules/esm/loader:332:22)
        at node:internal/modules/run_main:54:28
        at loadESM (node:internal/process/esm_loader:88:11)
        at async handleMainPromise (node:internal/modules/run_main:61:12)
    info Visit https://yarnpkg.com/en/docs/cli/add for documentation about this command.
    
    bug fixed 
    opened by lmuller18 44
  • entry.worker.ts esbuild compilation error

    entry.worker.ts esbuild compilation error

    Hello, I have this code running on my remix netlify instance in development (@remix-run/node server runtime and @remix-run/netlify server adapter), however running dev/build script that in turn runs this "worker" script that runs esbuild ./app/entry.worker.ts --outfile=./public/entry.worker.js --minify --bundle --format=esm --define:process.env.NODE_ENV='"production"' fails my build due to node requires coming from @remix-run/node package.

    $ npm-run-all -p build:*
    warning ../../package.json: No license field
    warning ../../package.json: No license field
    $ remix build
    $ esbuild ./app/entry.worker.ts --outfile=./public/entry.worker.js --minify --bundle --format=esm --define:process.env.NODE_ENV='"production"'
    ✘ [ERROR] Could not resolve "crypto"
    
        node_modules/@remix-run/node/upload/fileUploadHandler.js:15:21:
          15 │ var crypto = require('crypto');
             ╵                      ~~~~~~~~
    
      The package "crypto" wasn't found on the file system but is built into node. Are you trying to
      bundle for node? You can use "--platform=node" to do that, which will remove this error.
    
    ✘ [ERROR] Could not resolve "stream"
    
        node_modules/@remix-run/node/fetch.js:15:21:
          15 │ var stream = require('stream');
             ╵                      ~~~~~~~~
    
      The package "stream" wasn't found on the file system but is built into node. Are you trying to
      bundle for node? You can use "--platform=node" to do that, which will remove this error.
    
    ✘ [ERROR] Could not resolve "crypto"
    
        node_modules/@remix-run/node/sessions/fileStorage.js:15:21:
          15 │ var crypto = require('crypto');
             ╵                      ~~~~~~~~
    
      The package "crypto" wasn't found on the file system but is built into node. Are you trying to
      bundle for node? You can use "--platform=node" to do that, which will remove this error.
    
    ✘ [ERROR] Could not resolve "stream"
    
        node_modules/@remix-run/node/upload/memoryUploadHandler.js:15:21:
          15 │ var stream = require('stream');
             ╵                      ~~~~~~~~
    
      The package "stream" wasn't found on the file system but is built into node. Are you trying to
      bundle for node? You can use "--platform=node" to do that, which will remove this error.
    
    ✘ [ERROR] Could not resolve "stream"
    
        node_modules/@remix-run/node/parseMultipartFormData.js:15:21:
          15 │ var stream = require('stream');
             ╵                      ~~~~~~~~
    
      The package "stream" wasn't found on the file system but is built into node. Are you trying to
      bundle for node? You can use "--platform=node" to do that, which will remove this error.
    
    ✘ [ERROR] Could not resolve "fs"
    
        node_modules/@remix-run/node/upload/fileUploadHandler.js:16:17:
          16 │ var fs = require('fs');
             ╵                  ~~~~
    
      The package "fs" wasn't found on the file system but is built into node. Are you trying to bundle
      for node? You can use "--platform=node" to do that, which will remove this error.
    
    6 of 21 errors shown (disable the message limit with --log-limit=0)
    node:child_process:869
        throw err;
        ^
    
    Error: Command failed: /Users/josephmethven/Projects/rp-rdm-mobile/node_modules/esbuild-darwin-64/bin/esbuild ./app/entry.worker.ts --outfile=./public/entry.worker.js --minify --bundle --format=esm --define:process.env.NODE_ENV="production"
        at checkExecSyncError (node:child_process:828:11)
        at Object.execFileSync (node:child_process:866:15)
        at Object.<anonymous> (/Users/josephmethven/Projects/rp-rdm-mobile/node_modules/esbuild/bin/esbuild:163:26)
        at Module._compile (node:internal/modules/cjs/loader:1103:14)
        at Object.Module._extensions..js (node:internal/modules/cjs/loader:1157:10)
        at Module.load (node:internal/modules/cjs/loader:981:32)
        at Function.Module._load (node:internal/modules/cjs/loader:822:12)
        at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:77:12)
        at node:internal/main/run_main_module:17:47 {
      status: 1,
      signal: null,
      output: [ null, null, null ],
      pid: 82595,
      stdout: null,
      stderr: null
    }
    

    package.json

    {
    	"name": "my-package",
    	"private": true,
    	"description": "Remix + Netlify + PWA",
    	"license": "",
    	"sideEffects": false,
    	"scripts": {
    		"build": "npm-run-all -p build:*",
    		"build:remix": "remix build",
    		"dev": "npm-run-all -p dev:*",
    		"dev:netlify": "cross-env NODE_ENV=development netlify dev",
    		"postinstall": "remix setup node",
    		"build:worker": "esbuild ./app/entry.worker.ts --outfile=./public/entry.worker.js --minify --bundle --format=esm --define:process.env.NODE_ENV='\"production\"'",
    		"dev:worker": "esbuild ./app/entry.worker.ts --outfile=./public/entry.worker.js --bundle --format=esm --define:process.env.NODE_ENV='\"development\"' --watch"
    	},
    	"dependencies": {
    		"@emotion/cache": "^11.7.1",
    		"@emotion/css": "^11.7.1",
    		"@emotion/react": "^11.8.1",
    		"@emotion/server": "^11.4.0",
    		"@emotion/styled": "^11.8.1",
    		"@fortawesome/fontawesome-svg-core": "^6.1.1",
    		"@fortawesome/free-brands-svg-icons": "^6.1.1",
    		"@fortawesome/free-solid-svg-icons": "^6.1.1",
    		"@fortawesome/react-fontawesome": "^0.1.18",
    		"@mui/icons-material": "^5.6.2",
    		"@mui/material": "^5.5.0",
    		"@netlify/functions": "^1.0.0",
    		"@remix-run/eslint-config": "^1.3.5",
    		"@remix-run/netlify": "^1.4.1",
    		"@remix-run/node": "^1.4.3",
    		"@remix-run/react": "^1.3.5",
    		"@remix-validated-form/with-yup": "^2.0.1",
    		"cross-env": "^7.0.3",
    		"date-fns": "^2.28.0",
    		"lodash": "^4.17.21",
    		"marked": "^4.0.12",
    		"node-persist": "^3.1.0",
    		"prettier": "^2.6.0",
    		"react": "^18.0.0",
    		"react-dom": "^18.0.0",
    		"react-markdown": "^8.0.3",
    		"react-remark": "^2.1.0",
    		"react-string-replace": "^1.0.0",
    		"remix": "^1.4.1",
    		"remix-pwa": "^0.8.1",
    		"remix-seo": "^0.1.0",
    		"remix-validated-form": "^4.1.8",
    		"swiper": "^8.1.3",
    		"tiny-invariant": "^1.2.0",
    		"web-push": "^3.4.5",
    		"yup": "^0.32.11"
    	},
    	"devDependencies": {
    		"@remix-run/dev": "^1.3.5",
    		"@types/lodash": "^4.14.179",
    		"@types/react": "^18.0.1",
    		"@types/react-dom": "^18.0.0",
    		"@types/swiper": "^6.0.0",
    		"esbuild-plugin-alias": "^0.2.1",
    		"eslint": "^8.11.0",
    		"eslint-config-prettier": "^8.5.0",
    		"eslint-plugin-prettier": "^4.0.0",
    		"npm-run-all": "^4.1.5",
    		"typescript": "^4.5.5"
    	},
    	"engines": {
    		"node": ">=14"
    	}
    }
    

    If I add --platform=node as suggested by CLI, the app runs up fine but then the browser console throws an error

    entry.worker.js:13 Uncaught Error: Dynamic require of "path" is not supported
        at entry.worker.js:13:9
        at node_modules/source-map-support/source-map-support.js (entry.worker.js:1780:16)
        at __require2 (entry.worker.js:16:50)
        at node_modules/@remix-run/node/index.js (entry.worker.js:31541:28)
        at __require2 (entry.worker.js:16:50)
        at entry.worker.js:31629:27
    
    bug enhancement new feature fixed 
    opened by JoeMethven 18
  • SyntaxError: Unexpected token - Installation fails

    SyntaxError: Unexpected token - Installation fails

    $ npx remix-pwa@latest
    Welcome to Remix PWA!
    
    √ Is this a TypeScript or JavaScript project? Pick the opposite for chaos! · TypeScript
    
    √ What caching strategy do you want to use? Check out the docs 
    for more info. · Precaching
    
    √ What features of remix-pwa do you need? Don't be afraid to pick all! · No items were selected
    
    √ What is the location of your Remix app? · app
    √ Do you want to immediately run "npm install"? (Y/n) · true
    SyntaxError: Unexpected token (36:275)
      34 | }, [location]);
      35 |
    > 36 | return ( <html lang="en" className={` flex min-h-screen 
    flex-col bg-slate-100 font-montserrat scrollbar ${SCROLL_BAR_STYLE}`} > <head> <Meta /> <Links /> </head> <body className="flex min-h-screen flex-col text-2xl"> <Outlet /> <Scripts /> <LiveReload /> </body> </html> ); } 
         |
    
    
    
                                 ^
        at p (C:\Users\Moish\Documents\Repos\instabis\node_modules\prettier\parser-babel.js:22:1038)
        at d (C:\Users\Moish\Documents\Repos\instabis\node_modules\prettier\parser-babel.js:22:1271)
        at Object.parse (C:\Users\Moish\Documents\Repos\instabis\node_modules\prettier\parser-babel.js:27:50424)
        at Object.parse (C:\Users\Moish\Documents\Repos\instabis\node_modules\prettier-plugin-tailwindcss\dist\index.js:146:3860) 
        at Object.parse (C:\Users\Moish\Documents\Repos\instabis\node_modules\prettier\index.js:7334:23)
        at coreFormat (C:\Users\Moish\Documents\Repos\instabis\node_modules\prettier\index.js:8645:18)
        at formatWithCursor2 (C:\Users\Moish\Documents\Repos\instabis\node_modules\prettier\index.js:8837:18)
        at C:\Users\Moish\Documents\Repos\instabis\node_modules\prettier\index.js:37229:12
        at Object.format (C:\Users\Moish\Documents\Repos\instabis\node_modules\prettier\index.js:37243:12)
        at C:\Users\Moish\Documents\Repos\instabis\node_modules\remix-pwa\dist\cli.js:106:34 {
      loc: { start: { line: 36, column: 275 } },
      codeFrame: '\x1B[0m \x1B[90m 34 |\x1B[39m }\x1B[33m,\x1B[39m 
    [location])\x1B[33m;\x1B[39m\x1B[0m\n' +
        '\x1B[0m \x1B[90m 35 |\x1B[39m\x1B[0m\n' +
        '\x1B[0m\x1B[31m\x1B[1m>\x1B[22m\x1B[39m\x1B[90m 36 |\x1B[39m \x1B[36mreturn\x1B[39m ( \x1B[33m<\x1B[39m\x1B[33mhtml\x1B[39m lang\x1B[33m=\x1B[39m\x1B[32m"en"\x1B[39m className\x1B[33m=\x1B[39m{\x1B[32m` flex min-h-screen flex-col bg-slate-100 font-montserrat scrollbar ${SCROLL_BAR_STYLE}`\x1B[39m} \x1B[33m>\x1B[39m \x1B[33m<\x1B[39m\x1B[33mhead\x1B[39m\x1B[33m>\x1B[39m \x1B[33m<\x1B[39m\x1B[33mMeta\x1B[39m \x1B[35m/> <Links /\x1B[39m\x1B[33m>\x1B[39m \x1B[33m<\x1B[39m\x1B[35m/head> <body className="flex min-h-screen flex-col text-2xl"> <Outlet /\x1B[39m\x1B[33m>\x1B[39m \x1B[33m<\x1B[39m\x1B[33mScripts\x1B[39m \x1B[35m/> <LiveReload /\x1B[39m\x1B[33m>\x1B[39m \x1B[33m<\x1B[39m\x1B[33m/\x1B[39m\x1B[33mbody\x1B[39m\x1B[33m>\x1B[39m \x1B[33m<\x1B[39m\x1B[33m/\x1B[39m\x1B[33mhtml\x1B[39m\x1B[33m>\x1B[39m )\x1B[33m;\x1B[39m } \x1B[0m\n' +
        '\x1B[0m \x1B[90m    |\x1B[39m
    
    
    
                                                             \x1B[31m\x1B[1m^\x1B[22m\x1B[39m\x1B[0m'
    }
    

    OS: Windows Node: Latest

    opened by moishinetzer 11
  • ServiceWorker never registered because `entry.client.jsx#window.addEventListener(

    ServiceWorker never registered because `entry.client.jsx#window.addEventListener("load", ...)` is never triggered

    Hello,

    I've just installed remix-pwa@latest on a pristine [email protected] app (no template, using remix server). The service worker is never registered, I managed to pinpoint the problem to the lack of triggering of the window.addEventListener("load", ...) but can't manage to solve the issue. This happens both in dev and prod deployments.

    Changing to window.addEventListener("click", ...) does work.

    Screen Shot 2022-09-28 at 8 27 07 AM Screen Shot 2022-09-28 at 8 25 25 AM Screen Shot 2022-09-28 at 8 26 24 AM

    Any insight welcome :-)

    • Regards.
    opened by nuKs 9
  • Error: [node-persist][readFile] ... does not look like a valid storage file!

    Error: [node-persist][readFile] ... does not look like a valid storage file!

    POST /resources/subscribe 200 - - 3.177 ms
    Error: [node-persist][readFile] .node-persist/storage/b48b13e73a6ac2a86dc54425dd24d9ff does not look like a valid storage file!
        at ./libre-billboardoo-frontend/node_modules/node-persist/src/local-storage.js:314:89
        at FSReqCallback.readFileAfterClose [as oncomplete] (node:internal/fs/read_file_context:68:3)
    
    bug question 
    opened by JellyBrick 7
  • Causing double fetch and Prefetch not included in header

    Causing double fetch and Prefetch not included in header

    steps to reproduce:

    1. npx create-remix --template remix-run/indie-stack blog-tutorial

      . ? Do you want me to run npm install? No

    2. pnpm i
    3. Add prefetch="intent" to <Link>

    Purpose: prefetch in Request header from chrome devtools. ✅

    GET /notes?_data=routes%2Fnotes HTTP/1.1
    Accept: application/signed-exchange;v=b3;q=0.7,*/*;q=0.8
    Accept-Encoding: gzip, deflate, br
    Accept-Language: en,zh;q=0.9,fil;q=0.8
    Connection: keep-alive
    Cookie: __session=eyJ1c2VySWQiOiJjbDNrd3E2b2EwMDAyY2dheW44emM2bmM5In0%3D.mvQL20%2B0LlAVOzRUhhAASRAUzSPZopsiUJSY2UUGdhs
    Host: localhost:3000
    Purpose: prefetch 
    Sec-Fetch-Dest: empty
    Sec-Fetch-Mode: no-cors
    Sec-Fetch-Site: same-origin
    Sec-GPC: 1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.61 Safari/537.36
    
    1. npx remix-pwa@latest
    2. pnpm i
    3. setup VAPID_KEYS

    Purpose: prefetch missing. ❌

    GET /notes?_data=routes%2Fnotes HTTP/1.1
    Accept: */*
    Accept-Encoding: gzip, deflate, br
    Accept-Language: en,zh;q=0.9,fil;q=0.8
    Connection: keep-alive
    Cookie: __session=eyJ1c2VySWQiOiJjbDNrd3E2b2EwMDAyY2dheW44emM2bmM5In0%3D.mvQL20%2B0LlAVOzRUhhAASRAUzSPZopsiUJSY2UUGdhs
    Host: localhost:3000
    Sec-Fetch-Dest: empty
    Sec-Fetch-Mode: no-cors
    Sec-Fetch-Site: same-origin
    Sec-GPC: 1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.61 Safari/537.36
    

    image image

    Personal usage: caching request https://sergiodxa.com/articles/fix-double-data-request-when-prefetching-in-remix#cache-every-loader-request

    bug question 
    opened by GetCurious 6
  • action function in /resources/subscribe not working

    action function in /resources/subscribe not working

    Hello,

    Please could you help, I am able to get the subscription from the user using the default code but the /resources/subscribe post is not working from entry.client.tsx:

    await fetch("./resources/subscribe", { method: "POST", body: JSON.stringify({ subscription: subscription, type: "POST_SUBSCRIPTION" }) });

    Is this meant to work by default or is there a reason the loader is working but not the action?

    opened by simmondsty 6
  • node-persist error makes the application to crash

    node-persist error makes the application to crash

    Hello, any idea what is the cause of this error? I have the latest version of remix-pwa and the application is deployed in Vercel, and sometimes it crashes and generates this error.

    2022-07-19T04:35:38.321Z	c2e38db0-e42e-4b5c-ac95-f50ec717eb7e	ERROR	Unhandled Promise Rejection 	{"errorType":"Runtime.UnhandledPromiseRejection","errorMessage":"Error: ENOENT: no such file or directory, mkdir '/var/task/.node-persist'","reason":{"errorType":"Error","errorMessage":"ENOENT: no such file or directory, mkdir '/var/task/.node-persist'","code":"ENOENT","errno":-2,"syscall":"mkdir","path":"/var/task/.node-persist","stack":["Error: ENOENT: no such file or directory, mkdir '/var/task/.node-persist'"]},"promise":{},"stack":["Runtime.UnhandledPromiseRejection: Error: ENOENT: no such file or directory, mkdir '/var/task/.node-persist'","    at process.<anonymous> (file:///var/runtime/index.mjs:775:15)","    at process.emit (node:events:539:35)","    at process.emit (/var/task/node_modules/source-map-support/source-map-support.js:516:21)","    at emit (node:internal/process/promises:140:20)","    at processPromiseRejections (node:internal/process/promises:274:27)","    at processTicksAndRejections (node:internal/process/task_queues:97:32)"]}
    [ERROR] [1658205338322] LAMBDA_RUNTIME Failed to post handler success response. Http response code: 400.
    RequestId: 4ba770e1-f539-4c3c-b041-3fb60360f0ac Error: Runtime exited with error: exit status 128
    Runtime.ExitError
    

    Thank you!

    opened by NdozHH 4
  • base 64 decoding

    base 64 decoding

    There are a couple of issues with the function linked below

    https://github.com/ShafSpecs/remix-pwa/blob/077251e9c25e4a19754aa846b0d790e9f53f7c98/templates/ts/app/push.entry.client.ts#L1

    1. The replace function is using an unneeded escaped character
    2. The function is logging the following error: "The string to be decoded is not correctly encoded."

    I don't quite understand the idea of how the key needs to look like after encoding, but this is the result here: 'BPMc6qUvK0NNK3UX7+7s+fmd1CkkEmkghHHvz0qMLFbeuHOE4YTQHNNb3EBmgottwCNAgEyXqnK3DCAJB8MNPyI',==

    opened by cjenaro 4
  • Error: ENOENT: no such file or directory, open '/app/entry.client.tsx'

    Error: ENOENT: no such file or directory, open '/app/entry.client.tsx'

    pnpx remix-pwa
    Welcome to Remix PWA!
    
    ✔ Is this a TypeScript or JavaScript project? Pick the opposite for chaos! · TypeScript
    ✔ Do you want to immediately run "npm install"? (Y/n) · false
    Error: ENOENT: no such file or directory, open '/app/entry.client.tsx'
        at Object.openSync (node:fs:585:3)
        at Object.readFileSync (node:fs:453:35)
        at /node_modules/.pnpm/[email protected]_@[email protected]/node_modules/remix-pwa/dist/cli.js:72:39
        at step (/node_modules/.pnpm/[email protected]_@[email protected]/node_modules/remix-pwa/dist/cli.js:34:23)
        at Object.next (/node_modules/.pnpm/[email protected]_@[email protected]/node_modules/remix-pwa/dist/cli.js:15:53)
        at /node_modules/.pnpm/[email protected]_@[email protected]/node_modules/remix-pwa/dist/cli.js:9:71
        at new Promise (<anonymous>)
        at __awaiter (/node_modules/.pnpm/[email protected]_@[email protected]/node_modules/remix-pwa/dist/cli.js:5:12)
        at Run (/node_modules/.pnpm/[email protected]_@[email protected]/node_modules/remix-pwa/dist/cli.js:47:12)
        at /node_modules/.pnpm/[email protected]_@[email protected]/node_modules/remix-pwa/dist/cli.js:125:63 {
      errno: -2,
      syscall: 'open',
      code: 'ENOENT',
      path: '/app/entry.client.tsx'
    
    enhancement new feature fixed 
    opened by garth 4
  • MacOs instalation failure

    MacOs instalation failure

    Whats happening?

    On instalation steps:

    ➜  main npx remix-pwa@latest
    Welcome to Remix PWA!
    
    ✔ Is this a TypeScript or JavaScript project? Pick the opposite for chaos! · TypeScript
    ✔ What caching strategy do you want to use? Check out the docs for more info. · Just-In-Time Caching
    ✔ What features of remix-pwa do you need? Don't be afraid to pick all! · Service Workers, Web Manifest, Push Notifications, PWA Client Utilities, Development Icons
    ✔ What is the location of your Remix app? · src/app
    ✔ Do you want to immediately run "npm install"? (Y/n) · false
    Error: ENOENT: no such file or directory, open '/Users/ross/Documents/target/Conmution/ukraine-stands/main/src/app/entry.client.tsx'
        at Object.openSync (fs.js:476:3)
        at Object.readFileSync (fs.js:377:35)
        at /Users/ross/.npm/_npx/40109/lib/node_modules/remix-pwa/dist/cli.js:79:39
        at step (/Users/ross/.npm/_npx/40109/lib/node_modules/remix-pwa/dist/cli.js:34:23)
        at Object.next (/Users/ross/.npm/_npx/40109/lib/node_modules/remix-pwa/dist/cli.js:15:53)
        at /Users/ross/.npm/_npx/40109/lib/node_modules/remix-pwa/dist/cli.js:9:71
        at new Promise (<anonymous>)
        at __awaiter (/Users/ross/.npm/_npx/40109/lib/node_modules/remix-pwa/dist/cli.js:5:12)
        at Run (/Users/ross/.npm/_npx/40109/lib/node_modules/remix-pwa/dist/cli.js:48:12)
        at /Users/ross/.npm/_npx/40109/lib/node_modules/remix-pwa/dist/cli.js:182:42 {
      errno: -2,
      syscall: 'open',
      code: 'ENOENT',
      path: '/Users/ross/Documents/target/Conmution/ukraine-stands/main/src/app/entry.client.tsx'
    }
    

    Expected to have success of cli run, not a failure…

    System:

    Screenshot 2022-07-29 at 22 24 04
    opened by conmute 3
  • Installation not Working

    Installation not Working

    Running a fresh installation with these options:

    ✔ Is this a TypeScript or JavaScript project? Pick the opposite for chaos! · TypeScript
    ✔ What caching strategy do you want to use? Check out the docs for more info. · Just-In-Time Caching
    ✔ What features of remix-pwa do you need? Don't be afraid to pick all! · Service Workers, Web Manifest, Push Notifications, PWA Client Utilities, Development Icons
    ✔ What is the location of your Remix app? · arena-pwa
    ✔ Do you want to immediately run "npm install"? (Y/n) · false
    

    Ends up throwing this error:

    Error: ENOENT: no such file or directory, open '/Users/charlieblackstock/repos/arena-pwa/entry.client.tsx'
        at Object.openSync (node:fs:585:3)
        at Object.readFileSync (node:fs:453:35)
        at /Users/charlieblackstock/.npm/_npx/2a790d8a53532af9/node_modules/remix-pwa/dist/cli.js:79:39
        at step (/Users/charlieblackstock/.npm/_npx/2a790d8a53532af9/node_modules/remix-pwa/dist/cli.js:34:23)
        at Object.next (/Users/charlieblackstock/.npm/_npx/2a790d8a53532af9/node_modules/remix-pwa/dist/cli.js:15:53)
        at /Users/charlieblackstock/.npm/_npx/2a790d8a53532af9/node_modules/remix-pwa/dist/cli.js:9:71
        at new Promise (<anonymous>)
        at __awaiter (/Users/charlieblackstock/.npm/_npx/2a790d8a53532af9/node_modules/remix-pwa/dist/cli.js:5:12)
        at Run (/Users/charlieblackstock/.npm/_npx/2a790d8a53532af9/node_modules/remix-pwa/dist/cli.js:48:12)
        at /Users/charlieblackstock/.npm/_npx/2a790d8a53532af9/node_modules/remix-pwa/dist/cli.js:182:42 {
      errno: -2,
      syscall: 'open',
      code: 'ENOENT',
      path: '/Users/charlieblackstock/repos/arena-pwa/entry.client.tsx'
    }
    
    opened by chuckstock 1
  • Remix-pwa stops long lived loaders and fails navigation for any route that takes a long time.

    Remix-pwa stops long lived loaders and fails navigation for any route that takes a long time.

    Setup: Create a route with a loader, have that loader perform an operation that takes a while, you will then be redirected to the previous route you successfully landed on. This is especially bad if your root.tsx file loads longer than a second, You will be stuck in an infinite reload cycle as remix-pwa continues pinging changes.

    Example setup to instantly break a route:

    export const loader = ({request} : LoaderArgs) => {
      await new Promise((resolve) => setTimeout(resolve, 2 * 1000)); // sleep 2 seconds
      // Rest of Loader
    }
    

    Possible Explanation for Behavior: Remix-pwa doesn't wait for a user's request to finish before making additional requests with the worker.

    Fix (? not yet tested, don't have the time just yet): Remix-pwa must wait for all loaders to be finished before it can run its update. Can't locate the best place to find this, I think it's auto generated by remix-pwa in the build somehow but I'm still figuring out all the ins and outs of what remix-pwa provides and how it hooks into your app.

    Tested on: Pre-Existing application with many packages + remix-pwa Fresh Blues Stack App with only remix-pwa added Fresh Blues Stack App no additions (Error not present)

    bug help wanted 
    opened by Brocktho 4
  • Request for Documentation (specifically what remix-pwa does for you on install)

    Request for Documentation (specifically what remix-pwa does for you on install)

    Background: I'm really excited about this project cause I already love Remix and want to have an easy way to create a close to native experience. I was able to get a fresh remix-blues stack up and running with remix-pwa, although I had to remove cypress testing from my CI/CD since Electron was giving me issues and it was just beyond my understanding at this time.

    Issue: I read as much as I could from the README and the Roadmap but I still have questions on how I could learn some of the under the hood implementations or what APIs are directly touched by remix-pwa. I'd love to be able to help on the project or give better feedback but it's hard to know what remix-pwa does or doesn't do. I mean that in the sense of, I see some code generation happening when using the CLI tool, but I had issues using that same CLI tool on a remix application I already have in production, as a result some features of the library are definitely not working after I tried filling in what I could see from a successful fresh install.

    Request:

    1. Adding links to useful documentation or other references that go into more detail of what a PWA requires
    2. Adding information surrounding what the CLI tool aims to accomplish and what a user can do to set things up themselves should it fail on an existing application.
    3. Possibly looking at implementing remix-pwa on all existing remix stacks (Blues, Indie, Grunge. Most of it seems ready to go, I just personally experienced issues in the CI/CD pipeline when attempting to run the Cypress tests.)
    4. Add to documentation that CLI issues can happen if comments are present in the root.tsx file.

    Final Note: This is a really amazing project and makes Native Application support seem like an achievable goal for anyone with a remix stack already, I'd just love to have extra documentation so I can do something to help the project along and have more confidence in using it on existing applications.

    Edit: Dug through other issues and found the reason i had CLI issues on an existing project. Comments do seem to break the CLI, removing them all has fixed the issue. Added request 4. as a reuslt.

    documentation enhancement new feature high priority 
    opened by Brocktho 4
  • ServiceWorker never registered because entry.client.jsx#window.addEventListener(

    ServiceWorker never registered because entry.client.jsx#window.addEventListener("load", ...) is never triggered

    Reopening issue https://github.com/ShafSpecs/remix-pwa/issues/42.

    --

    Hello,

    I've just installed remix-pwa@latest on a pristine [email protected] app (no template, using remix server). The service worker is never registered, I managed to pinpoint the problem to the lack of triggering of the window.addEventListener("load", ...) but can't manage to solve the issue. This happens both in dev and prod deployments.

    Changing to window.addEventListener("click", ...) does work.

    image image image

    high priority 
    opened by nuKs 4
  • event.respondWith causing error with Safari while offline

    event.respondWith causing error with Safari while offline

    It seems the cached loaderFunctions are not working correctly with Safari:

    Cached pages while offline responds with:

    Load failed -

    It is working perfectly on Android and Windows devices.

    opened by simmondsty 1
Releases(v1.0)
  • v1.0(Jul 4, 2022)

    Official v1 Release is here!!

    We've been through a lot. Testing, building, editing and moving forward. I present to you, official v1 release of remix-pwa, a major milestone in our journey of bringing the Web even closer to our everyday lives and interactions.

    Changelog:

    • Added precaching option!! Now, you can cache that static app you have in one go and enjoy seamless transitions even offline
    • Added caching strategy option for Remix PWA
    • Released Remix PWA
    • Selection feature that allows you to choose just the features of Remix PWA you need
    • Now automates importing in root.
    • Now provided an option for selecting root directory locations.
    • Added jsdoc typings to APIs to provide additional info on the go.
    • Fixed weird root behaviour after install.
    • Revamped remix-pwa installation.
    • Added a new section in the docs, installation guide
    • Added new utils option to automate API selection.
    • Made Push API optional! No longer must you set up a feature you won't use.
    • Fixed type imports in Service Worker.
    • Fixed self declaration error in JavaScript Service Workers.
    • Fixed isMount re-initialization on every render. Thanks @mokhtar
    • Allowed interaction with useMatches function during Service Worker initialization. Thanks @pumpitbetter
    • Extra fixes that can't be mentioned but would no doubt improve the overall DX.
    • Minor tweaks
    • Minor Bug Fixes
    Source code(tar.gz)
    Source code(zip)
  • v0.8.2(Jun 4, 2022)

    Misc. Feature Update Here!

    Changelog:

    • Added a new prompt to the cli, so now you have to tell remix-pwa where your app folder is stored (e.g src/app or app)
    • Added JSDoc description typings to the client and server file.
    • Fixed Push API return values
    • Updated Contributors list. Thanks @theeomm :v:
    • Minor fixes
    • Little tweaks here and there
    Source code(tar.gz)
    Source code(zip)
  • v0.8.1(Apr 16, 2022)

    Fix Update here!

    Changelog:

    • Fixed imports to accomodate new Remix versions.
    • Adding jsdoc comments to API methods
    • Fixed Push API subscription error
    • Fixed storage.getItem() is not defined error.
    • Refactored CLI process
    • Improved template readability
    • Fixed Service Worker push handler JSON error
    Source code(tar.gz)
    Source code(zip)
  • v0.8.0(Mar 26, 2022)

    Push API v2 Update here!

    Changelog:

    • Upgraded Push API interface
    • Automatically installs dotenv
    • Added missing @type packages that caused errors
    • Removes need for editing Service Worker
    • Additional minor tweaks
    • Bug fixes
    Source code(tar.gz)
    Source code(zip)
  • v0.7.5(Mar 5, 2022)

    CLI Update here!

    Changelog:

    • Removed the need for "post install" command npm run pwa
    • npx remix-pwa@latest now handles installing PWA modules and installation of required dependencies
    • Remix PWA now includes module for editing dependencies and devDependencies for easier convenience
    • Minor fixes
    Source code(tar.gz)
    Source code(zip)
  • v0.7.0(Mar 2, 2022)

    💥Code-Breaking Update!

    Changelog:

    • remix-pwa must be installed via npx command and not npm install
    • To safely deploy your pre-0.7.0 app, you must remove remix-pwa from your dependencies in package.json
    • Fixed Syntax Errors that appears in root during installation formatting
    • Fixed Wrong Syntax of root code after installation
    • Minor fixes
    Source code(tar.gz)
    Source code(zip)
  • v0.6.0(Feb 26, 2022)

    New major release!

    Changelog:

    • Added Push API 🎉! It is finally here!
    • Added a new field to the Notifications API, the image field
    • Added a new field to the manifest, shortcuts! Make sure to check that out
    • Revamped Web Share API massively! Added two new custom handlers for sharing files and URLs
    • Added stricter typing to Web Share API. Catch those bugs while it's early!
    • Created a brand new server utility file to hold all your server util operations pwa-utils.server.[t/j]s!
    • Finally fixed the random {" "} that appears in the root file due to prettier formatting
    • Fixed bug where entry.client.ts template was getting copied to js projects
    • Added a new file reading and checking operation to conserve your changes whilst still adding PWA features
    • entry.client would now overwrite all changes from v0.1.0. Hint: Massive update in that file!
    • Added a new section to the doc, Going Deeper.
    • Added new, customizable Push handler in .worker file to handle push events
    • Added a brand-new subscribe feature that allows you to get user's to subscribe to the PushManager (no unsubbing yet!)
    • Minor bug fixes
    Source code(tar.gz)
    Source code(zip)
  • v0.5.0(Feb 20, 2022)

    New, major update available 🎉🥳!

    Changelog:

    • esbuild is no longer required to install remix-pwa
    • remix-pwa should now be installed as a Dev Dependency instead of a normal dependency
    • Added new client PWA utilities to remix-pwa and set the groundwork for more to come, these include:
      • Copy to Clipboard API
      • Badges API
      • Check user's network status
    • Added a new utility file to host client APIs in your own project!
    • Fixed duplication of Service Worker registration utilities on version upgrade
    • Added a new API Documentation segment to remix-pwa docs
    • Fixed crashing of Service Workers in Chrome
    • Fixed overwriting of custom manifest files
    • Fixed overwriting of already-created directories on remix-pwa install
    • Additional minor fixes
    • Additional bug fixes
    Source code(tar.gz)
    Source code(zip)
  • v0.4.14(Feb 20, 2022)

    Changelog:

    • Fixed bug where Service Worker crashes on Chrome
    • Modified template and smoothed file merging during installation
    • Minor fixes
    • Bug fixes
    Source code(tar.gz)
    Source code(zip)
  • v0.3.4(Feb 18, 2022)

  • v0.3.0(Feb 17, 2022)

    Changelog:

    • remix-pwa now automatically updates scripts in package.json file.
    • Improved CLI performance
    • README.md updated
    • Minor fixes
    • Bug fixes
    Source code(tar.gz)
    Source code(zip)
  • v0.2.6(Feb 17, 2022)

    Changelog:

    • Removed installation of types while running npm i remix-pwa
    • Formatted root file with prettier before serving file.
    • Added manifest examples
    • Updated README.md to include a better-detailed process
    • Minor fixes
    • Bug fixes
    Source code(tar.gz)
    Source code(zip)
  • v0.2.5(Feb 17, 2022)

    Changelog:

    • Moved out of pre-alpha phase into alpha stage!
    • Initiated tests into remix-pwa
    • Fixed breaking root error: "No file or directory found"
    • Updated entry.client to register Service Workers
    • Set up environment to enable minified scripts
    • Added README.md
    • Added LICENSE.md
    • Improved possible errors handling
    • Updated jest configs
    • Minor fixes
    • Bug fixes
    Source code(tar.gz)
    Source code(zip)
  • v0.1.17(Feb 16, 2022)

    Changelog:

    • Package running fine without any hitches
    • Fixed random empty template files
    • Updated scripts to run automatically after install
    • Removed bundling/minifying altogether
    • Improved FileBuffer stream read with fs-extra
    • Disabled linting on module install
    • Fixed minor bugs 🛠
    Source code(tar.gz)
    Source code(zip)
  • v0.1.4(Feb 15, 2022)

  • v0.1.0(Feb 15, 2022)

Owner
Abdur-Rahman
....learning something new everyday, one step at a time.
Abdur-Rahman
Persistent key/value data storage for your Browser and/or PWA, promisified, including file support and service worker support, all with IndexedDB. Perfectly suitable for your next (PWA) app.

BrowstorJS ?? ?? ?? Persistent key/value data storage for your Browser and/or PWA, promisified, including file support and service worker support, all

Nullix 8 Aug 5, 2022
NPM Package to integrate ONDC into Node.js backend

ondc-node This library can be used to integrate ONDC in JavaScript based applications. Package is developed in TypeScript and will work with Node.Js &

Utkarsh Mehta 12 Dec 11, 2022
A fully configurable & customizable Remix PWA stack.

Remix RockSpec Stack Learn more about Remix Stacks. npx create-remix --template ShafSpecs/rockspec-stack What's in the stack Fly app deployment with

Abdur-Rahman 54 Dec 18, 2022
Next-level academia! Repository for the Native Overleaf project, attempting to integrate Overleaf with native OS features for macOS, Linux and Windows.

Native Overleaf Overleaf is a fantastic webtool for writing and cooperating on LaTeX documents. However, would it not be even better if it were to beh

Floris-Jan Willemsen 40 Dec 18, 2022
An example project to how to integrate Chat Engine into a marketplace

Add Chat to Your Marketplace This is a example online marketplace with Chat Engine fully integrated. It's meant to help people building online marketp

Adam La Morre 13 Dec 22, 2022
Package fetcher is a bot messenger which gather npm packages by uploading either a json file (package.json) or a picture representing package.json. To continue...

package-fetcher Ce projet contient un boilerplate pour un bot messenger et l'executable Windows ngrok qui va permettre de créer un tunnel https pour c

AILI Fida Aliotti Christino 2 Mar 29, 2022
Live port of Lark's standalone parser to Javascript

Lark.js Generate LALR(1) parsers in Javascript Lark is a popular parsing toolkit for Python. This project is a live port of the Lark standalone parser

Lark - Parsing Library & Toolkit 51 Nov 19, 2022
qrcode generation standalone (doesn't depend on external services)

jquery.qrcode.js jquery.qrcode.js is jquery plugin for a pure browser qrcode generation. It allow you to easily add qrcode to your webpages. It is sta

Jerome Etienne 4.8k Dec 29, 2022
Standalone Epub reader using Bibi.

bi-epub-reader Epub reader application using Bibi. Features Beautiful epub viewer Open file as associated file type Standalone application You can see

azu 8 Aug 5, 2022
GraphQL Hive provides all the tools the get visibility of your GraphQL architecture at all stages, from standalone APIs to composed schemas (Federation, Stitching)

GraphQL Hive GraphQL Hive provides all the tools the get visibility of your GraphQL architecture at all stages, from standalone APIs to composed schem

Kamil Kisiela 184 Dec 21, 2022
Standalone AJAX library inspired by jQuery/zepto

ajax Standalone AJAX library inspired by jQuery/zepto Installation component-install ForbesLindesay/ajax Then load using: var ajax = require('ajax');

Forbes Lindesay 365 Dec 17, 2022
NFT Marketplace framework to build standalone NFT marketplace or inApp/inGame NFT marketplace

NFT Marketplace This project is a decentalized NFT Marketplace framework which is to be the baseline for you to build standalone NFT marketplace or in

Reddio, inc. 14 Dec 19, 2022
The Remix version of the fakebooks app demonstrated on https://remix.run. Check out the CRA version: https://github.com/kentcdodds/fakebooks-cra

Remix Fakebooks App This is a (very) simple implementation of the fakebooks mock app demonstrated on remix.run. There is no database, but there is an

Kent C. Dodds 61 Dec 22, 2022
Remix Stack for deploying to Vercel with remix-auth, Planetscale, Radix UI, TailwindCSS, formatting, linting etc. Written in Typescript.

Remix Synthwave Stack Learn more about Remix Stacks. npx create-remix --template ilangorajagopal/synthwave-stack What's in the stack Vercel deploymen

Ilango 56 Dec 25, 2022
Remix enables you to build fantastic user experiences for the web and feel happy with the code that got you there. In this workshop, we'll look at some more advanced use cases when building Remix applications.

?? Advanced Remix Workshop Remix enables you to build fantastic user experiences for the web and feel happy with the code that got you there. In this

Frontend Masters 167 Dec 9, 2022
Remix enables you to build fantastic user experiences for the web and feel happy with the code that got you there. Get a jumpstart on Remix with this workshop.

?? Remix Fundamentals Build Better websites with Remix Remix enables you to build fantastic user experiences for the web and feel happy with the code

Frontend Masters 204 Dec 25, 2022
simple-remix-blog is a blog template built using Remix and TailwindCSS. Create your own blog in just a few minutes!

simple-remix-blog is a blog template built using remix.run and TailwindCSS. It supports markdown and MDX for the blog posts. You can clone it and star

José Miguel Álvarez Vañó 8 Dec 8, 2022
An Open Source Remix template that integrates Stripe Subscriptions, Social Authentication, Testing and a few more features. PostgreSQL version. Deploys to Fly.io

Live Demo · Twitter An open source Remix Stack that integrates Stripe Subscriptions, Social Authentication, Testing and a few more features. PostgreSQ

xo 25 Dec 7, 2022
An Open Source Remix template that integrates Stripe Subscriptions, Social Authentication, Testing and a few more features. SQLite version. Deploys to Fly.io

Live Demo · Twitter An Open Source Remix template that integrates Stripe Subscriptions, Social Authentication, Testing and a few more features. SQLite

xo 135 Dec 31, 2022