PWAs wie eine App gestalten

Ihre progressive Web-App sollte nicht wie eine Website, sondern wie eine „echte“ App wirken

Wenn Sie Bingo für progressive Web-Apps spielen, sollten Sie sich sicher sein, dass PWAs nur Websites sind. Die PWA-Dokumentation von Microsoft stimmt zu, wir sagen es genau auf dieser Website. Und sogar die PWA-Nominierer Frances Berriman und Alex Russell schreiben das. Ja, PWAs sind einfach nur Websites, aber sie sind auch viel mehr. Bei richtiger Anwendung wirkt eine PWA nicht wie eine Website, sondern wie eine „echte“ App. Was bedeutet es nun, sich wie eine echte App anfühlen?

Zur Beantwortung dieser Frage verwende ich als Beispiel die App Podcasts von Apple. Sie ist unter macOS auf Computern bzw. unter iOS (bzw. iPadOS) auf Mobilgeräten verfügbar. Podcasts ist zwar eine Medien-App, aber die Kernideen, die ich anhand seiner Hilfe zeige, lassen sich auch auf andere App-Kategorien anwenden.

Ein iPhone und ein MacBook, auf denen jeweils die Podcasts App ausgeführt wird
Apple Podcasts auf dem iPhone und unter macOS (Quelle).

Offlineausführung möglich

Wenn Sie einmal einen Schritt zurücktreten und an die plattformspezifischen Anwendungen auf Ihrem Mobiltelefon oder Desktop-Computer denken, fällt eines klar auf: Sie bekommen nie nichts. In der Podcasts App ist immer etwas verfügbar, auch wenn ich offline bin. Auch wenn keine Netzwerkverbindung besteht, wird die App automatisch geöffnet. Im Bereich Top-Charts werden keine Inhalte angezeigt, sondern stattdessen die Meldung Verbindung nicht möglich zusammen mit der Schaltfläche Wiederholen angezeigt. Vielleicht nicht so sympathisch, aber ich finde etwas.

In der Podcasts-App wird die Informationsmeldung „Verbindung nicht möglich“ angezeigt, wenn keine Netzwerkverbindung verfügbar ist.
Podcasts-App ohne Netzwerkverbindung.
Vorgehensweise im Web

Die Podcasts-App folgt dem sogenannten App-Shell-Modell. Alle statischen Inhalte, die zum Anzeigen der Haupt-App erforderlich sind, werden lokal im Cache gespeichert, einschließlich dekorativer Bilder wie der Menüsymbole auf der linken Seite und der Symbole der Haupt-Player-Benutzeroberfläche. Dynamische Inhalte wie Daten aus den Top-Charts werden nur bei Bedarf geladen. Falls beim Laden ein Fehler auftritt, sind Fallback-Inhalte im lokalen Cache verfügbar. Im Artikel App Shell-Modell erfahren Sie, wie Sie dieses Architekturmodell auf Ihre Webanwendung anwenden.

Offline-Inhalte verfügbar und Medien können abgespielt werden

Während ich offline bin, kann ich über die linke Leiste weiterhin zum Abschnitt Heruntergeladen gehen und heruntergeladene Podcastfolgen abspielen, die zur Wiedergabe bereit sind und mit allen Metadaten wie Artwork und Beschreibungen angezeigt werden.

Podcasts-App mit einer heruntergeladenen Folge eines Podcasts, die wiedergegeben wird.
Heruntergeladene Podcastfolgen können auch ohne Netz wiedergegeben werden.
Vorgehensweise im Web

Zuvor heruntergeladene Medieninhalte können aus dem Cache bereitgestellt werden, z. B. mit dem Rezept Im Cache gespeicherte Audio- und Videodaten bereitstellen aus der Workbox-Bibliothek. Andere Inhalte können immer im Cache oder in IndexedDB gespeichert werden. Im Artikel Speicher für das Web finden Sie alle Einzelheiten und erfahren, wann Sie welche Speichertechnologie verwenden sollten. Wenn Sie Daten haben, die dauerhaft gespeichert werden sollen, ohne dass das Risiko besteht, dauerhaft gelöscht zu werden, wenn nur noch wenig Arbeitsspeicher verfügbar ist, können Sie die Persistent Storage API verwenden.

Proaktives Herunterladen im Hintergrund

