# Home-screen widget - JavaScript bridge API

> A small Android card on the home screen that your page fills with a title, a value and a few lines - AppMint.widget.

- **Applies to:** AppMint
- **Source:** extracted from the app runtime and its per-method example files; this page is generated from them.
- **HTML:** https://freewebtoapk.com/docs/api/widget

### `AppMint.widget`

```js
AppMint.widget.set(card) / clear() / placedCount() / requestPin()
```

**Example**

Fills your app's home-screen widget: a small native card with a title, one big value, up to six short lines, your colours, and a route that a tap opens. A widget cannot show HTML - you send it the text.

**Returns:** every method returns a Promise. `set(card)` → `{ok: true, placed}` (`placed` = how many copies are on the home screen) or `{ok: false, error}`. `clear()` → `undefined`. `placedCount()` → a number. `requestPin()` → `true` if the launcher's "Add" sheet opened. **Needs:** nothing - every build has the widget.

**Set the card** - once at start, and again every time the data it shows changes:

```js
async function updateWidget(events) {
  if (!(window.AppMint && AppMint.widget)) return;          // in a browser
  var r = await AppMint.widget.set({
    title: 'Today',
    value: events.length + ' events',
    lines: events.slice(0, 6).map(function (ev) { return ev.time + ' ' + ev.name; }),
    route: '/calendar',      // a tap opens the app at this route
    bg: '#0E7C86',           // background
    ink: '#FFFFFF',          // title and lines
    accent: '#FFE08A'        // the big value
  });
  if (!r.ok) console.log('Widget not updated: ' + r.error);
}
```

**An "Add to home screen" button:**

```js
async function addWidget() {
  if (!(window.AppMint && AppMint.widget)) return;
  if ((await AppMint.widget.placedCount()) > 0) { alert('The widget is already on your home screen'); return; }
  var opened = await AppMint.widget.requestPin();
  if (!opened) alert('Touch and hold your home screen, tap Widgets, and pick this app.');
}
```

**Empty it** (for example after the user signs out):

```js
if (window.AppMint && AppMint.widget) AppMint.widget.clear();   // shows "Nothing to show yet"
```

**A tap on the widget** opens the app with `appmint-shortcut://<package><route>` as its launch link - read it with `WebToApk.getLaunchUrl()` on start and the `appmint:deep-link` event while running:

```js
window.addEventListener('appmint:deep-link', function (e) {
  var m = /^appmint-shortcut:\/\/[^\/?#]*([^#]*)/i.exec(e.detail.url);
  if (m) goTo(m[1] || '/');
});
```

**Notes:** All card fields are optional: an empty `title` shows the app name; empty `value` or lines are hidden; lines after the sixth are dropped; colours are `#RRGGBB` / `#AARRGGBB` (a bad colour uses the default). The widget keeps the last card, even after a restart, and changes only when your page calls `set()` again. `requestPin()` needs Android 8+ and a launcher that supports it. AI-built apps can use `widget` from `@/lib/appmintNative`. **Website-mode apps:** a widget tap restarts the app, and in Website mode the shell then tries to load the `appmint-shortcut://` address as a page, which fails (the WebView cannot open that kind of address) - so a tap `route` only works in HTML, ZIP and AI-built apps.

### `widgetClear`

```js
window.WebToApk.widgetClear()
```

Removes the card; placed widgets go back to their empty state.

**Example**

Internal plumbing behind `AppMint.widget.clear()` - removes the widget's card; every placed widget goes back to "Nothing to show yet".

**Returns:** nothing. **Needs:** nothing.

The public API first:

```js
async function onSignOut() {
  if (window.AppMint && AppMint.widget) await AppMint.widget.clear();
}
```

The raw call:

```js
if (window.WebToApk && typeof window.WebToApk.widgetClear === 'function') {
  window.WebToApk.widgetClear();
}
```

**Notes:** The widget stays on the home screen; only its content is removed. Call `AppMint.widget.set()` to fill it again.

