Claude Code
Écrit le hook de connexion, le wrapper fetch, chaque état de chargement, vide et d'erreur, l'error boundary, la page de repli et des tests Playwright qui simulent le hors ligne et les erreurs serveur, puis les exécute.
Claude Code + fiabilité
Un reviewer active le mode avion, touche un peu partout, puis le désactive. Si votre app affiche une page blanche, une erreur brute ou un spinner qui ne s'arrête jamais, c'est un refus pour la guideline 2.1 ou pour fonctionnalité défaillante. WebViewGold couvre les échecs de chargement de page avec un écran hors ligne natif ; tout ce qui se passe dans votre web app en cours d'exécution relève de votre code. Voici comment Claude Code construit cette partie, et comment la tester comme un reviewer.
Dès $109 en paiement unique par plateforme, ou notre équipe s'occupe de tout dès $698.
La coque. Quand la WebView ne parvient pas à charger une page, WebViewGold affiche son écran hors ligne natif au lieu d'une page d'erreur. Sur iOS, vous définissez ses textes avec offlinetitle, offlinemsg, screen1, screen2 et offlinebuttontext, et offlinescreenautoretry réessaie chaque seconde sans qu'il faille toucher l'écran. Sur Android, vous définissez l'arrière-plan avec OFFLINE_SCREEN_BACKGROUND_COLOR ; les textes de l'app se trouvent dans strings.xml. Pour aller plus loin, les deux plateformes peuvent afficher hors connexion une page HTML locale intégrée à l'app (offlinelocalhtmlswitch sur iOS, FALLBACK_USE_LOCAL_HTML_FOLDER_IF_OFFLINE sur Android), avec un bouton Réessayer qui appelle reconnect:// pour recharger la dernière URL chargée en ligne (API Reconnect).
Votre app. Une single-page app déjà lancée ne déclenche pas de chargement de page quand la connexion tombe. Ses requêtes fetch échouent dans la page, et seul votre code peut afficher quelque chose de sensé : un bandeau hors ligne, un état d'erreur avec Réessayer, un délai d'expiration au lieu d'un spinner sans fin. C'est de là que viennent la plupart des refus liés au hors ligne, et c'est la partie que Claude Code construit ci-dessous. Le hub du mode hors ligne compare les trois niveaux de prise en charge du hors ligne.
Les reviewers appliquent la guideline 2.1 (complétude de l'app : plantages, écrans cassés, contenu provisoire) et Google applique ses règles sur les fonctionnalités défaillantes. Aucun des deux n'attend que votre app fonctionne entièrement hors ligne ; tous deux attendent qu'elle dise ce qui se passe et qu'elle se rétablisse.
Écrit le hook de connexion, le wrapper fetch, chaque état de chargement, vide et d'erreur, l'error boundary, la page de repli et des tests Playwright qui simulent le hors ligne et les erreurs serveur, puis les exécute.
Définissez les textes et les couleurs de l'écran hors ligne natif, copiez la page de repli dans les deux projets WebViewGold, activez le repli si vous le souhaitez, et compilez une fois.
Mode avion au lancement et en cours de session, réseau lent et API en panne, sur de vrais appareils. C'est le seul test qui corresponde à ce que fait l'App Review.
| Situation | Géré par | Ce que l'utilisateur doit voir |
|---|---|---|
| Pas de connexion au démarrage de l'app | Écran hors ligne WebViewGold ou repli local | Votre message à vos couleurs et Réessayer |
| La connexion tombe pendant l'utilisation | Votre web app | Un bandeau hors ligne discret ; actions réseau désactivées ou mises en file d'attente |
| Réseau très lent | Votre web app | Des squelettes, puis un délai d'expiration avec Réessayer après 10 à 15 secondes environ |
| L'API renvoie une erreur 500 | Votre web app | Une phrase simple et Réessayer ; ni stack trace ni JSON |
| Session expirée | Votre web app | Retour à la connexion avec une courte explication, puis retour à la page d'origine |
| Route inconnue | Votre web app | Une page introuvable au style d'une app, avec un bouton Accueil |
| Maintenance planifiée | Votre web app | Une page de maintenance que vous pouvez activer sans déploiement |

Excellente façon de convertir son app web en app native ! Un délai très court, et un super moyen de mettre ses apps dans les stores sans devoir développer une app native complète !
Les tests Playwright du point 7 rendent tout cela reproductible : Claude Code les écrit, les exécute via son outil Bash et corrige ce qui échoue.
Les reviewers testent notre app en mode avion et sur de mauvais réseaux. L'app tourne dans des apps natives iOS et Android construites avec WebViewGold. Quand le chargement d'une page échoue, le wrapper affiche son écran hors ligne natif, mais une fois notre single-page app lancée, les fetch qui échouent et les changements de route ne sont gérés que par notre code. Rendez chaque échec visible et récupérable. 1. src/lib/use-online.ts : un hook basé sur les événements online et offline de window. Hors ligne, affichez un bandeau discret sous la safe area : Vous êtes hors ligne. Nous rechargerons vos données dès votre retour. Masquez-le une fois la connexion revenue et relancez les requêtes visibles. 2. src/lib/fetch-json.ts : un wrapper fetch unique avec un délai d'expiration de 12 secondes (AbortController), une NetworkError pour le hors ligne, les délais dépassés et les requêtes échouées, et une redirection vers /login?reason=expired en cas de 401, qui ramène au chemin d'origine après la connexion. Remplacez les appels fetch directs par ce wrapper. 3. Chaque écran qui charge des données reçoit un squelette de chargement, un état vide avec une action utile et un état d'erreur avec une phrase simple et un bouton Réessayer. Aucun message d'erreur brut, code de statut ou stack trace dans l'interface. 4. Les actions qui ont besoin du réseau sont désactivées hors ligne et affichent En attente de connexion, ou sont mises en file d'attente et envoyées au retour de la connexion. Ne perdez jamais ce que l'utilisateur a saisi. 5. Une error boundary à la racine avec un écran de repli convivial et un bouton Recharger, une page introuvable au style d'une app avec un bouton Accueil, et une page /maintenance que nous pouvons activer avec une variable d'environnement. 6. Aucun spinner ne doit tourner indéfiniment : chaque état de chargement se termine par du contenu, un état vide ou une erreur. 7. Des tests Playwright qui utilisent context.setOffline(true) pour vérifier le bandeau, l'état d'erreur avec Réessayer et le rétablissement après le retour en ligne, plus un test qui simule une réponse 500 de l'API. Exécutez-les et corrigez les échecs. 8. public/offline-fallback/index.html : une page autonome (CSS inline, sans polices, scripts ni images externes) aux couleurs de notre marque, avec un court message et un bouton Réessayer qui navigue vers reconnect://. Je la copierai dans les projets WebViewGold. Listez chaque écran modifié et tout ce que vous n'avez pas pu tester.
Assez court pour être relu d'une traite. Notez que navigator.onLine à true ne prouve pas qu'internet fonctionne (pensez au Wi-Fi d'un hôtel) : les requêtes échouées sont donc aussi traitées comme des erreurs réseau.
// src/lib/use-online.ts
import { useEffect, useState } from "react";
export function useOnline() {
const [online, setOnline] = useState(typeof navigator === "undefined" ? true : navigator.onLine);
useEffect(() => {
const up = () => setOnline(true);
const down = () => setOnline(false);
window.addEventListener("online", up);
window.addEventListener("offline", down);
return () => {
window.removeEventListener("online", up);
window.removeEventListener("offline", down);
};
}, []);
return online;
}
// src/lib/fetch-json.ts
export class NetworkError extends Error {}
export async function fetchJson<T>(url: string, init: RequestInit = {}, timeoutMs = 12000): Promise<T> {
if (typeof navigator !== "undefined" && !navigator.onLine) throw new NetworkError("offline");
const ctrl = new AbortController();
const timer = setTimeout(() => ctrl.abort(), timeoutMs);
try {
const res = await fetch(url, { ...init, signal: ctrl.signal });
if (res.status === 401) {
window.location.href = "/login?reason=expired&next=" + encodeURIComponent(location.pathname);
throw new Error("unauthorized");
}
if (!res.ok) throw new Error("HTTP " + res.status);
return (await res.json()) as T;
} catch (e) {
if (e instanceof DOMException && e.name === "AbortError") throw new NetworkError("timeout");
if (e instanceof TypeError) throw new NetworkError("network"); // la requête n'a jamais atteint le serveur
throw e;
} finally {
clearTimeout(timer);
}
}Tout est inline, car cette page s'affiche précisément quand rien ne peut être téléchargé. Copiez-la dans le dossier HTML local de chaque projet WebViewGold, comme le décrivent le guide de configuration iOS et le guide de configuration Android (option C).
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
<title>Offline</title>
<style>
body { margin: 0; min-height: 100vh; display: grid; place-items: center; padding: 24px;
box-sizing: border-box; text-align: center; background: #0f172a; color: #e2e8f0;
font-family: -apple-system, system-ui, sans-serif; }
h1 { font-size: 22px; margin: 0 0 8px; }
p { margin: 0; line-height: 1.5; color: #94a3b8; }
button { margin-top: 24px; min-height: 48px; padding: 0 28px; border: 0; border-radius: 12px;
background: #38bdf8; color: #0f172a; font-size: 17px; font-weight: 600; }
</style>
</head>
<body>
<main>
<h1>You are offline</h1>
<p>We will take you back to where you were as soon as the connection returns.</p>
<button type="button" onclick="window.location.href='reconnect://'">Try again</button>
</main>
</body>
</html>Dix minutes par projet, plus un build.
iOS : rédigez offlinetitle, offlinemsg, screen1, screen2 et offlinebuttontext avec le ton de votre app et réglez offlinescreenautoretry sur true. Android : définissez OFFLINE_SCREEN_BACKGROUND_COLOR et relisez la formulation hors ligne parmi les textes de l'app dans strings.xml.
Copiez la page ci-dessus dans le dossier HTML local et activez offlinelocalhtmlswitch (iOS) ou FALLBACK_USE_LOCAL_HTML_FOLDER_IF_OFFLINE (Android), en laissant uselocalhtmlfolder / USE_LOCAL_HTML_FOLDER sur false pour que l'URL distante reste la source principale.
Choisissez l'indicateur de chargement natif ou la barre de progression (useLoadingSign, useLoadingProgressBar, loadingIndicatorColor sur iOS ; ACTIVATE_PROGRESS_BAR sur Android). Pour les longues opérations serveur, votre app peut afficher le spinner natif avec spinneron:// et le masquer avec spinneroff://.
Relisez le diff, exécutez vous-même les tests Playwright une fois, déployez. La partie web arrive instantanément sur les installations existantes de l'app.
Les textes hors ligne et la page de repli font partie du build natif. Si vous voulez que notre équipe configure tout cela et compile les deux apps, le Full Service s'en charge.
autoRefreshEnabled / AUTO_REFRESH_ENABLED si vos données deviennent obsolètes, et vérifiez que cela n'efface pas les formulaires à moitié remplis).Non. Les reviewers attendent un message clair et un rétablissement qui fonctionne, pas des fonctionnalités hors ligne. Une utilisation entièrement hors ligne exige une version locale intégrée ou une app conçue pour les données hors ligne.
Parce que rien n'est en cours de chargement à ce moment-là. Une single-page app en cours d'exécution ne fait échouer que ses propres requêtes fetch : c'est donc à votre code d'afficher le bandeau et les états d'erreur.
Il recharge la dernière URL chargée avec succès avant que l'app ne bascule sur la page hors ligne. Si la connexion est toujours absente, la page de repli réapparaît.
Il peut simuler le hors ligne dans un navigateur avec Playwright (context.setOffline) et simuler des erreurs serveur, ce qui couvre votre code web. L'écran hors ligne natif et le comportement réel du réseau demandent toujours un test sur téléphone.
Sous la barre d'état et la safe area, au-dessus du contenu, sans jamais masquer les boutons principaux. Une fine barre en haut est la convention que les utilisateurs reconnaissent.
Même résultat, charge de travail différente de votre côté. Les trois formules incluent la garantie d'approbation et le support humain 24/7.
$109 par plateforme, paiement unique
La licence WebViewGold : un projet Xcode ou Android Studio prêt à l'emploi. Collez votre URL, définissez le nom et l'icône, activez les fonctionnalités, compilez et soumettez. Mises à jour gratuites à vie.
Voir les offres sur la page principale$349 par licence, extension en paiement unique
Ni Mac, ni Xcode, ni Android Studio : configurez dans le navigateur, nous compilons les deux apps dans le cloud et les transmettons à App Store Connect et à la Play Console.
Comment fonctionne le Cloud Builder Essayer la démo gratuite$698 par plateforme $798
Envoyez-nous votre URL et votre icône. Notre équipe configure, compile et livre votre app sous 72 heures, en marque blanche, projets sources inclus. Les deux plateformes pour $1,158.
Détails du Full Service Propulsé parPrix Soldes d'hiver valables jusqu'au 31 décembre 2026.
Garantie d'approbation App Store & Google Play – ou remboursement sous 14 jours
Vous préférez déléguer ? Full Service : nous configurons, compilons et livrons sous 72 heures, dès $698 par plateforme. Des questions ? Chattez avec nous 24/7.
Les remboursements sont accordés aux conditions indiquées dans notre FAQ : un refus non lié au contenu par Apple et/ou Google, demandé dans les 14 jours suivant l'achat.