Wenn ich wieder online bin, kann ich natürlich mit einer Suchanfrage wie http 203 nach Inhalten suchen. Wenn ich das Suchergebnis, den HTTP 203-Podcast, abonnieren möchte, wird die neueste Folge der Serie sofort heruntergeladen und es werden keine Fragen gestellt.

Mit der Podcasts-App wird die neueste Folge eines Podcasts sofort nach dem Abonnieren heruntergeladen.
Nachdem du einen Podcast abonniert hast, wird die neueste Folge sofort heruntergeladen.
Vorgehensweise im Web

Das Herunterladen einer Podcastfolge kann länger dauern. Mit der Background Fetch API können Sie Downloads an den Browser delegieren, der sie dann im Hintergrund abarbeitet. Unter Android wiederum kann der Browser diese Downloads sogar weiter an das Betriebssystem delegieren, sodass der Browser nicht ständig ausgeführt werden muss. Sobald der Download abgeschlossen ist, wird der Service Worker Ihrer App geweckt und Sie können entscheiden, was mit der Antwort geschehen soll.

Freigabe für andere Anwendungen und Interaktion mit anderen Anwendungen

Die Podcasts App lässt sich ganz einfach in andere Apps integrieren. Wenn ich beispielsweise mit der rechten Maustaste auf eine Folge klicke, die mir gefällt, kann ich sie mit anderen Apps auf meinem Gerät teilen, z. B. mit der Messages App. Sie ist auch in die Systemzwischenablage integriert. Ich kann mit der rechten Maustaste auf eine Folge klicken und einen Link dazu kopieren.

Das Kontextmenü der Podcasts-App, das bei einer Podcastfolge aufgerufen wird und die Option „Folge teilen → Nachrichten“ ausgewählt ist
Podcast-Folge in der Messages App teilen.
Vorgehensweise im Web

Mit der Web Share API und der Web Share Target API kann deine App Texte, Dateien und Links mit anderen Anwendungen auf dem Gerät teilen und von ihnen empfangen. Obwohl es noch nicht möglich ist, dass eine Webanwendung Menüelemente zum integrierten Rechtsklickmenü des Betriebssystems hinzufügt, gibt es viele andere Möglichkeiten, eine Verknüpfung zu und von anderen Apps auf dem Gerät herzustellen. Mit der Async Clipboard API kannst du programmatisch Text- und Bilddaten (PNG-Bilder) lesen und in die Systemzwischenablage schreiben. Unter Android können Sie die Contact Picker API verwenden, um Einträge aus dem Kontaktmanager des Geräts auszuwählen. Wenn du sowohl eine plattformspezifische App als auch eine PWA anbietest, kannst du mit der Get Install Related Apps API prüfen, ob die plattformspezifische App installiert ist. In diesem Fall musst du Nutzer nicht dazu ermutigen, die PWA zu installieren oder Web-Push-Benachrichtigungen zu akzeptieren.

Aktualisierung der App im Hintergrund

In den Einstellungen der Podcasts App kann ich die App so konfigurieren, dass neue Folgen automatisch heruntergeladen werden. So muss ich nicht einmal darüber nachdenken, aktualisierte Inhalte werden immer da sein. Magie.

Im Einstellungsmenü der Podcasts-App im Abschnitt „Allgemein“, in dem für „Podcasts aktualisieren“ die Option „Jede Stunde“ ausgewählt ist
Podcasts, die so konfiguriert sind, dass stündlich nach neuen Podcastfolgen gesucht wird.
Vorgehensweise im Web

Mit der Periodic Background Sync API kann der Inhalt Ihrer App regelmäßig im Hintergrund aktualisiert werden, ohne dass sie ausgeführt werden muss. Das bedeutet, dass neue Inhalte proaktiv verfügbar sind und Ihre Nutzer sich jederzeit damit vertraut machen können.

Status über die Cloud synchronisiert

Gleichzeitig werden meine Abos auf allen Geräten synchronisiert, die ich besitze. In einer nahtlosen Welt muss ich meine Podcast-Abos nicht manuell synchronisieren. Außerdem muss ich keine Angst haben, dass der Arbeitsspeicher meines Mobilgeräts durch Folgen belegt wird, die ich mir bereits auf meinem Computer angehört habe. Der Wiedergabestatus wird synchronisiert und die angehörten Folgen werden automatisch gelöscht.

