Home Screen Shortcuts in React Native (with Expo)
Tags: reactnative, javascript, ios, android
Published: 2021-08-19 20:25:06

On March 22, 2017 Apple acquired "Workflow", an app which has since been re-branded and distributed as "Shortcuts".

![Workflow](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o26suilc08t3l77r9q6m.png)
 
 

It's a versatile app, enabling users to string together features from various apps installed on their device.

*One such feature is the ability to add Shortcuts to the iOS home-screen.*

Developers can access these features programmatically with [SiriKit](https://developer.apple.com/documentation/sirikit), the SDK used to interact with Siri and Shortcuts.

![siri copy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ngjox16nsgb80kupxnan.png)

To use SiriKit in React Native, like most native SDKs, it's common to install an existing library and link native dependencies.

At this time, I've only found one popular library to solve this problem:  [react-native-siri-shortcut](https://github.com/Gustash/react-native-siri-shortcut)

I found another called [react-native-siri-shortcuts](https://www.npmjs.com/package/react-native-siri-shortcuts), but it has low NPM activity and partial implementation.

Unfortunately, I found three issues with this approach:

###  Cross-Platform Compatibility

Because SiriKit is an iOS-only feature, you won't be able to save shortcuts to your Android home-screen.

Android [has its own solution](https://developer.android.com/guide/topics/ui/shortcuts/creating-shortcuts) for this.

### Expo Ejection

[react-native-siri-shortcut](https://github.com/Gustash/react-native-siri-shortcut) needs to be linked, so, to use it with an Expo app, you'll need to eject.

![c6d1d5e3eac6bd923ec571c3eedeaa1e](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sdqth3wh9nya6f3zt772.gif)
 
Luckily, with the new "Bare" Expo workflow, this is [easier than ever](https://docs.expo.dev/bare/exploring-bare-workflow/
).

###  Viral License

[react-native-siri-shortcut](https://github.com/Gustash/react-native-siri-shortcut) is licensed under [GPL-3](https://github.com/Gustash/react-native-siri-shortcut/blob/main/LICENSE).

This is considered a "copyleft" and "viral" license, because all distributed dependent work is (usually) required to be licensed under the same terms:

>  You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. - [GPL v3 Section 5c](https://www.gnu.org/licenses/gpl-3.0.en.html)

I personally avoid dependencies with viral licensing, especially in commercial products.

If you don't know what licenses you're currently using, I suggest the [license-checker](https://www.npmjs.com/package/license-checker) NPM tool.

I use this command to check for [several common "viral" licenses](https://tldrlegal.com/licenses/tags/Viral): 

```bash
license-checker | grep "GPL\|CC\|MTS\|Mechanical" -B1
```
*Tip:  Not all CC licenses are copyleft.  Look for the "ShareAlike" qualifier.*

##  Homeward

Given these problems, we built a small web app, called [Homeward](https://github.com/CodalReef/homeward), to save shortcuts to the iOS / Android home-screen.

To use it, re-direct users from your mobile app to the Homeward web app with the required parameters.

The user will then be prompted to save the link to their home-screen:

![Example](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/anu7aab9g5bwmlnr2nl3.png)

To simplify this process in React Native / Expo apps, we built [Homeward SDK](https://github.com/CodalReef/homeward-sdk).

### Installation

```bash
npm i https://github.com/CodalReef/homeward-sdk
```

>  **NOTE**
>  We plan on publishing to npm shortly.

###  Create the Link
Next, create the deep link you'd like saved to the user's home-screen:

```typescript
const link = "myapp://feature1.context1?payload={ ... }"
```

The exact format of the link will depend on your application.

If you're using Expo, the [expo-linking](https://docs.expo.dev/guides/linking/) library can help with this:

```typescript
import * as Linking from 'expo-linking';
const link = Linking.makeUrl();
```

###  Build a Web App Manifest

The Homeward SDK directs the user to a web browser where they can save the icon to their home-screen.

The style of both the icon and the web page are controlled by the supplied [Web App Manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest) JSON.

Web App Manifests are an experimental web standard supported by [several major browsers](https://developer.mozilla.org/en-US/docs/Web/Manifest#browser_compatibility).

Let's make a Web App Manifest to save a Calendar icon to the home-screen:

```typescript
import { WebAppManifest } from 'homeward';
const manifest: WebAppManifest = {
    name: "Calendar",
    background_color: "#79ccd2",
    theme_color: "#79ccd2",
    "icons": [{
        "src": "https://image.flaticon.com/icons/png/512/2948/2948115.png",
        "sizes": "512x512",
        "type": "image/jpeg"
    }]
}
```

The [name](https://developer.mozilla.org/en-US/docs/Web/Manifest/name) field will be shown below the icon on the home-screen.

The [theme_color](https://developer.mozilla.org/en-US/docs/Web/Manifest/theme_color) field is used on Android to style the navigation bar and on iOS to style the default icon.

The [background_color](https://developer.mozilla.org/en-US/docs/Web/Manifest/background_color) field is a transitory color shown while loading the browser.


If you do not specify an icon, [a default icon is created](https://github.com/CodalReef/homeward#default-icon).

>  **NOTE** 
> Android has full support for custom icons, but on iOS you [must specify a "180x180" icon](https://github.com/CodalReef/homeward#custom-icon).


###  Trigger Save to Home

With the link and the manifest, we can now save the icon to the home-screen:

```typescript
import { saveToHome } from 'homeward';

saveToHome({ link, manifest });
```

This immediately redirects the user to the web app with instructions on how to save the shortcut (shown above).

Once saved, the user can tap the home-screen icon to be directed to the cached Homeward PWA.  This then immediately opens the provided link.

The PWA stays open in the switcher and can be tapped again to re-open the deep link.

>  See [Pitch / Antipitch](#pitch--anti-pitch) and [Disclaimer](#disclaimer) for caveats and further discussion.

##  Technical Details

I originally considered abstracting over native iOS / Android APIs, but, a solution effectively exists.

On both plaftorms, the built-in web browser has a "Save to Home-Screen" feature.

Apps like "Facebook Groups", "Workflow", and others have taken advantage of this to create ad-hoc home-screen shortcuts.

This approach is [documented on StackOverflow](https://stackoverflow.com/questions/28042152/link-to-safari-add-to-home-screen-from-inside-app):

1.  Redirect from the Native App to a Web App

2.  Check the timestamp of the request.  If it's new, prompt the user to save the shortcut to their home-screen.  If it's old, re-direct to the deep link.

3.  When the user taps the icon on their home-screen, it will redirect to the same Web URL but with an old timestamp, triggering the deep link.

## Conclusion

This solution provides a standardized way of saving a deep link across platforms without abstracting over disparate APIs.

There's a *lot* of interesting work to be done bridging the gap in SiriKit, Shortcuts, and the associated Android SDKs.  

I'm sure usable SDK wrappers will be available soon, but in the meantime, this browser-based solution has worked for me.

I hope you enjoyed this write-up on SiriKit, shortcuts, and my personal struggles.

Cheers,
CodalReef


*If you'd like more articles like this, feel free to follow me on:  [Github](https://github.com/CodalReef), [Dev](https://dev.to/codalreef), [Twitter](https://twitter.com/CodalReef), [Reddit](https://www.reddit.com/user/CodalReef)*


*The Calendar icon was created by [bqlqn](https://www.flaticon.com/authors/bqlqn) and hosted by [Flat Icon](https://www.flaticon.com/free-icon/calendar_2948115?term=calendar&page=2&position=69&page=2&position=69&related_id=2948115)*