React Native Flow

App Features

Quick Tools Widget (iOS + Android)

A website-ready overview and starter setup for the Quick Tools home-screen widget. Users can jump directly to Notes (Summarize), Scan, and PDF Tools from iOS and Android widgets using deep links.

Supported platforms

  • iOS: built with `expo-widgets` + `@expo/ui/swift-ui`.
  • Android: built with `react-native-android-widget`.

What users can do

From the home screen, one tap opens these routes in-app:

  • Notes (Summarize)
  • Scan
  • PDF Tools

Design summary

  • Branded title section: `Quick Tools`.
  • Compact action chips for quick, reliable tap targets.
  • Theme-aware rendering for light and dark modes.

Example screenshot

Reference preview of the Quick Tools widget on an iPhone home screen.

Quick Tools widget shown on iPhone home screen with Notes, Scan, and PDF actions.
Quick Tools widget example on iOS home screen.

Website listing copy

Short copy

Add this widget to your home screen for one-tap access to Notes, Scan, and PDF tools. Available on iOS and Android with a fast, clean, theme-aware design.

Long copy

Bring quick actions to your home screen with the Quick Tools widget.

Jump straight into Notes (Summarize), Scan, and PDF Tools without opening the app first.

The widget is optimized for speed, supports modern light/dark themes, and is available on both iOS and Android.

iOS widget details

  • Widget definition: `src/widgets/QuickToolsWidget.tsx`.
  • Registered through the `expo-widgets` plugin config in `app.json`.
  • Supports `systemMedium` and `systemLarge` families.
  • Deep links: `yourapp://?widgetTarget=summarize`, `yourapp://?widgetTarget=scan`, `yourapp://?widgetTarget=pdf`.

Android widget details

  • Widget UI file: `src/widgets/android/QuickToolsAndroidWidget.tsx`.
  • Task handler: `src/widgets/android/widgetTaskHandler.tsx`.
  • Registration entrypoint: `index.ts`.
  • Android config plugin: `react-native-android-widget` in `app.json`.
  • Default size: `minWidth 260dp`, `minHeight 140dp`, `targetCellWidth 4`, `targetCellHeight 2`.

Implementation steps (with code)

Choose your widget style

  • Option A - Simple widget: minimal UI, quick to ship, easiest to maintain.
  • Option B - Detailed widget: richer design (badges, chips, borders, theme variants).

If you only want a clean and simple widget, follow Option A only.

Option A - iOS Widget (Simple)

iOS Step 1: Add plugin config in `app.json`

[
  "expo-widgets",
  {
    "bundleIdentifier": "com.app.YourApp.ExpoWidgetsTarget",
    "groupIdentifier": "group.com.app.YourApp",
    "widgets": [
      {
        "name": "QuickToolsWidget",
        "displayName": "Quick Tools",
        "description": "Open Summarize, Scan, and PDF quickly.",
        "supportedFamilies": ["systemMedium", "systemLarge"]
      }
    ]
  }
]

iOS Step 2: Create `src/widgets/QuickToolsWidget.tsx`

import { HStack, Link, Text, VStack } from "@expo/ui/swift-ui";
import { createWidget, type WidgetEnvironment } from "expo-widgets";

type QuickToolsWidgetProps = {
  heading?: string;
};

const QuickToolsWidgetView = (
  props: QuickToolsWidgetProps,
  _environment: WidgetEnvironment
) => {
  "widget";

  return (
    <VStack spacing={10}>
      <Text>{props.heading ?? "Quick Tools"}</Text>
      <HStack spacing={6}>
        <Link label="Notes" destination="yourapp://?widgetTarget=summarize" />
        <Link label="Scan" destination="yourapp://?widgetTarget=scan" />
        <Link label="PDF" destination="yourapp://?widgetTarget=pdf" />
      </HStack>
    </VStack>
  );
};

export default createWidget("QuickToolsWidget", QuickToolsWidgetView);

iOS Step 3: Register iOS widget handling in `src/app/_layout.tsx`

if (Platform.OS === "ios") {
  const quickToolsWidgetModule = await import("../widgets/QuickToolsWidget");
  const expoWidgetsModule = await import("expo-widgets");
  const QuickToolsWidget = quickToolsWidgetModule.default;
  QuickToolsWidget.updateSnapshot({ heading: "Quick Tools" });

  expoWidgetsModule.addUserInteractionListener((event) => {
    // Handle widget button targets
  });
}

