Criar APK grátis

API da ponte JavaScript

Abertura, atalhos e o botão voltar

Como o app foi aberto, atalhos de pressionar e segurar no ícone, o pedido de avaliação no app e como avisar o shell de que a página quer o toque em voltar.

AppMint.requestReview helper#

AppMint.requestReview(options)

Exemplo

Pede ao Google Play que mostre a própria folha de avaliação dentro do app (Play In-App Review) e informa o que aconteceu.

Retorna: uma Promise que sempre é resolvida com {result, openedStore, message?}. result é 'shown' (o Play exibiu sua folha — ele nunca informa se o usuário avaliou), 'not_from_play' (esta instalação não veio do Google Play: um APK instalado manualmente ou uma instalação de teste, em que o Play nunca mostra a folha), 'quota' (o Play decidiu não exibi-la agora: a cota dele para este usuário, ou o usuário já avaliou) ou 'error' (não foi possível consultar o Play: sem Play Store, offline). Com {openStore: true}, a página do app no Play abre quando a folha não apareceu, e openedStore é true. Requer: nada para ativar.

Qualquer código:

// A "Rate us" button: the sheet when Play shows it, the Play listing otherwise.
document.getElementById('rate-btn').onclick = async function () {
  if (!(window.AppMint && AppMint.requestReview)) { location.href = 'https://play.google.com/store/apps/details?id=com.example.app'; return; }
  var r = await AppMint.requestReview({ openStore: true });
  if (r.result === 'shown' || r.openedStore) showToast('Thank you!');
};

Pergunte depois de um momento de sucesso em vez de a partir de um botão, sem nunca sair do app:

async function onOrderDelivered(count) {
  if (count !== 3 || !(window.AppMint && AppMint.requestReview)) return;
  var r = await AppMint.requestReview();      // no openStore: nothing opens if Play says no
  if (r.result === 'not_from_play') console.log('Test install: Play only shows the sheet for Play installs');
}

Quando o criador ativou Pedir aos usuários que avaliem o app (etapa Exibição), o app pergunta por conta própria em um momento tranquilo e informa à página o que aconteceu:

window.addEventListener('appmint:review', function (e) {
  // e.detail = { result, openedStore: false, source: 'auto' }
  analytics.track('rate_prompt', { result: e.detail.result });
});

Observações: O Google Play limita a frequência da folha e decide por conta própria se ela aparece; nunca recompense uma avaliação nem prometa a folha em um botão. Teste com uma instalação da faixa de teste interno do Play - um APK instalado manualmente sempre responde not_from_play.

Sem código: o link appmint://review. Um botão ou link com este endereço pede a mesma folha (e abre a página do Play quando o Play não a mostra, porque o usuário pediu para avaliar). Em uma mensagem no app, coloque-o em um botão na central de envios (o modelo Avalie-nos faz isso); em uma página, use como um link simples:

<a href="appmint://review" class="rate-link">Rate us on Google Play</a>

A partir de um script, por exemplo, depois do terceiro pedido concluído:

function maybeAskForRating(ordersDone) {
  if (ordersDone === 3) location.href = 'appmint://review';   // the app runs it; nothing is loaded
}

Saiba o que o usuário escolheu em uma mensagem no app "Avalie-nos" antes de a folha abrir:

window.addEventListener('appmint:inapp', function (e) {
  var d = e.detail;
  if (d.type === 'answered' && d.question === 'stars' && d.value <= 3) showFeedbackForm();
  if (d.type === 'clicked' && d.link === 'appmint://review') console.log('Opening the Play review sheet');
});

AppMint.setBackHandler helper#

AppMint.setBackHandler(handler)

Exemplo

Dá à sua página a primeira palavra quando o usuário aperta o botão Voltar do celular (ou usa o gesto de voltar). Necessário para apps que trocam de tela mostrando e ocultando elementos, onde o histórico do Android está vazio e Voltar fecharia o app.

Retorna: nada. Seu handler deve retornar true (tratado, ficar aqui) ou false (deixar o app voltar / sair). Requer: nada. Instalado no início do documento, então você pode registrá-lo no seu primeiro script.

if (window.AppMint && AppMint.setBackHandler) {
  AppMint.setBackHandler(function () {
    if (isMenuOpen)               { closeMenu();  return true; }   // consumed
    if (currentScreen !== 'home') { goTo('home'); return true; }
    return false;   // nothing to undo: normal Back (history back, exit dialog, exit)
  });
}