Im Menü „Erweitert“ der Podcasts-App ist die Option „Abos geräteübergreifend synchronisieren“ aktiviert.
Der Status wird über die Cloud synchronisiert.
Vorgehensweise im Web

Die Synchronisierung der App-Statusdaten ist eine Aufgabe, die Sie an die Background Sync API delegieren können. Die Synchronisierung selbst muss nicht sofort, sondern nur letztendlich und möglicherweise auch dann erfolgen, wenn der Nutzer die App bereits wieder geschlossen hat.

Steuerung der Hardware-Medientaste

Wenn ich gerade mit einer anderen App beschäftigt bin, z. B. beim Lesen einer Nachrichtenseite im Chrome-Browser, kann ich die Podcasts App weiterhin mit den Medientasten auf meinem Laptop steuern. Du musst nicht mehr zur App wechseln, um vor- oder zurückzugehen.

Apple MacBook Pro Magic Keyboard mit Medientasten mit Anmerkungen
Über die Medientasten kann die Podcasts-App (Quelle) gesteuert werden.
Vorgehensweise im Web

Medienschlüssel werden von der Media Session API unterstützt. So können Nutzer die Hardware-Medientasten ihrer physischen Tastaturen oder Kopfhörer verwenden oder sogar die Web-App über die Software-Medientasten auf ihrer Smartwatch steuern. Eine weitere Idee für sanfte Suchvorgänge besteht darin, ein Vibrationsmuster zu senden, wenn der Nutzer einen erheblichen Teil des Inhalts durchläuft, z. B. den Vorspann oder eine Kapitelgrenze.

Multitasking und App-Verknüpfung

Natürlich kann ich auch von überall aus zur Podcasts App zurückwechseln. Die App hat ein deutlich unterscheidbares Symbol, das ich auch auf meinem Desktop oder meinem App-Dock platzieren kann, sodass Podcasts sofort gestartet werden können, wenn es mir gefällt.

Der Task-Wechsler unter macOS mit einer Reihe von App-Symbolen, darunter eines der Podcasts-App.
Multitasking zurück zur Podcasts-App
Vorgehensweise im Web

Progressive Web-Apps können sowohl auf dem Desktop als auch auf Mobilgeräten auf dem Startbildschirm, im Startmenü oder auf dem Anwendungsdock installiert werden. Die Installation kann auf Grundlage einer proaktiven Aufforderung erfolgen oder vollständig vom App-Entwickler gesteuert werden. Im Artikel Was muss ich tun, um installierbar zu sein? erfahren Sie alles, was Sie wissen müssen. Beim Multitasking werden PWAs unabhängig vom Browser angezeigt.

Schnellaktionen im Kontextmenü

Die häufigsten App-Aktionen, Nach neuen Inhalten suchen und Nach neuen Folgen suchen, sind direkt über das Kontextmenü der App im Dock verfügbar. Über das Menü Optionen kann ich auch festlegen, dass die App bei der Anmeldung geöffnet wird.

Kontextmenü für Symbol der Podcasts-App mit den Optionen „Suche“ und „Nach neuen Folgen suchen“.
Schnellaktionen sind sofort über das App-Symbol verfügbar.
Vorgehensweise im Web

Durch Angabe von Verknüpfungen für App-Symbole im Web-App-Manifest der PWA können Sie Schnellrouten zu gängigen Aufgaben registrieren, auf die Nutzer direkt über das App-Symbol zugreifen können. Unter Betriebssystemen wie macOS können Nutzer auch mit der rechten Maustaste auf das App-Symbol klicken und festlegen, dass die App bei der Anmeldung gestartet wird. Es wird derzeit an einem Vorschlag für die Ausführung bei der Anmeldung gearbeitet.

Als Standard-App fungieren

Mithilfe des URL-Schemas podcasts:// können andere iOS-Apps und sogar Websites oder E-Mails in die Podcasts-App integriert werden. Wenn ich im Browser einem Link wie podcasts://podcasts.apple.com/podcast/the-css-podcast/id1042283903 folge, werde ich direkt zur Podcasts App weitergeleitet und kann entscheiden, ob ich den Podcast abonnieren oder anhören möchte.

Im Chrome-Browser wird ein Bestätigungsdialogfeld angezeigt, in dem der Nutzer gefragt wird, ob er die Podcasts App öffnen möchte.
Die Podcasts App kann direkt über den Browser geöffnet werden.
Vorgehensweise im Web

