In questo tutorial, partiremo da una nuova Angular app e passare al mondo delle app mobile native con Capacitor. Puoi anche aggiungere Capgo Native Navigation and Transitions per un feeling nativo e usare tailwind-capacitor per le safe areas.
Capacitor ti permette di convertire facilmente la tua web app Angular in un'app mobile nativa senza dover apportare modifiche sostanziali o imparare una nuova tecnologia come React Native.
Con pochi semplici passaggi, la maggior parte delle applicazioni Angular può essere trasformata in app mobile.
Questo tutorial ti guiderà nel processo, partendo da una nuova app Angular e integrando Capacitor per passare al mondo delle app mobile native. Puoi anche usare Capgo Native Navigation, Transitions e tailwind-capacitor per le safe areas.
Informazioni su Capacitor
CapacitorJS cambia le regole del gioco! Puoi integrarlo senza sforzo in qualsiasi progetto web: incapsulerà la tua applicazione in una webview nativa, generando per te i progetti Xcode e Android Studio. Inoltre, i suoi plugin danno accesso alle funzionalità native del dispositivo, come la fotocamera, tramite un bridge JS.
Con Capacitor, ottieni una fantastica app mobile nativa senza configurazioni complicate né curve di apprendimento ripide. Il suo API leggero e le funzionalità snelle lo rendono semplicissimo da integrare nel tuo progetto. Fidati, rimarrai stupito da quanto sia facile ottenere un'app nativa pienamente funzionante con Capacitor!
Preparazione della tua app Angular
Per creare una nuova app Angular, esegui il seguente comando:
ng new my-app
cd my-app
Quando richiesto la versione di Angular, seleziona “Angular”.
Per creare un'app mobile nativa, abbiamo bisogno di un export del nostro progetto. Quindi aggiungiamo uno script semplice nel nostro package.json che puoi usare per buildare e copiare il progetto Angular:
{
"scripts": {
// ...
"build": "ng build --prod"
}
}
Dopo aver eseguito il comando build, dovresti essere in grado di individuare un nuovo dist cartella nella root del progetto.
Questa cartella verrà usata da Capacitor in seguito, ma per ora dobbiamo configurarla correttamente.
Aggiungere Capacitor alla tua app Angular
Per impacchettare un'app web in un container mobile nativo, dobbiamo seguire alcuni passaggi iniziali, ma poi basterà eseguire un singolo sync comando.
Per prima cosa, possiamo installare Capacitor CLI come dev dependency e poi configurarlo nel progetto. Durante il setup, puoi premere “invio” per accettare i valori di default per name e bundle ID.
Successivamente, dobbiamo installare il pacchetto core e i pacchetti necessari per le piattaforme iOS e Android.
Infine, possiamo aggiungere le piattaforme e Capacitor creerà le cartelle per ogni piattaforma nella root del progetto:
# Install the Capacitor CLI locally
npm install -D @capacitor/cli
# Initialize Capacitor in your Angular project
npx cap init
# Install the required packages
npm install @capacitor/core @capacitor/ios @capacitor/android
# Add the native platforms
npx cap add ios
npx cap add android
A questo punto, dovresti già vedere le nuove iOS e Android cartelle nel tuo progetto Angular.
Sono veri progetti nativi!
Per accedere al progetto Android in seguito, devi installare Android Studio. Per iOS, ti serve un Mac e devi installare Xcode.
Inoltre, dovresti trovare un file capacitor.config.ts nel tuo progetto, che contiene alcune impostazioni fondamentali di Capacitor utilizzate durante la sync. L'unica cosa a cui prestare attenzione è webDir, che deve puntare al risultato del tuo comando di build. Attualmente, non è corretto.
Per risolvere, apri il file capacitor.config.json file e aggiornare il webDir:
{
"appId": "com.example.app",
"appName": "my-app",
"webDir": "dist"
}
Puoi provarlo eseguendo i seguenti comandi:
npm run build
npx cap sync
Il primo comando npm run build eseguirà semplicemente la build del tuo progetto Angular e copierà la build statica, mentre il secondo comando npx cap sync sincronizzerà tutti i code web nelle posizioni corrette delle piattaforme native, così da poterli visualizzare nell'app.
Inoltre, il comando sync potrebbe aggiornare le piattaforme native e installare i plugin, quindi quando installi un nuovo plugin Capacitor è il momento di eseguire npx cap sync ancora.
Senza accorgertene, hai finito: ora proviamo l'app su un dispositivo!
Build e deploy di app native
Per sviluppare app iOS, devi avere Xcode installato, mentre per le app Android devi avere Android Studio installati. Inoltre, se intendi distribuire la tua app sugli store, dovrai iscriverti all'Apple Developer Program per iOS e alla Google Play Console per Android.
Se sei alle prime armi con lo sviluppo mobile nativo, puoi usare Capacitor CLI per aprire facilmente entrambi i progetti nativi:
npx cap open ios
npx cap open android
Una volta configurati i tuoi progetti nativi, distribuire l'app su un dispositivo connesso è semplicissimo. In Android Studio, devi solo attendere che tutto sia pronto e puoi distribuire l'app su un dispositivo connesso senza modificare alcuna impostazione. Ecco un esempio:

In Xcode, devi configurare il tuo account di firma per distribuire l'app su un dispositivo reale invece che solo sul simulatore. Se non l'hai mai fatto, Xcode ti guida attraverso il processo (ma anche qui devi essere iscritto al Developer Program). Poi ti basta premere play per eseguire l'app sul dispositivo connesso, che puoi selezionare in alto. Ecco un esempio:

Congratulazioni! Hai distribuito con successo la tua web app Angular su un dispositivo mobile. Ecco un esempio:
Ma aspetta, c'è anche un modo più veloce per farlo durante lo sviluppo...
Capacitor Live Reload
A questo punto, probabilmente sei abituato all'hot reload con tutti i framework moderni, e la buona notizia è che puoi avere la stessa funzionalità su un dispositivo mobile con il minimo sforzo!
Abilita l'accesso alla tua applicazione ospitata localmente con il live reload sulla tua rete facendo caricare i contenuti all'app Capacitor tramite l'URL specifico.
Il primo passo è individuare il tuo indirizzo IP locale. Se usi un Mac, puoi trovarlo eseguendo questo comando nel terminale:
ipconfig getifaddr en0
Su Windows, esegui:
ipconfig
Poi cerca l'indirizzo IPv4.
Possiamo indicare a Capacitor di caricare l'app direttamente dal server aggiungendo un'altra voce al nostro capacitor.config.ts file:
import { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.example.app',
appName: 'my-app',
webDir: 'dist',
bundledWebRuntime: false,
server: {
url: 'http://192.168.x.xx:4200',
cleartext: true
}
};
export default config;
Assicurati di usare l'IP e la porta corretti, in questo esempio ho usato la porta predefinita di Angular.
Ora possiamo applicare queste modifiche copiandole nel nostro progetto nativo:
npx cap copy
Il copy il comando è simile a sync, ma copierà solo le modifiche apportate alla cartella web e alla configurazione, senza aggiornare il progetto nativo.
Ora puoi distribuire la tua app tramite Android Studio o Xcode. Successivamente, se modifichi qualcosa nella tua app Angular, l'app si ricaricherà automaticamente e mostrerà le modifiche!
Tieni presente che se installi nuovi plugin come la camera, è comunque necessario un rebuild del progetto nativo. Questo perché i file nativi vengono modificati e l'operazione non può avvenire on the fly.
Nota che dovresti usare l'IP e la porta corretti nella configurazione. Il blocco code sopra mostra la porta Angular predefinita a scopo dimostrativo.
Utilizzo dei plugin Capacitor
Vediamo come usare in pratica un plugin Capacitor, di cui abbiamo già parlato un paio di volte. Per farlo, possiamo installare un plugin abbastanza semplice eseguendo:
npm i @capacitor/share
Non c'è niente di speciale in Plugin di condivisione, ma apre comunque il dialog di condivisione nativo! Per farlo, ora basta importare il pacchetto e chiamare la relativa share() funzione dalla nostra app, quindi modifichiamo src/app/app.component.ts in questo modo:
import { Component } from '@angular/core';
import { Share } from '@capacitor/share';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'my-app';
async share() {
await Share.share({
title: 'Open Youtube',
text: 'Check new video on youtube',
url: 'https://www.youtube.com',
dialogTitle: 'Share with friends'
});
}
}
Come accennato prima, quando installi nuovi plugin devi eseguire un'operazione di sync e poi ridistribuire l'app sul dispositivo. Per farlo, esegui questo comando:
npx cap sync
Dopo aver cliccato il pulsante, potrai vedere il bellissimo dialog di condivisione nativo in azione!
Successivamente, puoi rendere l'app più nativa su iOS e Android con navigazione e transizioni Capgo, e risolvere i comuni problemi di layout su iOS che causano overflow orizzontale o safe area tagliate.
UI dall'aspetto nativo con Capgo Native Navigation and Transitions
Ho lavorato per anni con Ionic per buildare applicazioni cross-platform, ma integrarlo con Angular è un workaround e raramente ne vale la pena quando hai già Tailwind CSS.
Per un feeling mobile nativo in un'app Angular + Capacitor, usa i plugin Capgo invece di UI kit solo web come Konsta UI:
- @capgo/capacitor-native-navigation — navbar nativa, tab bar Liquid Glass su iOS e stile tab bar sfocata su Android. L'Angular router mantiene lo stato delle rotte; il plugin gestisce la UI nativa.
- @capgo/capacitor-transitions — transizioni di pagina in stile Ionic e swipe-back dal bordo su iOS nel layer WebView, senza adottare Ionic UI.
Installa entrambi:
bun add @capgo/capacitor-native-navigation @capgo/capacitor-transitions
bunx cap sync
Configura la navigazione nativa con la modalità CSS inset, così il contenuto web rispetta le barre native:
import { NativeNavigation } from '@capgo/capacitor-native-navigation';
await NativeNavigation.configure({
contentInsetMode: 'css',
animationDuration: 360,
glass: {
effect: 'liquidGlass',
},
});
Renderizza una tab bar Liquid Glass (iOS usa il rendering di sistema; Android usa un backdrop WebView sfocato):
import { inject } from '@angular/core';
import { Router } from '@angular/router';
const router = inject(Router);
await NativeNavigation.setTabbar({
selectedId: 'home',
labelVisibilityMode: 'labeled',
icons: true,
colors: { dynamic: true },
tabs: [
{ id: 'home', title: 'Home', icon: { svg: '...' } },
{ id: 'settings', title: 'Settings', icon: { svg: '...' } },
],
});
await NativeNavigation.addListener('tabSelect', ({ id }) => {
router.navigate([`/${id}`]);
});
Add native page transitions in your app shell:
```typescript
// app.component.ts
import { Component, CUSTOM_ELEMENTS_SCHEMA, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
import { Router } from '@angular/router';
import '@capgo/capacitor-transitions';
import { initTransitions, setDirection, setupRouterOutlet } from '@capgo/capacitor-transitions';
initTransitions({ platform: 'auto' });
@Component({
selector: 'app-root',
schemas: [CUSTOM_ELEMENTS_SCHEMA],
template: `
<cap-router-outlet #outlet platform="auto" swipe-gesture="auto">
<router-outlet></router-outlet>
</cap-router-outlet>
`,
})
export class AppComponent implements AfterViewInit {
@ViewChild('outlet') outlet?: ElementRef<HTMLElement>;
constructor(private router: Router) {}
ngAfterViewInit() {
if (this.outlet?.nativeElement) {
setupRouterOutlet(this.outlet.nativeElement, { platform: 'auto', swipeGesture: 'auto' });
}
}
openSettings() {
setDirection('forward');
this.router.navigate(['/settings']);
}
}
Avvolgi le pagine del router in cap-router-outlet, cap-page, e cap-content, e chiama setDirection('forward') o setDirection('back') prima di navigare. Non duplicare header o footer web se la navigazione nativa gestisce già quelle aree.
Guarda le guide complete: Usando @capgo/capacitor-native-navigation e Uso di @capgo/capacitor-transitions.
Safe areas con Tailwind
Per le safe area del dispositivo in Tailwind CSS, usa @capgo/tailwind-capacitor (pubblicato come tailwind-capacitor su npm). Fornisce safe-areas utility e altri plugin Tailwind compatibili con Capacitor:
bun add -D tailwind-capacitor
In src/styles.css:
@import 'tailwindcss';
@plugin "@capgo/tailwind-capacitor/platform";
@plugin "@capgo/tailwind-capacitor/safe-areas";
Usa utility come pt-safe, pb-safe, e px-safe invece di aggiungere manualmente env(safe-area-inset-*) a mano. Il progetto è in attivo sviluppo — se manca qualcosa per il tuo setup Angular, apri una PR su GitHub.
Risolvere problemi di layout su iOS (Viewport, Safe Area e overflow orizzontale)
Se i contenuti appaiono tagliati, spostati o con scroll orizzontale su iOS, aggiungere più overflow-x: hidden o modificare il tag viewport di solito non basta. Segui questi controlli in ordine.
Assicurati che il meta tag viewport sia applicato correttamente
In src/index.html, imposta il meta tag viewport in <head>:
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
Gestisci la safe area di iOS da un unico wrapper root
Crea un unico app shell e applica lì il padding per la safe area — non in più componenti annidati:
html,
body,
app-root {
width: 100%;
min-height: 100%;
margin: 0;
padding: 0;
overflow-x: hidden;
}
* {
box-sizing: border-box;
}
.app-shell {
min-height: 100dvh;
width: 100%;
padding-top: env(safe-area-inset-top);
padding-right: env(safe-area-inset-right);
padding-bottom: env(safe-area-inset-bottom);
padding-left: env(safe-area-inset-left);
}
Racchiudi tutto il contenuto della pagina in .app-shell. Il padding della safe-area duplicato in header, modal e wrapper del layout spesso fa apparire l'interfaccia tagliata o troppo grande.
Con @capgo/tailwind-capacitor, puoi applicare lo stesso padding con utility come pt-safe pb-safe px-safe su quella singola shell.
Imposta Capacitor iOS contentInset a never per primo
In capacitor.config.ts, preferisci disabilitare i native inset e lascia che il CSS (o quella contentInsetMode: 'css'di Native Navigation) gestisca la safe area:
const config: CapacitorConfig = {
appId: 'com.example.myapp',
appName: 'my-app',
webDir: 'www',
ios: {
contentInset: 'never',
},
};
Mescolare l'automatic content inset di Capacitor con il CSS env(safe-area-inset-*) il padding è una causa comune di spaziature doppie.
Trova il vero elemento che causa l'overflow
Il colpevole di solito è un elemento che usa 100vw, Tailwind w-screen, una larghezza fissa in pixel, o un grande min-width.
In Safari Web Inspector, esegui:
[...document.querySelectorAll('*')]
.filter(el => el.scrollWidth > document.documentElement.clientWidth)
.map(el => ({
el,
tag: el.tagName,
class: el.className,
scrollWidth: el.scrollWidth,
clientWidth: document.documentElement.clientWidth,
}));
Con Tailwind, sostituisci w-screen con w-full quando possibile. Molti problemi di overflow orizzontale derivano da 100vw / w-screen, padding della safe-area duplicato o un contenitore a larghezza fissa — non dal meta tag viewport stesso."
Conclusione
Capacitor è un'ottima opzione per creare applicazioni native partendo da un progetto web esistente, offrendo un modo semplice per condividere code e mantenere una UI coerente.
E con l'aggiunta di Capgo, è ancora più facile aggiungere live updates alla tua app, così i tuoi utenti hanno sempre accesso alle ultime funzionalità e ai bug fix.
Se vuoi scoprire come aggiungere Capgo alla tua app Angular, leggi il prossimo articolo:
Continua da Creare app mobile con Angular e Capacitor
Se stai usando Creare app mobile con Angular e Capacitor per pianificare il comportamento dei media nativi e dell'interfaccia, collegalo a Uso di @capgo/capacitor-live-activities per la funzionalità nativa nella pagina Uso di @capgo/capacitor-live-activities, @capgo/capacitor-live-activities per il dettaglio implementativo in @capgo/capacitor-live-activities, Uso di @capgo/capacitor-video-player per la funzionalità nativa in Utilizzo di @capgo/capacitor-video-player, @capgo/capacitor-video-player per i dettagli di implementazione in @capgo/capacitor-video-player, e Usando @capgo/capacitor-native-navigation per la funzionalità nativa in Usando @capgo/capacitor-native-navigation.