// Remove it again, for example when the screen that needed it closes:
// AppMint.setBackHandler(null);

O evento appmint:back - cancelável. Chame e.preventDefault() para consumir o toque. Ele roda antes do manipulador, e qualquer número de ouvintes pode usá-lo:

window.addEventListener('appmint:back', function (e) {
  var sheet = document.querySelector('.bottom-sheet.open');
  if (sheet) {
    sheet.classList.remove('open');
    e.preventDefault();   // consumed: the handler and the shell do nothing more
  }
});

Evite perder uma nota pela metade: Voltar mostra sua própria barra "Descartar alterações?" em vez de sair (um confirm() bloqueante perderia a janela de resposta de 350 ms, e o shell voltaria de qualquer jeito):

if (window.AppMint && AppMint.setBackHandler) {
  var noteDirty = false;
  document.getElementById('note').addEventListener('input', function () { noteDirty = true; });

  AppMint.setBackHandler(function () {
    if (!noteDirty) return false;        // nothing to lose: normal Back
    showDiscardBar();                    // your in-page "Discard changes? / Keep editing" bar
    return true;                         // stay here while the user decides
  });

  document.getElementById('discard-btn').onclick = function () {
    noteDirty = false;                   // the next Back press passes straight through
    hideDiscardBar();
    closeEditor();
  };
}

Observações: A resposta deve ser síncrona: retornar uma Promise conta como "não tratado". Responda rápido - se a página não responder em cerca de 350 ms, o shell volta por conta própria. Ordem a cada toque: um menu lateral aberto (a gaveta do próprio app) fecha primeiro e a página não é consultada; depois os ouvintes de appmint:back → seu manipulador → o fechador de diálogos embutido do shell (fecha um <dialog> aberto, diálogo ARIA ou modal em tela cheia) → voltar no histórico / confirmação de saída / saída. Apps que usam history.pushState para cada tela (React Router e similares) não precisam disto. Apps criados com IA podem usar onBackGesture de @/lib/appmintNative.

__pullRefreshEligible ponte#

window.WebToApk.__pullRefreshEligible(eligible: Boolean)

Veja [pullPageEligible] / [pullProbeJs]. Chamado a cada touchstart.

Exemplo

Estrutura interna por trás de puxar para atualizar: a sonda de toque do próprio shell a chama a cada toque para dizer se um puxão para baixo ali deve atualizar a página. As páginas nunca a chamam - elas controlam puxar para atualizar com CSS padrão e eventos de toque.

Retorna: nada. Requer: Ativar puxar para atualizar ligado na Etapa 3 (Integrar), em Opções de exibição, ao compilar (sem isso, a sonda não é instalada).

A forma pública de impedir que o puxar para atualizar atue em parte da sua página — reivindique o gesto:

<style>
  /* A map, drawing canvas or slider: this element owns vertical drags. */
  #map, #canvas { touch-action: none; }
  /* A horizontal carousel: pan-x also tells the shell "not a refresh". */
  .carousel { touch-action: pan-x; }
</style>

Ou reivindique a partir de um manipulador de toque, da forma padrão:

document.getElementById('canvas').addEventListener('touchstart', function (e) {
  e.preventDefault();   // the page took this gesture: no pull-to-refresh
}, { passive: false });

Impeça uma superfície de arrastar e dar zoom de atualizar a página reivindicando os arrastos verticais apenas com CSS:

<div id="board" style="touch-action: none; height: 60vh"></div>
<script>
  // Dragging on #board moves the board; a pull from the top of the rest of the page still refreshes.
  document.getElementById('board').addEventListener('pointermove', function (e) { moveBoard(e); });
</script>

Observações: Um puxão só atualiza quando a caixa rolável mais próxima sob o dedo (ou a própria página) está rolada até o topo, apenas um dedo está apoiado e nenhuma das reivindicações acima se aplica. Um toque dentro de um iframe de outra origem nunca atualiza. Não chame este método você mesmo.

getAppIcon ponte#

window.WebToApk.getAppIcon(): String

O ícone do launcher em uso: "default" ou um dos nomes de getAvailableIcons().

Exemplo

O ícone do launcher em uso: 'default' ou um dos nomes de getAvailableIcons().