Vollständig benutzerdefinierte URL-Schemas können noch nicht vollständig benutzerdefinierte URL-Schemas verarbeitet werden. Wir arbeiten jedoch an einem Vorschlag zur URL-Protokollbehandlung für PWAs. Derzeit ist registerProtocolHandler() mit dem Schemapräfix web+ die beste Alternative.

Integration des lokalen Dateisystems

Sie denken vielleicht nicht sofort darüber nach, aber die Podcasts-App integriert sich von Natur aus in das lokale Dateisystem. Wenn ich eine Podcastfolge herunterlade, wird sie auf meinem Laptop in ~/Library/Group Containers/243LU875E5.groups.com.apple.podcasts/Library/Cache gespeichert. Im Gegensatz zu ~/Documents ist dieses Verzeichnis natürlich nicht für den direkten Zugriff von regulären Nutzern gedacht, aber es ist vorhanden. Im Abschnitt Offlineinhalte wird auf andere Speichermechanismen als Dateien verwiesen.

Über den macOS Finder wurde das Systemverzeichnis der Podcasts-App aufgerufen.
Podcastfolgen werden in einem speziellen System-App-Ordner gespeichert.
Vorgehensweise im Web

Mit der File System Access API erhalten Entwickler Zugriff auf das lokale Dateisystem des Geräts. Sie können es direkt oder über die Supportbibliothek browser-fs-access verwenden, die transparent einen Fallback für Browser bietet, die die API nicht unterstützen. Aus Sicherheitsgründen sind Systemverzeichnisse nicht über das Web zugänglich.

Plattform-Design

Es gibt noch eine feinere Sache, die für eine iOS-App wie Podcasts selbstverständlich ist: Keines der Textlabels kann ausgewählt werden und der gesamte Text fügt sich in die Systemschrift des Geräts ein. Außerdem wird die von mir gewählte Systemfarbauswahl (dunkler Modus) berücksichtigt.

Die Podcasts App im dunklen Modus
Die Podcasts App unterstützt den hellen und den dunklen Modus.
Die Podcasts App im hellen Modus.
Die App verwendet die Standardsystemschriftart.
Vorgehensweise im Web

Wenn Sie die CSS-Eigenschaft user-select mit dem Wert none verwenden, können Sie verhindern, dass UI-Elemente versehentlich ausgewählt werden. Sie dürfen diese Property jedoch nicht missbrauchen, um die Auswahl von App-Inhalten zu verhindern. Er sollte nur für UI-Elemente wie Schaltflächentexte usw. verwendet werden. Mit dem Wert system-ui für die CSS-Eigenschaft font-family kannst du die Standard-UI-Schriftart des Systems angeben, das für deine App verwendet werden soll. Außerdem kann deine App dem Farbschema des Nutzers entsprechen, indem es seine prefers-color-scheme-Einstellung berücksichtigt und diese mit einer optionalen Ein-/Aus-Schaltfläche für den dunklen Modus überschrieben wird. Außerdem sollten Sie sich darüber entscheiden, wie der Browser vorgehen soll, wenn er die Grenze eines Scrollbereichs erreicht, z. B. um ein benutzerdefiniertes Pull zum Aktualisieren zu implementieren. Das ist mit der CSS-Eigenschaft overscroll-behavior möglich.

Angepasste Titelleiste

Wenn Sie sich das Fenster der Podcasts-App ansehen, stellen Sie fest, dass es keine klassische integrierte Titelleiste und Symbolleiste wie das Safari-Browserfenster hat, sondern eine benutzerdefinierte Ansicht, die wie eine Seitenleiste aussieht, die an das Hauptfenster des Players angedockt ist.

Die integrierte Kachelleiste und Symbolleiste des Safari-Browsers
Die benutzerdefinierte, aufgeteilte Titelleiste der Podcasts-App
Benutzerdefinierte Titelleisten von Safari und Podcasts.
Vorgehensweise im Web

Die Anpassung der Titelleiste ist derzeit nicht möglich. Sie können und sollten jedoch die Attribute display und theme-color des Web-App-Manifests angeben, um das Design Ihres Anwendungsfensters zu bestimmen und festzulegen, welche Standard-Browsersteuerelemente – möglicherweise keines von ihnen – angezeigt werden sollen.

Knackige Animationen