Option A - Android Widget (Simple)

Android Step 1: Install package

yarn add react-native-android-widget

Android Step 2: Add plugin config in `app.json`

[
  "react-native-android-widget",
  {
    "widgets": [
      {
        "name": "QuickToolsAndroid",
        "label": "Quick Tools",
        "description": "Open Summarize, Scan, and PDF quickly.",
        "previewImage": "./assets/images/icon.png",
        "minWidth": "260dp",
        "minHeight": "140dp",
        "targetCellWidth": 4,
        "targetCellHeight": 2
      }
    ]
  }
]

Android Step 3: Create `src/widgets/android/QuickToolsAndroidWidget.tsx`

"use no memo";
import React from "react";
import { FlexWidget, TextWidget } from "react-native-android-widget";

export function renderQuickToolsAndroidWidget() {
  return (
    <FlexWidget
      style={{ height: "match_parent", width: "match_parent", padding: 14 }}
    >
      <TextWidget text="Quick Tools" style={{ fontSize: 16, fontWeight: "700" }} />

      <FlexWidget style={{ flexDirection: "row", flexGap: 8, marginTop: 10 }}>
        <FlexWidget
          clickAction="OPEN_URI"
          clickActionData={{ uri: "yourapp://?widgetTarget=summarize" }}
        >
          <TextWidget text="Notes" />
        </FlexWidget>

        <FlexWidget
          clickAction="OPEN_URI"
          clickActionData={{ uri: "yourapp://?widgetTarget=scan" }}
        >
          <TextWidget text="Scan" />
        </FlexWidget>

        <FlexWidget
          clickAction="OPEN_URI"
          clickActionData={{ uri: "yourapp://?widgetTarget=pdf" }}
        >
          <TextWidget text="PDF" />
        </FlexWidget>
      </FlexWidget>
    </FlexWidget>
  );
}

Android Step 4: Create `src/widgets/android/widgetTaskHandler.tsx`

import type { WidgetTaskHandlerProps } from "react-native-android-widget";
import { renderQuickToolsAndroidWidget } from "./QuickToolsAndroidWidget";

export async function widgetTaskHandler(props: WidgetTaskHandlerProps) {
  if (props.widgetInfo.widgetName !== "QuickToolsAndroid") return;

  props.renderWidget({
    light: renderQuickToolsAndroidWidget(),
    dark: renderQuickToolsAndroidWidget(),
  });
}

Android Step 5: Register handler in root `index.ts`

import { Platform } from "react-native";
import { registerWidgetTaskHandler } from "react-native-android-widget";
import { widgetTaskHandler } from "./src/widgets/android/widgetTaskHandler";
import "expo-router/entry";

if (Platform.OS === "android") {
  registerWidgetTaskHandler(widgetTaskHandler);
}

Option B - Detailed Variants (Also Possible)

For a more premium look, these upgrades are also possible:

  • Add a header badge/icon plus a subtitle.
  • Use action chips with border radius and custom colors.
  • Add separate light and dark widget rendering.
  • Add clickable zones for each action (Notes / Scan / PDF).
  • Add a custom preview image for the widget picker.

iOS detailed upgrade example

<VStack spacing={12}>
  <HStack spacing={8}>
    <Text>Quick Tools</Text>
    <Text>Fast actions from home screen</Text>
  </HStack>
  <HStack spacing={6}>
    <Link label="Notes" destination="yourapp://?widgetTarget=summarize" />
    <Link label="Scan" destination="yourapp://?widgetTarget=scan" />
    <Link label="PDF" destination="yourapp://?widgetTarget=pdf" />
  </HStack>
</VStack>

Android detailed upgrade example

props.renderWidget({
  light: renderQuickToolsAndroidWidget("light"),
  dark: renderQuickToolsAndroidWidget("dark"),
});
// In QuickToolsAndroidWidget.tsx
// Use styled chips, borders, badge, and theme palette maps.

Build / refresh steps

  • npx expo prebuild
  • yarn ios
  • yarn android
  • If the widget is blank or stale, remove it from the home screen and add it again.

Note

Code is taken from Briefix app, my own product will be live soon.

Briefix — Coming Soon

Sponsored

Quick promo