Per pubblicare una web app su App Store e Google Play, avvolgi la tua web app compilata in un progetto nativo con Capacitor, aggiungi alcune funzionalità native, crea account per sviluppatori Apple e Google, firma e compila i binari iOS e Android, testali con utenti reali, prepara le schede store e inviali per la revisione. Il tuo HTML, CSS e JavaScript esistenti continua a girare all'interno di un WebView nativo, quindi non devi riscrivere l'app.
Di seguito trovi i 11 passaggi nell'ordine che evita attese, con i comandi per Capacitor 8 e le regole store applicabili nell'ottobre 2026.
Cosa ti serve
- Una web app che compila in file statici (React, Vue, Angular, Svelte, export statico di Next.js, generate di Nuxt, HTML puro, o un'app creata con un builder AI come Lovable o Bolt).
- Node.js 22 o successivo (requisito di Capacitor 8) e Bun o un altro package manager.
- Android Studio per le build Android.
- Xcode 26 su macOS per le build iOS, oppure un servizio di build cloud se non hai un Mac.
- 99 USD all'anno per Apple e 25 USD una tantum per Google.
Timeline realistica
| Fase | Tempo stimato | Si può eseguire in parallelo? |
|---|---|---|
| Iscrizione account sviluppatore | Ore (individuale) a 2 settimane (organizzazione con nuovo D-U-N-S) | Sì, inizia dal primo giorno |
| Setup Capacitor e prima esecuzione su dispositivo | 1 giorno | |
| Refinamento mobile e funzionalità native | Da 3 giorni a 3 settimane | |
| Firma e prime build | 1 giorno | |
| Test chiuso Google Play (nuovi account personali) | Minimo 14 giorni, poi revisione accesso alla produzione | Sì, tramite iOS TestFlight |
| Scheda dello store | 1-2 giorni | Sì |
| Revisione dell'app | Apple solitamente 1-2 giorni, Google da poche ore a diversi giorni |
Passaggio 1: inizia oggi l'iscrizione all'account sviluppatore
La verifica dell'account è il passaggio che non puoi accelerare, quindi fallo prima di scrivere codice.
- Apple Developer Program: 99 USD all'anno. Per i privati serve un Apple Account con autenticazione a due fattori e il nome legale. Le organizzazioni necessitano anche di un numero D-U-N-S, un sito web aziendale e un'email di lavoro su quel dominio.
- Google Play Console: 25 USD una tantum. Le organizzazioni necessitano di un numero D-U-N-S. È prevista la verifica dell'identità.
Se ti registri su Google Play come individuo, il tuo account è soggetto alla regola di test chiuso (Passo 9). Guida completa: come creare account developer Apple e Google Play.
Passo 2: Prepara l'app web per lo smartphone
Capacitor esegue la tua app in una WebView. Le cose che vanno bene in una scheda del browser sembrano sbagliate in un'app:
- Output di build statica. Capacitor carica i file dal bundle dell'app. Il server-side rendering non viene eseguito sullo smartphone. Usa l'output statico del tuo framework (
next buildconoutput: 'export',nuxt generate, Vitebuild). API chiama go verso il tuo backend tramite HTTPS come prima. - Routing client-side che funziona da un'origine file. Usa il routing history (Capacitor serve l'app da
https://localhostsu Android ecapacitor://localhoston iOS, so it works) and make sure deep URLs fall back toindex.html. - CORS. Aggiungi gli origin Capacitor agli origin consentiti del tuo API:
capacitor://localhost(iOS) ehttps://localhost(Android). - Touch, non hover. Remove hover-only menus. Make tap targets at least 44 x 44 points.
- Aree sicure. Aggiungi
viewport-fit=coveral meta tag viewport e aggiungi padding agli header e alle barre inferiori conenv(safe-area-inset-top)eenv(safe-area-inset-bottom). - Reti offline e lente. Mostra uno stato appropriato invece di uno schermo vuoto. I revisori testano su Wi-Fi instabili.
- Nessun banner “scarica la nostra app” e nessun link che invii gli utenti sul tuo sito web per svolgere le attività principali.
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
Passaggio 3: Aggiungi Capacitor
Dalla root del tuo progetto web:
bun add @capacitor/core
bun add -d @capacitor/cli
bunx cap init "My App" com.example.myapp --web-dir dist
bun add @capacitor/ios @capacitor/android
bun run build
bunx cap add ios
bunx cap add android
Usa la cartella di output reale per --web-dir: dist per Vite, out per l'export statico di Next.js, .output/public per Nuxt generate, build per Create React App, dist/<project>/browser per Angular.
Il bundle ID (com.example.myapp) è permanente una volta pubblicata l'app sugli store. Usa un reverse domain di tua proprietà.
Il tuo capacitor.config.ts ora è così:
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.example.myapp',
appName: 'My App',
webDir: 'dist',
};
export default config;
Capacitor 8 crea il progetto iOS con Swift Package Manager in modo predefinito, quindi non hai bisogno di CocoaPods. Ogni volta che modifichi il code web:
bun run build
bunx cap sync
Eseguilo:
bunx cap run ios
bunx cap run android
Fai il commit del ios/ e android/ cartelle. Sono il code sorgente che modificherai (permessi, icone, firma). Per ulteriori dettagli, consulta quanto è facile trasformare una web app in un'app mobile con Capacitor, e se hai sviluppato con uno strumento di AI, il nostro guida da Lovable al mobile.
Passaggio 4: Aggiungi feature native per giustificare l'app
La linea guida 4.2 di Apple (Funzionalità Minime) rifiuta le app che sono solo un sito web in una shell. Non servono decine di funzionalità native, ma l'app deve comportarsi come un'app. Aggiunte comuni e utili:
| Funzionalità | Plugin |
|---|---|
| Notifiche push | @capacitor/push-notifications |
| Accesso nativo con Google, Apple e Facebook | @capgo/capacitor-social-login |
| Sblocco con Face ID / impronta digitale | @capgo/capacitor-native-biometric |
| Fotocamera e foto | @capacitor/camera |
| Acquisti in-app e abbonamenti | @capgo/capacitor-native-purchases |
| Share sheet nativa | @capacitor/share |
| Feedback aptico | @capacitor/haptics |
| Status bar e splash screen | @capacitor/status-bar, @capacitor/splash-screen |
| Prompt per valutare l'app | @capgo/capacitor-in-app-review |
| Live Update | @capgo/capacitor-updater |
Esempio: mostra la share sheet nativa invece di un pulsante “copia link”.
import { Share } from '@capacitor/share';
import { Capacitor } from '@capacitor/core';
export async function shareLink(url: string, title: string) {
if (Capacitor.isNativePlatform()) {
await Share.share({ title, url });
} else {
await navigator.clipboard.writeText(url);
}
}
Se vendi contenuti digitali o abbonamenti, pianifica ora i pagamenti. Apple e Google nella maggior parte dei casi richiedono i loro sistemi di acquisti in-app per i beni digitali. Nell'App Store statunitense, dopo la sentenza del 2025 le app possono anche linkare a checkout web esterni; altre regioni hanno regole proprie. Per beni e servizi fisici (consegne, corse) puoi usare Stripe o qualsiasi provider di pagamento. Vedi acquisti in-app con Capacitor.
Il catalogo completo dei plugin Capgo è nella pagina dei plugin.
Passaggio 5: Icone, splash screen e stringhe dei permessi
Genera tutte le dimensioni di icone e splash screen da due immagini sorgente:
bun add -d @capacitor/assets
# assets/icon.png 1024x1024, assets/splash.png 2732x2732
bunx capacitor-assets generate
Su iOS, ogni permesso che usi richiede una usage description in ios/App/App/Info.plist, altrimenti l'app crasha durante la richiesta e Apple la rifiuta:
<key>NSCameraUsageDescription</key>
<string>Take a photo of your receipt to attach it to an expense.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Choose receipt photos from your library.</string>
Scrivi motivazioni specifiche. “Questa app ha bisogno della fotocamera” viene rifiutata.
Su Android, i plugin aggiungono la maggior parte dei permessi al manifest. Rimuovi quelli che non usi; Google ti chiede di giustificare quelli sensibili.
Aggiungi anche un Il privacy manifest (PrivacyInfo.xcprivacy) se il tuo code utilizza API con motivo obbligatorio. Consulta la guida al privacy manifest per app iOS.
Passaggio 6: Configura il signing
iOS. Ti serve un certificato Apple Distribution (con la sua chiave privata, di solito esportata come .p12) e un profilo di provisioning App Store Connect per il tuo bundle ID. Xcode può crearli automaticamente, oppure puoi crearli tu stesso, anche senza un Mac. Leggi Certificati iOS e provisioning profile spiegati; la Generatore di certificati iOS gestisce il passaggio CSR nel browser.
Android. Crea un keystore per l'upload e tienilo in backup. Google Play usa Play App Signing, quindi Google detiene la chiave di firma finale dell'app e tu firmi gli upload con la tua.
keytool -genkeypair -v -keystore upload-keystore.jks -alias upload \
-keyalg RSA -keysize 2048 -validity 10000
Oppure usa il Generatore di keystore per Android.
Passaggio 7: Genera i binari di release
In locale
iOS (su un Mac con Xcode 26, obbligatorio per gli upload su App Store da aprile 2026):
bunx cap open ios- Seleziona la target dell'app, imposta versione e numero di build, seleziona il tuo team in Signing & Capabilities.
- Usa Qualsiasi dispositivo iOS (arm64), poi Prodotto > Archivio.
- Nell'Organizer, Distribuisci App > App Store Connect > Upload.
Android:
bun run build
bunx cap sync android
cd android
./gradlew bundleRelease
L'AAB si trova in android/app/build/outputs/bundle/release/. Configura signingConfigs nella android/app/build.gradle con il tuo keystore, caricando le password dalle variabili d'ambiente.
Assicurati che targetSdkVersion sia 36. Dal 31 agosto 2026 Google Play richiede che le nuove app e gli aggiornamenti puntino ad Android 16 (API 36), che è il default di Capacitor 8.
Nel cloud
Se non hai un Mac o vuoi build riproducibili dalla CI, Build Capgo compila entrambe le piattaforme su macchine host e può caricare direttamente su TestFlight e Google Play:
bunx @capgo/cli@latest build credentials save --appId com.example.myapp --platform ios
bunx @capgo/cli@latest build credentials save --appId com.example.myapp --platform android
bunx @capgo/cli@latest build request com.example.myapp --platform ios --path .
bunx @capgo/cli@latest build request com.example.myapp --platform android --path .
Le credenziali vengono usate solo per la build e non vengono salvate sui server di Capgo. Vedi la Capgo Documentazione build.
Passaggio 8: Distribuisci ai tester
Metti la build su telefoni reali prima che chiunque in Apple o Google la veda.
- iOS: carica su TestFlight. I tester interni (fino a 100 membri del team) la ricevono subito dopo l'elaborazione; i tester esterni (fino a 10.000) dopo una breve Beta App Review.
- Android: crea una release di test interno in Play Console e condividi il link di opt-in.
Testa registrazione e login, pagamenti in sandbox, notifiche push, comportamento offline, la tastiera che copre gli input e il comportamento del pulsante indietro su Android. Dettagli per ogni opzione: come distribuire app iOS e Android ai tester.
Passaggio 9: Test chiuso di Google Play (nuovi account personali)
Se il tuo account Play è un account personale creato dopo il 13 novembre 2023, non puoi pubblicare in produzione finché non hai eseguito un test chiuso con almeno 12 tester iscritti per 14 giorni consecutivi. Poi richiedi l'accesso alla produzione nella dashboard di Play Console, che Google di solito revisiona entro una settimana.
Inizia non appena hai un build Android utilizzabile. Usa un Google Group come elenco tester in modo che le persone possano unirsi da sole. Pubblica aggiornamenti durante i 14 giorni e raccogli feedback, poiché Google chiede cosa hai imparato. Gli account organizzativi sono esenti.
Passaggio 10: Prepara le schede degli store e invia
Per entrambi gli store ti servono: nome app, descrizioni, screenshot nelle dimensioni accettate, icona, URL della privacy policy, disclosure sulla privacy (Apple App Privacy e Google Data safety), questionario sulla classificazione per età, contatto di supporto e un account demo se l'app ha un login. Google richiede anche una feature graphic di 1024 x 500. Specifiche e limiti: come preparare il tuo listing su App Store e Google Play.
Invio su iOS: in App Store Connect, crea la versione, seleziona il build di TestFlight, compila le Informazioni per la revisione dell'app (account demo, note) e clicca Aggiungi per la revisione, poi Invia.
Pubblicazione su Android: crea una release di produzione con l'AAB (o promuovi quella testata da un testing track), completa ogni Contenuti dell'app dichiarazione, imposta i paesi e invia in revisione.
I motivi di rifiuto più comuni per le web app:
- 4.2 Funzionalità minima: l'app è semplicemente il tuo sito web. Aggiungi valore nativo e rimuovi l'interfaccia tipica del browser.
- Login richiesto senza account demo, oppure l'account non funziona.
- Nessuna opzione di login rispettosa della privacy quando offri il login con Google o Facebook su iOS. La linea guida 4.8 richiede un'opzione equivalente che limiti la raccolta dati; Sign in with Apple è la scelta abituale.
- Impossibilità di eliminare l'account all'interno dell'app quando gli utenti possono creare account.
- Acquisti digitali tramite Stripe dove è richiesto l'in-app purchase.
- Layout iPad rotto perché il progetto supporta iPad in modo predefinito.
- Stringhe di autorizzazione mancanti o vaghe.
Il nostro guida alla prima revisione dell'app e Guida alla submission di app iOS esaminiamo ogni punto nel dettaglio.
Passaggio 11: Pubblica update senza attendere la review
Dopo il lancio, la maggior parte delle modifiche resterà nel web code. Invece di una nuova build per lo store per ogni fix, aggiungi live updates. L'updater Capgo scarica i nuovi web bundle da Capgo e li applica al prossimo avvio, con rollback automatico se il nuovo bundle non riesce a partire.
bun add @capgo/capacitor-updater
bunx cap sync
bunx @capgo/cli@latest init
Chiama notifyAppReady() quando la tua app è avviata, in modo che l'updater sappia che il bundle è sano:
import { CapacitorUpdater } from '@capgo/capacitor-updater';
CapacitorUpdater.notifyAppReady();
Poi ogni release del web code è un solo comando:
bun run build
bunx @capgo/cli@latest bundle upload --channel production
Entrambi gli store lo consentono per il code interpretato, purché l'aggiornamento non cambi lo scopo principale dell'app o aggiri le loro regole di pagamento. Le modifiche native (nuovi plugin, nuove permission, upgrade di Capacitor) passano ancora dagli store. Leggi di più su Live updates di Capgo e il documentazione dell'updater.
Aggiungi il plugin prima della tua prima submission allo store. Deve essere presente nel binary che gli utenti installano, altrimenti il tuo primo live update raggiungerà gli utenti solo dopo una seconda release dello store.
Infine, automatizza: build e upload a ogni tag da GitHub Actions o GitLab CI, pubblica live update a ogni merge su main, e mantieni le release native per le modifiche native.
Checklist pre-lancio
- Account Apple e Google approvati, accordi accettati
- L'app funziona offline o mostra uno stato offline chiaro
- Gestiti safe areas, tastiera e tasto back di Android
- Almeno alcune feature native che un sito web non può offrire
- Icone, splash, stringhe permessi e privacy manifest
- Certificato di distribuzione, profilo App Store, backup dell'upload keystore
- Target SDK 36 su Android, build con Xcode 26 su iOS
- TestFlight e test interno Play eseguiti su dispositivi reali
- Closed test di Google Play completato (account personali)
- Listing completi su entrambi gli store, account demo aggiunto
- Eliminazione account in-app se gli utenti possono registrarsi
- Plugin Live Updates incluso nel primo binario
Risoluzione problemi
Schermo bianco all'avvio. webDir punta alla cartella sbagliata o hai dimenticato bunx cap sync dopo la build. Controlla ios/App/App/public e android/app/src/main/assets/public contengono index.html.
Le chiamate API falliscono solo nell'app. CORS: consenti capacitor://localhost e https://localhost. Controlla anche di non chiamare http:// URL che iOS blocca di default.
Route 404 dopo refresh o deep link. Usa un router che fa fallback su index.html, or hash routing for older setups.
Errori di firma in Xcode. Consulta l'elenco degli errori in Certificati iOS e provisioning profile spiegati.
Il build Gradle fallisce dopo l'aggiornamento. Capacitor 8 richiede Android Studio Otter (2025.2.1) o versioni successive e JDK 21, come indicato nel guida all'aggiornamento a Capacitor 8. Per altri errori Gradle, consulta come risolvere gli errori di build Android in Capacitor.
Upload su Google Play rifiutato per il target SDK. Imposta targetSdkVersion = 36 nella android/variables.gradle.