Retorna: uma string. 'default' em uma compilação sem ícones alternativos.

if (window.WebToApk && WebToApk.getAppIcon) {
  const current = WebToApk.getAppIcon();          // 'default', 'Dark', …
  document.querySelectorAll('[data-icon]').forEach(el => {
    el.classList.toggle('selected', el.dataset.icon === current);
  });
}

Troque para o próximo ícone a partir de uma tela de configurações:

function nextIcon() {
  if (!(window.WebToApk && WebToApk.getAvailableIcons && WebToApk.setAppIcon)) return;
  const names = JSON.parse(WebToApk.getAvailableIcons());
  if (names.length < 2) return;                                  // no alternate icons in this build
  const next = names[(names.indexOf(WebToApk.getAppIcon()) + 1) % names.length];
  if (!WebToApk.setAppIcon(next)) alert('Could not change the icon.');
}

Mostre o nome do ícone em um rótulo ou oculte-o fora do app:

const label = document.getElementById('icon-label');
if (window.WebToApk && WebToApk.getAppIcon) {
  const name = WebToApk.getAppIcon();
  label.textContent = name === 'default' ? 'Classic icon' : name + ' icon';
} else {
  label.hidden = true;           // in a browser there is no launcher icon
}

getAvailableIcons ponte#

window.WebToApk.getAvailableIcons(): String

Array JSON dos nomes de ícones que setAppIcon aceita: "default" primeiro, depois os alternativos da compilação.

Exemplo

Os nomes de ícones que setAppIcon aceita, como uma string de array JSON: 'default' primeiro, depois os ícones alternativos do assistente de compilação na ordem em que você os adicionou.

Retorna: '["default","Dark","Gold"]', ou '["default"]' em uma compilação sem ícones alternativos.

Crie um seletor de ícones:

function iconPicker(container) {
  if (!(window.WebToApk && WebToApk.getAvailableIcons)) return;
  const names = JSON.parse(WebToApk.getAvailableIcons());
  if (names.length < 2) { container.hidden = true; return; }   // nothing to choose
  const current = WebToApk.getAppIcon();
  container.innerHTML = '';
  names.forEach(name => {
    const b = document.createElement('button');
    b.textContent = name === 'default' ? 'Classic' : name;
    b.className = name === current ? 'selected' : '';
    b.onclick = () => { if (WebToApk.setAppIcon(name)) iconPicker(container); };
    container.appendChild(b);
  });
}
iconPicker(document.querySelector('#iconPicker'));

Oculte o seletor em uma compilação sem ícones alternativos:

const picker = document.getElementById('iconPicker');
let names = ['default'];
if (window.WebToApk && WebToApk.getAvailableIcons) names = JSON.parse(WebToApk.getAvailableIcons());
picker.hidden = names.length < 2;      // only 'default' means there is nothing to choose

Troque o ícone junto com o tema:

function matchIconToTheme(dark) {
  if (!(window.WebToApk && WebToApk.getAvailableIcons && WebToApk.setAppIcon)) return;
  const names = JSON.parse(WebToApk.getAvailableIcons());
  const wanted = dark ? 'Dark' : 'default';
  if (names.includes(wanted) && WebToApk.getAppIcon() !== wanted) WebToApk.setAppIcon(wanted);
}
matchIconToTheme(matchMedia('(prefers-color-scheme: dark)').matches);

getLaunchUrl ponte#

window.WebToApk.getLaunchUrl(): String

O deep link que abriu ou retomou este app, ou "" se ele foi aberto normalmente. Leia sempre que seu app for montado e faça o roteamento você mesmo: const u = window.WebToApk?.getLaunchUrl?.(); if (u) router.navigate(new URL(u).pathname); O valor é MANTIDO, não consumido, então um app montado tarde ainda o vê; um link posterior que chegue com o app em execução o substitui e também dispara 'appmint:deep-link'.

Exemplo

O deep link que abriu (ou reabriu) o app, como string, ou "" quando o app foi aberto normalmente.

Retorna: uma string, de forma síncrona. Requer: nada. O valor é mantido, não consumido, então é seguro ler sempre que seu app for montado.

Um link pode chegar em três formatos: https://yoursite.com/path, o appmint-shortcut://<package>/<route> do próprio shell (atalhos do launcher, o widget da tela inicial) ou seu esquema personalizado myapp://segment/path. Este auxiliar transforma os três em uma rota:

function routeOf(link) {
  var m = /^([a-z][a-z0-9+.-]*):\/\/([^\/?#]*)([^#]*)/i.exec(link || '');
  if (!m) return '/';
  var scheme = m[1].toLowerCase(), host = m[2], rest = m[3] || '';
  if (scheme === 'http' || scheme === 'https' || scheme === 'appmint-shortcut') return rest || '/';
  return '/' + host + rest;               // myapp://product/42 -> /product/42
}

// 1. On start: the link that launched the app.
if (window.WebToApk && typeof window.WebToApk.getLaunchUrl === 'function') {
  var link = window.WebToApk.getLaunchUrl();
  if (link) goTo(routeOf(link));
}

// 2. While running: a new link replaces the old one and fires 'appmint:deep-link'.
window.addEventListener('appmint:deep-link', function (e) {
  goTo(routeOf(e.detail.url));            // detail: { url }
});

O mesmo aviso também é passado a um hook global, se você preferir um:

window.onAppMintDeepLink = function (detail) { goTo(routeOf(detail.url)); };

Leia um código de indicação de um link como https://yoursite.com/invite?code=AB12 ou myapp://invite?code=AB12, uma vez por link (usa routeOf de cima):

function applyInvite(link) {
  if (!link) return;
  var done = '';
  try { done = sessionStorage.getItem('handledLink') || ''; } catch (e) {}
  if (link === done) return;                      // the same url is announced again after a reload
  try { sessionStorage.setItem('handledLink', link); } catch (e) {}
  var code = null;
  try { code = new URL(link).searchParams.get('code'); } catch (e) { return; }
  if (code && routeOf(link).indexOf('/invite') === 0) showInviteBanner(code);
}

if (window.WebToApk && typeof window.WebToApk.getLaunchUrl === 'function') {
  applyInvite(window.WebToApk.getLaunchUrl());
  window.addEventListener('appmint:deep-link', function (e) { applyInvite(e.detail.url); });
}

Observações: appmint:deep-link também é disparado após cada carregamento de página enquanto um link é mantido, então o mesmo url pode chegar mais de uma vez. Ignore um link que você já tratou.

Apps no modo Site são diferentes: o próprio shell carrega um link https:// recebido (na abertura a frio e durante a execução), e um link de esquema personalizado myapp://product/42 é antes reescrito para o endereço do seu site (https://yoursite.com/product/42), então getLaunchUrl() retorna a forma https:// e sua página geralmente não tem nada a rotear. Um atalho do launcher ou toque em widget abre a rota no seu site (/today carrega https://yoursite.com/today), e getLaunchUrl() ainda retorna a forma appmint-shortcut:// (veja setAppShortcuts). Em apps HTML, ZIP e criados com IA (servidos de dentro do app), o shell nunca navega: sua página recebe o link e faz o roteamento. Um link de esquema personalizado permanece como chegou ali, porque não há endereço de site para mapeá-lo. Apps criados com IA podem usar launchUrl() de @/lib/appmintNative.

rateApp ponte#

window.WebToApk.rateApp(): String

Abre o fluxo de avaliação da página do Play. `rateApp()` já existia, mas só o item da gaveta nativa podia alcançá-lo, então um app que desenha a própria interface - toda compilação com IA, onde a gaveta está desligada - não tinha como pedir avaliação. É a única ação de loja que uma página realmente não pode fazer sozinha: `market://` é uma intent, não uma URL navegável. Controlado pelo próprio botão "Botão Avaliar app" do criador, exatamente como o item da gaveta e o item Compartilhar da navegação inferior: desligar Avaliar deve significar nenhuma superfície de avaliação em lugar nenhum, ou o botão parece quebrado.

Exemplo

Abre a página do app no Google Play para o usuário avaliá-lo.

Retorna: 'opened' quando a página foi aberta, 'off' quando o criador desativou Avaliar app (então nada acontece). Requer: o botão Botão Avaliar app na Etapa 5 (Menu) ao compilar (vem ativado por padrão; também adiciona um item "Avaliar app" ao menu lateral). Com ele desativado, a chamada não faz nada e retorna 'off'. Para a folha de avaliação no app do Google Play, use AppMint.requestReview().

var rateBtn = document.getElementById('rate-btn');
if (window.WebToApk && typeof window.WebToApk.rateApp === 'function') {
  rateBtn.onclick = function () { window.WebToApk.rateApp(); };
} else {
  rateBtn.hidden = true;   // in a browser
}

Ofereça a avaliação uma vez, depois que o usuário terminar cinco treinos, a partir de um cartão em que ele toque:

function maybeOfferRating(completedCount) {
  if (!window.WebToApk || typeof window.WebToApk.rateApp !== 'function') return;
  var asked = false;
  try { asked = localStorage.getItem('rateAsked') === '1'; } catch (e) {}
  if (asked || completedCount < 5) return;

  var card = document.getElementById('rate-card');   // "Enjoying the app? Rate it on Google Play"
  card.hidden = false;
  card.querySelector('.rate-yes').onclick = function () {
    window.WebToApk.rateApp();                         // opens the Play listing
    try { localStorage.setItem('rateAsked', '1'); } catch (e) {}
    card.hidden = true;
  };
  card.querySelector('.rate-later').onclick = function () { card.hidden = true; };
}

Uma linha "Avalie-nos" na sua tela de configurações que agradece quando o usuário volta do Google Play (o retorno da página ao primeiro plano é o único sinal de que o usuário voltou):

document.getElementById('settings-rate').onclick = function () {
  if (!window.WebToApk || typeof window.WebToApk.rateApp !== 'function') return;
  window.WebToApk.rateApp();
  document.addEventListener('visibilitychange', function onBack() {
    if (document.visibilityState !== 'visible') return;
    document.removeEventListener('visibilitychange', onBack);
    showToast('Thanks for taking a look!');           // your own toast; the user may not have rated
  });
};

Observações: Abre a página do app na Play Store (market://details?id=<package>), ou o site do Play quando o app Play Store não está instalado. Não é o cartão de avaliação dentro do app. Uma página não consegue abrir market:// por conta própria — é uma intent do Android, não um endereço web. Só peça depois que o usuário fizer algo de que gostou, e a partir de um toque.

requestReview ponte#

window.WebToApk.requestReview(optionsJson: String, callbackId: String)

Pede ao Play a folha de avaliação; [optionsJson] `{openStore?}`. Resolve AppMint.requestReview [callbackId].

Exemplo

Estrutura interna por trás de AppMint.requestReview() - as páginas usam esse auxiliar de Promise, que pede ao Google Play a folha de avaliação no app e resolve com o que aconteceu.

Retorna: nada diretamente; o resultado resolve a promise de AppMint.requestReview(). Requer: nada para ativar. A folha só aparece para um app instalado pelo Google Play.

A API pública:

async function askForRating() {
  if (!(window.AppMint && AppMint.requestReview)) return;          // a browser: no store here
  var r = await AppMint.requestReview();
  console.log(r.result);   // 'shown' | 'not_from_play' | 'quota' | 'error'
}

Pergunte depois de um bom momento e peça a página da loja quando a folha não aparecer:

async function afterHappyMoment() {
  if (!(window.AppMint && AppMint.requestReview)) return;
  const r = await AppMint.requestReview({ openStore: true });   // {result, openedStore, message?}
  if (r.result === 'shown') thankUser();
  else if (r.openedStore) console.log('Opened the Play listing instead');
}

Ouça o pedido automático e informe um erro:

window.addEventListener('appmint:review', (e) => {
  if (e.detail.source === 'auto') console.log('Rate prompt result:', e.detail.result);
});

AppMint.requestReview().then((r) => {
  if (r.result === 'error') console.warn(r.message);
  if (r.result === 'not_from_play') showMessage('Rating is available once the app is installed from Google Play.');
});

setAppIcon ponte#

window.WebToApk.setAppIcon(name: String): Boolean

Troca o ícone do launcher do app por um dos ícones alternativos adicionados no assistente de compilação, pelo nome dado lá ("default" = o ícone normal). Retorna false para um nome que esta compilação não tem. O launcher redesenha no seu próprio tempo (alguns segundos em certos celulares), e alguns launchers fecham o app ou movem o ícone da tela inicial quando ele muda - troque a partir de uma tela de configurações, não no meio de uma tarefa.

Exemplo

Troca o ícone do launcher do app por um dos ícones alternativos que você adicionou no assistente de compilação (etapa Básico, "Ícones alternativos do app"), pelo nome que você deu lá. 'default' é o seu ícone normal.

Retorna: true quando a troca foi feita (ou já é esse ícone), false para um nome que esta compilação não tem. Requer: ícones alternativos adicionados no assistente (até 4). Alguns launchers levam alguns segundos para redesenhar o ícone, e alguns fecham o app ou movem o atalho da tela inicial quando ele muda: troque a partir de uma tela de configurações, não no meio de uma tarefa. Seus atalhos do launcher (setAppShortcuts) são republicados com o novo ícone automaticamente.

function useIcon(name) {
  if (!(window.WebToApk && window.WebToApk.setAppIcon)) return false;
  const ok = WebToApk.setAppIcon(name);
  if (!ok) console.warn('no icon called', name);
  return ok;
}

document.querySelector('#darkIcon').addEventListener('click', () => useIcon('Dark'));
document.querySelector('#normalIcon').addEventListener('click', () => useIcon('default'));

Monte o seletor a partir dos ícones que esta compilação tem:

if (window.WebToApk && WebToApk.getAvailableIcons) {
  const names = JSON.parse(WebToApk.getAvailableIcons());   // 'default' first, then your alternates
  const current = WebToApk.getAppIcon();
  names.forEach((n) => addRadio('icon', n, n === current, () => WebToApk.setAppIcon(n)));
}

Verifique a resposta para um nome que a compilação não tem:

function pickIcon(name) {
  if (!(window.WebToApk && WebToApk.setAppIcon)) return showMessage('Icons can be changed in the app only');
  if (!WebToApk.setAppIcon(name)) {
    showMessage('Unknown icon "' + name + '". Choose one of: ' + JSON.parse(WebToApk.getAvailableIcons()).join(', '));
  } else {
    showMessage('Done. Your launcher may take a few seconds to redraw the icon.');
  }
}

Observações: a primeira atualização que ADICIONA ícones alternativos move a entrada do launcher para um novo componente, então um atalho da tela inicial feito antes dessa atualização pode precisar ser colocado de novo.

setAppShortcuts ponte#

window.WebToApk.setAppShortcuts(itemsJson: String)

Atalhos do launcher (pressionar e segurar o ícone do app). Até quatro entradas: `[{id, title, route}]`, em que `route` é um caminho no app ('/new-note'). Um toque abre o app com essa rota como deep link de abertura (`appmint-shortcut://<package><route>`), que a página lê por `getLaunchUrl()` e roteia exatamente como qualquer outro deep link. Em um app no modo Site, o próprio shell abre a rota no site (`/new-note` → `https://<site>/new-note`). Passe `[]` para removê-los. Android 7.1+; sem efeito abaixo disso.

Exemplo

Define os atalhos do launcher que aparecem quando o usuário toca e segura o ícone do app.

Retorna: nada. Requer: nada. Android 7.1+ (sem efeito abaixo disso).

itemsJson é uma string JSON: um array de até quatro objetos {id, title, route}. route é um caminho dentro do seu app. Um toque abre o app com appmint-shortcut://<package><route> como link de abertura:

if (window.WebToApk && typeof window.WebToApk.setAppShortcuts === 'function') {
  window.WebToApk.setAppShortcuts(JSON.stringify([
    { id: 'new-note', title: 'New note', route: '/new-note' },
    { id: 'search',   title: 'Search',   route: '/search' }
  ]));
}

Leia o toque da mesma forma que qualquer outro deep link, na abertura e durante a execução:

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

Remover todos os atalhos:

if (window.WebToApk && window.WebToApk.setAppShortcuts) window.WebToApk.setAppShortcuts('[]');

Observações: Cada chamada substitui a lista inteira. Entradas sem title são ignoradas; o rótulo é cortado em 25 caracteres (50 para o rótulo longo). id tem como padrão appmint-<index>. Uma rota sem / inicial ganha uma. O ícone é o ícone do app. Uma lista malformada é ignorada (registrada no log), nunca gera exceção. Apps criados com IA podem usar shortcuts de @/lib/appmintNative. Apps no modo site: um toque abre a rota no seu site — /new-note carrega https://<your site>/new-note — e getLaunchUrl() ainda retorna o link appmint-shortcut://, então uma página que faz o próprio roteamento continua funcionando.

Gerado a partir do runtime do app e de seus arquivos de exemplo a cada build da documentação. Leia em Markdown · Todas as famílias.

Conferido com a ponte atual em 22/10/2026.