### `widgetPlacedCount`

```js
window.WebToApk.widgetPlacedCount(): Int
```

How many copies of the widget the user has placed on the home screen.

**Example**

Internal plumbing behind `AppMint.widget.placedCount()` - how many copies of your widget the user has put on the home screen.

**Returns:** a number, synchronously (`0` when none). **Needs:** nothing.

The public API first - show an "Add widget" button only when the widget is not placed yet:

```js
async function showAddWidgetButton() {
  var btn = document.getElementById('add-widget');
  if (!(window.AppMint && AppMint.widget)) { btn.hidden = true; return; }
  btn.hidden = (await AppMint.widget.placedCount()) > 0;
}
```

The raw call:

```js
if (window.WebToApk && typeof window.WebToApk.widgetPlacedCount === 'function') {
  var n = window.WebToApk.widgetPlacedCount();
  console.log('Widgets on the home screen: ' + n);
}
```

**Notes:** Check it again when the app comes back to the front (`visibilitychange`), since the user adds widgets from the launcher, outside your app.

### `widgetRequestPin`

```js
window.WebToApk.widgetRequestPin(): Boolean
```

Opens the launcher's "Add to home screen" sheet for the widget (Android 8+). False where the launcher cannot.

**Example**

Internal plumbing behind `AppMint.widget.requestPin()` - opens the launcher's "Add to home screen" sheet for your widget.

**Returns:** `true` if the sheet opened, `false` where the launcher cannot (synchronously). **Needs:** Android 8+ and a launcher that supports pinning widgets.

The public API first, from a button tap:

```js
document.getElementById('add-widget').onclick = async function () {
  if (!(window.AppMint && AppMint.widget)) return;
  var opened = await AppMint.widget.requestPin();
  if (!opened) {
    alert('Touch and hold your home screen, tap Widgets, then pick this app.');
  }
};
```

The raw call:

```js
if (window.WebToApk && typeof window.WebToApk.widgetRequestPin === 'function') {
  if (!window.WebToApk.widgetRequestPin()) showManualSteps();
}
```

**Notes:** `true` only means the sheet opened - the user can still cancel it. Use `AppMint.widget.placedCount()` later to see whether it was added. Fill the card with `AppMint.widget.set()` first, so the new widget is not empty.

### `widgetSet`

```js
window.WebToApk.widgetSet(cardJson: String): String
```

Saves the widget card [cardJson] `{title?, value?, lines?, route?, bg?, ink?, accent?}` and redraws every placed widget. Returns `{ok, placed}`.

**Example**

Internal plumbing behind `AppMint.widget.set(card)` - pages use that helper to fill the home-screen widget.

**Returns:** a JSON string `{"ok":true,"placed":<number>}` or `{"ok":false,"error":"…"}` (synchronously). **Needs:** nothing - every build has the widget.

The public API first:

```js
if (window.AppMint && AppMint.widget) {
  AppMint.widget.set({ title: 'Steps', value: '8 214', lines: ['Goal 10 000'], route: '/' })
    .then(function (r) { if (!r.ok) console.log(r.error); });
}
```

The raw call takes the card as a JSON string and returns JSON text:

```js
if (window.WebToApk && typeof window.WebToApk.widgetSet === 'function') {
  var card = { title: 'Steps', value: '8 214', lines: ['Goal 10 000'], route: '/',
               bg: '#15161A', ink: '#FFFFFF', accent: '#22D3EE' };
  var r = JSON.parse(window.WebToApk.widgetSet(JSON.stringify(card)));
  console.log(r.ok ? 'on ' + r.placed + ' home screen(s)' : r.error);
}
```

**Notes:** Card keys: `title`, `value`, `lines` (up to six), `route` (a `/` is added if missing), `bg`, `ink`, `accent`. Every placed widget redraws at once. `placed` is `0` when the user has not added the widget yet - the card is still saved and appears when they do.