In-App-Animationen in Podcasts sind schnell und flüssig. Wenn ich beispielsweise rechts die Leiste mit den Notizen zu Folgen öffne, wird sie elegant angezeigt. Wenn ich eine Folge aus meinen Downloads entferne, bleiben die restlichen Folgen erhalten und verbrauchen Platz auf dem Bildschirm, der durch die gelöschte Folge freigegeben wurde.

In der Podcasts-App ist die Leiste „Notizen zu Folgen“ maximiert.
In-App-Animationen wie beim Öffnen einer Leiste sind knackig.
Vorgehensweise im Web

Effektive Animationen im Web sind mitunter möglich, wenn Sie eine Reihe von Best Practices berücksichtigen, die im Artikel Animationen und Leistung beschrieben werden. Scroll-Animationen, wie sie häufig in paginierten Inhalten oder Medienkarussells zu sehen sind, können mit der Funktion CSS Scroll Snap erheblich verbessert werden. Die vollständige Kontrolle erhalten Sie mit der Web Animations API.

Inhalte außerhalb der App

Die Podcasts-App für iOS kann Inhalte auch an anderen Orten als in der eigentlichen App anzeigen, z. B. in der Widget-Ansicht des Systems oder in Form eines Siri-Vorschlags. Proaktive, nutzungsbasierte Calls-to-Action, die nur ein Tippen zum Interagieren erfordern, können die Re-Engagement-Rate einer App wie Podcasts erheblich steigern.

iOS-Widget-Ansicht, in der die Podcasts-App eine neue Folge eines Podcasts vorschlägt.
App-Inhalte werden außerhalb der Podcast-Haupt-App angezeigt.
Vorgehensweise im Web

Mit der Content Index API kann Ihre Anwendung dem Browser mitteilen, welche Inhalte der PWA offline verfügbar sind. Dadurch kann der Browser diese Inhalte außerhalb der Haupt-App anzeigen. Wenn du interessante Inhalte in deiner App als für die speakable-Audiowiedergabe geeignet auszeichnest und strukturiertes Markup im Allgemeinen verwendest, kannst du Suchmaschinen und virtuellen Assistenten wie Google Assistant dabei unterstützen, deine Angebote in ein optimales Licht zu bringen.

Widget für die Mediensteuerung auf dem Sperrbildschirm

Wenn eine Podcastfolge abgespielt wird, zeigt die Podcasts-App auf dem Sperrbildschirm ein Widget mit Metadaten wie dem Artwork der Folge, dem Titel der Folge und dem Namen des Podcasts an.

iOS-Widget für die Medienwiedergabe auf dem Sperrbildschirm, das eine Podcastfolge mit umfangreichen Metadaten zeigt.
Die Wiedergabe von Medien in der App kann über den Sperrbildschirm gesteuert werden.
Vorgehensweise im Web

Mit der Media Session API kannst du Metadaten wie Artwork, Titel usw. angeben, die dann auf dem Sperrbildschirm, auf einer Smartwatch oder in anderen Medien-Widgets im Browser angezeigt werden.

Push-Benachrichtigungen.

Push-Benachrichtigungen sind im Web etwas lästig, auch wenn Benachrichtigungsaufforderungen jetzt viel leiser sind. Wenn sie aber richtig eingesetzt werden, können sie einen großen Mehrwert bieten. Beispielsweise kann die iOS Podcasts App mich optional über neue Folgen von Podcasts benachrichtigen, die ich abonniert habe, oder neue Empfehlungen sowie Benachrichtigungen über neue App-Funktionen.

In der iOS Podcasts App ist auf dem Bildschirm „Benachrichtigungseinstellungen“ die Ein/Aus-Schaltfläche „Neue Folgen“ aktiviert.
Apps können Push-Benachrichtigungen senden, um Nutzer über neue Inhalte zu informieren.
Vorgehensweise im Web

Mit der Push API kann deine App Push-Benachrichtigungen erhalten, sodass du deine Nutzer über wichtige Ereignisse im Zusammenhang mit deiner PWA informieren kannst. Für Benachrichtigungen, die zu einem bekannten Zeitpunkt in der Zukunft ausgelöst werden sollen und keine Netzwerkverbindung erforderlich sind, können Sie die Notification Triggers API verwenden.

Kennzeichen für App-Symbole

Immer wenn neue Folgen für einen der Podcasts verfügbar sind, die ich abonniert habe, erscheint auf dem Startbildschirm von Podcasts ein App-Symbolsymbol. Damit ermutigt mich das auch, die App auf eine nicht aufdringliche Weise noch einmal zu verwenden.

iOS-Einstellungsbildschirm, auf dem die Option „Kennzeichen“ aktiviert ist
Badges sind eine gute Möglichkeit für Anträge, Nutzer über neue Inhalte zu informieren.
Vorgehensweise im Web

Mit der Badging API können Sie Badges für App-Symbole einrichten. Das ist besonders nützlich, wenn deine PWA „ungelesene“ Elemente drückt oder du eine Möglichkeit benötigst, die Aufmerksamkeit des Nutzers unauffällig wieder auf die App zu lenken.

Die Medienwiedergabe hat Vorrang vor den Einstellungen für den Energiesparmodus

Wenn Podcast-Medien abgespielt werden, wird der Bildschirm möglicherweise ausgeschaltet, das System wechselt jedoch nicht in den Stand-by-Modus. Apps können optional auch den Bildschirm aktiviert lassen, zum Beispiel, um Songtexte oder Untertitel anzuzeigen.

macOS-Einstellungen im Abschnitt „Energiesparmodus“.
Apps können den Bildschirm aktiv lassen.
Vorgehensweise im Web

Mit der Screen Wake Lock API kannst du verhindern, dass sich der Bildschirm ausschaltet. Die Medienwiedergabe im Web verhindert automatisch, dass das System in den Standby-Modus wechselt.

App-Sichtbarkeit über einen App-Shop

Die Podcasts App ist Teil der macOS-Desktop-App, auf iOS-Geräten muss sie jedoch über den App Store installiert werden. Durch eine kurze Suche nach podcast, podcasts oder apple podcasts wird die App sofort im App Store freigeschaltet.

Wenn du im iOS App Store nach „Podcasts“ suchst, wird die Podcasts-App angezeigt.
Nutzer haben gelernt, Apps in App-Shops zu entdecken.
Vorgehensweise im Web

Bei Apple sind PWAs im App Store nicht zulässig. Auf Android kannst du sie aber in einer vertrauenswürdigen Webaktivität einreichen. Mit dem Skript bubblewrap ist dies ein unkomplizierter Vorgang. Dieses Skript ist auch die Grundlage für die interne Funktion von PWABuilder zum Exportieren von Android-Apps, die Sie verwenden können, ohne die Befehlszeile zu berühren.

Featurezusammenfassung

Die folgende Tabelle bietet einen kompakten Überblick über alle Funktionen sowie eine Liste nützlicher Ressourcen für ihre Verwendung im Web.

Funktion Nützliche Ressourcen hierfür im Web
Offline ausgeführt
Offlineinhalte verfügbar und Medien abspielbar
Proaktiver Download im Hintergrund
Daten für andere Anwendungen freigeben und mit ihnen interagieren
Aktualisierung von Apps im Hintergrund
Über die Cloud synchronisierte Status
Steuerung der Hardware-Medientaste
Multitasking und App-Verknüpfung
Schnellaktionen im Kontextmenü
Als Standard-App fungieren
Integration lokaler Dateisysteme
Plattform-Design
Angepasste Titelleiste
Beeindruckende Animationen
Inhalte außerhalb der App
Widget für die Mediensteuerung auf dem Sperrbildschirm
Push-Benachrichtigungen
Kennzeichen für App-Symbole
Medienwiedergabe hat Vorrang vor Energiesparmodus-Einstellungen
Auffindbarkeit von Apps über einen App-Shop

Fazit

Seit ihrer Einführung im Jahr 2015 hat sich die Entwicklung von PWAs stark verändert. Im Rahmen des Project Fugu 🐡 arbeitet das unternehmensübergreifende Chromium-Team daran, die letzten Lücken zu schließen. Wenn Sie nur einige der Ratschläge in diesem Artikel befolgen, können Sie Stück für Stück dem App-ähnlichen Gefühl näher kommen und Ihre Nutzer vergessen, dass es sich nur um eine Website handelt. Den meisten von ihnen ist es egal, wie Ihre App aufgebaut ist (und warum sie?), solange sie sich wie eine echte App anfühlt.

Danksagungen

Dieser Artikel wurde von Kayce Basques, Joe Medley, Joshua Bell, Dion Almaer, Ade Oshineye, Pete LePage, Sam Thorogood, Reilly Yaskin und Reilly Yaskin