Niech Twoja PWA przypomina aplikację

Zaprojektuj progresywną aplikację internetową, która nie przypomina witryny, ale jak „prawdziwa”

Gdy grasz w progresywne bingo z progresywną aplikacją internetową, możesz śmiało powiedzieć, że „PWA to tylko witryny”. Dokumentacja programu PWA firmy Microsoft zgadza się, informujemy o tym na tej samej stronie. Według nominacji do PWA również Frances Berriman i Alex Russell. Tak. PWA to tylko witryny, ale to coś więcej. Prawidłowa aplikacja PWA będzie wyglądać jak „prawdziwa” i nie będzie wyglądać jak strona internetowa. Co to znaczy być prawdziwa aplikacja?

Aby odpowiedzieć na to pytanie, użyję jako przykładu aplikacji Podcasty firmy Apple. Jest ona dostępna w systemie macOS na komputerze lub na iOS (odpowiednio na iPadOS) na urządzeniach mobilnych. Podcasty są aplikacją do multimediów, ale podstawowe pomysły, które przypomnę, z jej pomocą, mają zastosowanie także w innych kategoriach aplikacji.

iPhone i MacBook obok siebie z aplikacją Podcasty.
Apple Podcasty na iPhone'a i system macOS (źródło).

Możliwość pracy w trybie offline

Kiedy spojrzysz wstecz i przypomnisz sobie aplikacje związane z konkretną platformą, które masz w telefonie komórkowym lub komputerze, wyraźnie oddaje się jedna rzecz: nigdy nie otrzymujesz niczego. Nawet gdy jestem offline, zawsze coś jest w aplikacji Podcasty. Jeśli nie masz połączenia sieciowego, aplikacja automatycznie się otworzy. Sekcja Top listy nie zawiera żadnych treści, natomiast zamiast tego wyświetla się komunikat Nie można się teraz połączyć powiązany z przyciskiem Ponów. To może nie być najbardziej przyjazne doświadczenie, ale coś mi daje.

Aplikacja Podcasty wyświetla komunikat „Nie można się teraz połączyć”, gdy nie jest dostępne połączenie sieciowe.
Aplikacja Podcasty bez połączenia z siecią.
Jak to zrobić w przeglądarce

Aplikacja Podcasty korzysta z tak zwanego modelu powłoki aplikacji. Wszystkie treści statyczne potrzebne do wyświetlenia głównej aplikacji są przechowywane lokalnie w pamięci podręcznej. Dotyczy to również obrazów dekoracyjnych, takich jak ikony menu po lewej stronie oraz ikony głównego interfejsu odtwarzacza. Zawartość dynamiczna, np. dane z Top list, jest wczytywana tylko na żądanie, a w razie niepowodzenia wczytywania można użyć treści zastępczych zapisanych lokalnie w pamięci podręcznej. Przeczytaj artykuł Model powłoki aplikacji, aby dowiedzieć się, jak zastosować ten model architektury w swojej aplikacji internetowej.

Treści offline są dostępne i można je odtwarzać

W trybie offline za pomocą panelu po lewej stronie nadal mogę przejść do sekcji Pobrane i odsłuchać pobrane odcinki podcastu, które są gotowe do odtwarzania i są wyświetlane ze wszystkimi metadanymi, takimi jak grafika i opisy.

Aplikacja Podcasty z pobranym odcinkiem odtwarzanego podcastu.
Pobrane odcinki podcastów można odtwarzać nawet bez połączenia z siecią.
Jak to zrobić w przeglądarce

Wcześniej pobrane treści multimedialne mogą być wyświetlane z pamięci podręcznej, np. przy użyciu przepisu Udostępnianie dźwięku i obrazu z pamięci podręcznej z biblioteki Workbox. Inne treści można zawsze przechowywać w pamięci podręcznej lub w IndexedDB. Więcej informacji na ten temat znajdziesz w artykule Miejsce na dane w internecie. Dowiesz się z niego, kiedy używać wybranej technologii przechowywania danych. Jeśli masz dane, które powinny być trwale przechowywane bez ryzyka ich trwałego usunięcia po wyczerpaniu dostępnej pamięci, możesz użyć interfejsu Persistent Storage API.

Aktywne pobieranie w tle

Gdy jestem z powrotem online, mogę oczywiście wyszukać treści za pomocą zapytania typu http 203, a gdy zdecyduję się zasubskrybować wynik wyszukiwania, podcast HTTP 203, od razu zostanie pobrany ostatni odcinek serii, bez żadnych pytań.

Aplikacja Podcasty pobiera najnowszy odcinek podcastu natychmiast po zasubskrybowaniu.
Gdy zasubskrybujesz podcast, jego najnowszy odcinek zostanie od razu pobrany.
Jak to zrobić w przeglądarce

Pobranie odcinka podcastu może potrwać dłużej. Interfejs Background Fetch API pozwala przekazywać pobrane pliki przeglądarce, która będzie je wykonywać w tle. Na Androidzie przeglądarka może nawet przekazać te pliki do systemu operacyjnego, dzięki czemu przeglądarka nie musi działać w sposób ciągły. Po zakończeniu pobierania aktywuje się skrypt service worker aplikacji, w którym możesz określić, co zrobić z odpowiedzią.

Udostępnianie i interakcja z innymi aplikacjami

Aplikacja Podcasty integruje się w naturalny sposób z innymi aplikacjami. Gdy na przykład kliknę prawym przyciskiem myszy odcinek, który mi się podoba, mogę go udostępnić innym aplikacjom na urządzeniu, takim jak Wiadomości. Ta funkcja w naturalny sposób integruje się ze schowkiem systemowym. Mogę kliknąć prawym przyciskiem myszy dowolny odcinek i skopiować do niego link.

Menu kontekstowe aplikacji Podcasty zostało wywołane w przypadku odcinka podcastu z wybraną opcją „Udostępnij odcinek → Wiadomości”.
udostępnienie odcinka podcastu w aplikacji Wiadomości.
Jak to zrobić w przeglądarce

Web Share API i Web Share Target API pozwalają aplikacji na udostępnianie i odbieranie tekstów, plików i linków do i z innych aplikacji na urządzeniu. W aplikacji internetowej nie ma jeszcze możliwości dodawania pozycji menu do wbudowanego menu rozwijanego prawym przyciskiem myszy w systemie operacyjnym, ale istnieje wiele innych sposobów tworzenia linków do innych aplikacji na urządzeniu i z nich. Interfejs Async Clipboard API umożliwia programowe odczytywanie i zapisywanie danych tekstowych i graficznych (obrazów PNG) w schowku systemowym. Na urządzeniu z Androidem możesz użyć interfejsu Contact Picker API, aby wybrać wpisy z menedżera kontaktów na urządzeniu. Jeśli oferujesz zarówno aplikację na określoną platformę, jak i aplikację PWA, możesz użyć interfejsu Get installed Related Apps API, aby sprawdzić, czy jest zainstalowana ta aplikacja. W takim przypadku nie musisz zachęcać użytkowników do jej instalowania ani akceptowania powiadomień push w aplikacji internetowej.

Odświeżanie aplikacji w tle

W ustawieniach aplikacji Podcasty mogę skonfigurować ją tak, aby automatycznie pobierała nowe odcinki. Dzięki temu nawet nie muszę o tym myśleć. Aktualne treści zawsze będą tam dostępne. Magia.

Menu ustawień aplikacji Podcasty w sekcji „Ogólne”, gdzie opcja „Odśwież podcasty” jest ustawiona na „Co godzinę”.
Podcasty skonfigurowane tak, aby sprawdzały, czy jest dostępny nowy odcinek co godzinę.
Jak to zrobić w przeglądarce

Interfejs Periodic Background Sync API umożliwia aplikacji regularne odświeżanie zawartości w tle bez konieczności jej działania. Oznacza to, że nowe treści są dostępne bez pytania, więc użytkownicy mogą od razu zacząć z nich korzystać, gdy tylko zechcą.

Stan zsynchronizowany przez chmurę

Jednocześnie moje subskrypcje są synchronizowane na wszystkich moich urządzeniach. Dzisiaj nie muszę się przejmować ręczną synchronizacją subskrypcji podcastów. Nie muszę się też martwić, że w pamięci urządzenia mobilnego wliczają się odcinki, których słucham na komputerze. Stan odtwarzania jest zsynchronizowany, a odsłuchane odcinki są automatycznie usuwane.

Menu ustawień aplikacji Podcasty w sekcji „Zaawansowane” z aktywowaną opcją „Synchronizuj subskrypcje na różnych urządzeniach”.
Stan jest zsynchronizowany z chmurą.
Jak to zrobić w przeglądarce

Synchronizowanie danych o stanie aplikacji to zadanie, które możesz przekazać do interfejsu Background Sync API. Sama operacja synchronizacji nie musi nastąpić od razu, jedynie w końcu, a nawet po ponownym zamknięciu aplikacji przez użytkownika.

Opcje sprzętowego klawisza multimedialnego

Kiedy mam zajęty dostęp do innej aplikacji, na przykład czytając stronę z wiadomościami w przeglądarce Chrome, nadal mogę sterować aplikacją Podcasty za pomocą klawiszy multimedialnych na laptopie. Nie trzeba przechodzić do aplikacji, aby przewinąć film do przodu lub do tyłu.

Magiczna klawiatura Apple MacBook Pro z adnotacjami klawiszy multimedialnych.
Klawisze multimedialne umożliwiają sterowanie aplikacją Podcasty (źródło).
Jak to zrobić w przeglądarce

Klucze multimediów są obsługiwane przez interfejs Media Session API. W ten sposób użytkownicy mogą używać sprzętowych klawiszy multimedialnych na klawiaturze fizycznej i słuchawkach, a nawet sterować aplikacją internetową za pomocą programowych klawiszy multimedialnych na zegarkach. Dodatkowym sposobem na ułatwienie wyszukiwania jest wysyłanie wzorca wibracji, gdy użytkownik wyszuka znaczącą część treści, np. w przypadku przejścia między napisami początkowymi lub granicami rozdziału.

Wielozadaniowość i skrót do aplikacji

Oczywiście zawsze mogę wykonywać wiele zadań jednocześnie i z dowolnego miejsca wrócić do aplikacji Podcasty. Aplikacja ma łatwo rozpoznawalną ikonę, którą mogę też umieścić na pulpicie lub w docku z aplikacją, aby podcasty uruchamiały się od razu, gdy mam na to ochotę.

Przełącznik zadań w systemie macOS z kilkoma ikonami aplikacji do wyboru – jedną z nich jest aplikacja Podcasty.
Wykonywanie wielu zadań jednocześnie w aplikacji Podcasty
Jak to zrobić w przeglądarce

Progresywne aplikacje internetowe zarówno na komputerach, jak i urządzeniach mobilnych można instalować na ekranie głównym, w menu Start lub w docku z aplikacjami. Instalacja może się odbyć po otrzymaniu aktywnej prośby lub w pełni kontrolowana przez dewelopera aplikacji. W artykule Jak zainstalować aplikację? znajdziesz wszystko, co musisz wiedzieć na ten temat. Podczas wykonywania wielu zadań aplikacje PWA wyglądają niezależnie od przeglądarki.

Szybkie działania w menu kontekstowym

Najpopularniejsze działania w aplikacji – wyszukiwanie nowych treści i sprawdzanie nowych odcinków – są dostępne bezpośrednio w menu kontekstowym aplikacji w Docku. W menu Opcje mogę też określić, że aplikacja ma być otwierana w momencie logowania.

Menu kontekstowe ikony aplikacji Podcasty z opcjami „Szukaj” i „Sprawdź nowe odcinki”.
Szybkie działania są dostępne od razu po kliknięciu ikony aplikacji.
Jak to zrobić w przeglądarce

Określając skróty ikony aplikacji w pliku manifestu aplikacji internetowej PWA, możesz rejestrować szybkie trasy do typowych zadań, do których użytkownicy mogą przejść bezpośrednio po kliknięciu ikony aplikacji. W systemach operacyjnych, takich jak macOS, użytkownicy mogą też kliknąć prawym przyciskiem myszy ikonę aplikacji i ustawić uruchamianie aplikacji w momencie logowania. Trwają prace nad propozycji uruchamiania po zalogowaniu.

Działa jako aplikacja domyślna

Z aplikacją Podcasty można zintegrować inne aplikacje na iOS, a nawet strony i e-maile, korzystając ze schematu adresu URL podcasts://. Jeśli w przeglądarce kliknę link taki jak podcasts://podcasts.apple.com/podcast/the-css-podcast/id1042283903, jestem bezpośrednio w aplikacji Podcasty i mogę zasubskrybować podcast lub go odsłuchać.

Przeglądarka Chrome z oknem potwierdzenia z pytaniem, czy użytkownik chce otworzyć aplikację Podcasty.
Aplikację Podcasty można otworzyć w przeglądarce.
Jak to zrobić w przeglądarce

Obsługa w pełni niestandardowych schematów adresów URL nie jest jeszcze możliwa, ale trwają prace nad propozycji obsługi protokołów adresów URL w PWA. Obecnie najlepszą alternatywą jest registerProtocolHandler() z prefiksem schematu web+.

Integracja z lokalnym systemem plików

Być może nie przyszło Ci to od razu, ale aplikacja Podcasty w naturalny sposób integruje się z lokalnym systemem plików. Gdy pobieram odcinek podcastu, jest on przechowywany na laptopie w usłudze ~/Library/Group Containers/243LU875E5.groups.com.apple.podcasts/Library/Cache. W przeciwieństwie do np. ~/Documents ten katalog oczywiście nie jest przeznaczony bezpośrednio dla zwykłych użytkowników, ale on istnieje. Sekcja Treści offline zawiera odwołania do innych mechanizmów przechowywania danych niż pliki.

Finder w systemie macOS przeszedł do katalogu systemowego aplikacji Podcasty.
Odcinki podcastów są przechowywane w specjalnym folderze aplikacji systemowej.
Jak to zrobić w przeglądarce

Interfejs File System Access API umożliwia programistom uzyskanie dostępu do lokalnego systemu plików na urządzeniu. Możesz z niej skorzystać bezpośrednio lub za pomocą biblioteki pomocy browser-fs-access, która w przejrzysty sposób tworzy wersję zastępczą dla przeglądarek, które nie obsługują tego interfejsu API. Ze względów bezpieczeństwa katalogi systemowe są niedostępne w internecie.

Wygląd i styl platformy

W przypadku aplikacji na iOS, takiej jak Podcasty, jest bardziej subtelna rzecz: nie można wybrać żadnych etykiet tekstowych, a cały tekst wtapiają się w czcionkę systemową komputera. Respektowany jest też mój wybór motywu kolorystycznego systemu (tryb ciemny).

aplikacja Podcasty w trybie ciemnym,
Aplikacja Podcasty obsługuje tryb jasny i ciemny.
Aplikacja Podcasty w trybie jasnym.
Aplikacja używa domyślnej czcionki systemowej.
Jak to zrobić w przeglądarce

Korzystając z właściwości CSS user-select o wartości none, możesz chronić elementy interfejsu przed przypadkowym wyborem. Uważaj jednak, aby nie nadużywać tej właściwości do usuwania zawartości aplikacji. Należy go używać tylko w przypadku elementów interfejsu, np. tekstów przycisków. Wartość system-ui właściwości CSS font-family pozwala określić domyślną czcionkę interfejsu systemu, która ma być używana w przypadku Twojej aplikacji. Aplikacja może też stosować wybrane przez użytkownika kolorystykę, respektując wybór prefers-color-scheme oraz opcjonalnym przełącznikiem trybu ciemnego, który zastąpi tę opcję. Kolejną rzeczą, o której musisz się zdecydować, może być to, co powinna zrobić przeglądarka po osiągnięciu granicy obszaru przewijania, np. w celu zaimplementowania niestandardowej funkcji pociągnij, aby odświeżyć. Jest to możliwe dzięki właściwości CSS overscroll-behavior.

Własny pasek tytułu

Gdy spojrzysz na okno aplikacji Podcasty, zauważysz, że nie ma ona klasycznego zintegrowanego paska tytułu i paska narzędzi, np. okna przeglądarki Safari, tylko niestandardowego interfejsu, który wygląda jak pasek boczny zadokowany do głównego okna odtwarzacza.

Zintegrowany pasek kafelków i pasek narzędzi przeglądarki Safari.
Spersonalizowany, podzielony pasek tytułu aplikacji Podcasty.
Niestandardowe paski tytułów w Safari i podcastach.
Jak to zrobić w przeglądarce

Obecnie nie jest to możliwe, ale pracujemy nad dostosowaniem paska tytułu. Możesz (i powinno) określić właściwości display i theme-color pliku manifestu aplikacji internetowej, aby określić wygląd i styl okna aplikacji oraz zdecydować, które domyślne ustawienia przeglądarki (a potencjalnie żadne z nich) nie powinny być wyświetlane.

Atrakcyjne animacje

Animacje w aplikacji są płynne i chwytliwe w Podcastach. Na przykład gdy otwieram panel Notatki odcinka po prawej stronie, elegancko się wsuwa. Gdy usuwam jeden odcinek z pobranych filmów, pozostałe odcinki przesuwają się w górę i zajmują miejsce dostępne na ekranie, które zostało zwolnione dzięki usunięciu odcinka.

Aplikacja Podcasty z rozwiniętą szufladą „Notatki dotyczące odcinka”.
Animacje w aplikacji, np. po otwarciu panelu, są dynamiczne.
Jak to zrobić w przeglądarce

Utworzenie skutecznych animacji w internecie jest oczywiście możliwe, o ile zastosujesz sprawdzone metody opisane w artykule Animacje i wydajność. Animacje przewijania, które są często spotykane w treściach podzielonych na strony lub w karuzeli multimediów, można znacząco poprawić przy użyciu funkcji CSS Scroll Snap. Aby mieć pełną kontrolę, użyj interfejsu Web Animations API.

Treści wyświetlane poza aplikacją

Aplikacja Podcasty na iOS może wyświetlać treści w innych miejscach niż rzeczywista aplikacja, na przykład w widoku widżetów systemu lub w postaci sugestii Siri. Aktywne wezwania do działania oparte na wykorzystaniu, które wymagają kliknięcia, aby wejść w interakcję, mogą znacznie zwiększyć współczynnik ponownego zaangażowania użytkowników aplikacji takich jak Podcasty.

Widok widżetu w iOS, w którym aplikacja Podcasty sugeruje nowy odcinek podcastu.
Treści aplikacji pojawiają się poza główną aplikacją Podcasty.
Jak to zrobić w przeglądarce

Interfejs Content Index API pozwala aplikacji informować przeglądarkę, które treści PWA są dostępne offline. Dzięki temu przeglądarka może wyświetlać te treści poza główną aplikacją. Oznaczając interesujące treści w aplikacji jako odpowiednie do odtwarzania dźwięku głośnie i ogólnie używając znaczników uporządkowanych danych, możesz pomóc wyszukiwarkom i wirtualnym asystentom, takim jak Asystent Google, zaprezentować Twoją ofertę w idealnym świetle.

Widżet do sterowania multimediami na ekranie blokady

Podczas odtwarzania odcinka podcastu na ekranie blokady wyświetla się atrakcyjny widżet z elementami sterującymi zawierającymi takie metadane jak grafika i tytuł odcinka.

Widżet odtwarzania multimediów na iOS na ekranie blokady z odcinkiem podcastu ze szczegółowymi metadanymi.
Multimediami odtwarzanymi w aplikacji można sterować z ekranu blokady.
Jak to zrobić w przeglądarce

Interfejs Media Session API pozwala określić metadane, takie jak grafika, tytuły utworów itp., które są wyświetlane na ekranie blokady, zegarkach lub innych widżetach multimedialnych w przeglądarce.

Powiadomienia push

Powiadomienia push są trochę uciążliwe w internecie (chociaż teraz prośby o powiadomienia są teraz znacznie cichsze). Jednak jeśli zostaną odpowiednio wykorzystane, mogą wiele zyskać. Na przykład aplikacja Podcasty na iOS może powiadamiać mnie o nowych odcinkach podcastów, które subskrybuję, lub polecać nowe, a także powiadamiać mnie o nowych funkcjach.

Aplikacja Podcasty na iOS na ekranie ustawień „Powiadomienia” z włączonym przełącznikiem powiadomień „Nowe odcinki”.
Aplikacje mogą wysyłać powiadomienia push, aby informować użytkownika o nowych treściach.
Jak to zrobić w przeglądarce

Interfejs Push API umożliwia aplikacji otrzymywanie powiadomień push, co pozwala informować użytkowników o istotnych zdarzeniach związanych z aplikacją PWA. W przypadku powiadomień, które powinny być uruchamiane w znanym czasie w przyszłości i nie wymagają połączenia z siecią, możesz użyć interfejsu Notification Triggers API.

Plakietki na ikonach aplikacji

Gdy dostępne są nowe odcinki jednego z subskrybowanych przeze mnie podcastów, na ikonie na ekranie głównym Podcastów wyświetla się plakietka aplikacji, która zachęca mnie do ponownego użycia aplikacji w sposób, który nie uciążliwy.

Ekran ustawień iOS z włączonym przełącznikiem „Plakietki”.
Plakietki to subtelny sposób informowania użytkowników o nowych treściach przez aplikacje.
Jak to zrobić w przeglądarce

Plakietki ikon aplikacji możesz ustawić za pomocą interfejsu Badging API. Jest to szczególnie przydatne, gdy w Twojej aplikacji PWA występują elementy „nieprzeczytane” lub gdy potrzebujesz sposobu na dyskretne zwrócenie uwagi użytkownika na aplikację.

Odtwarzanie multimediów ma pierwszeństwo przed ustawieniami oszczędzania energii

Podczas odtwarzania multimediów może się wyłączyć ekran, ale system nie przejdzie w tryb gotowości. Aplikacje mogą też opcjonalnie umożliwiać wybudzanie ekranu, na przykład wyświetlać tekst piosenek lub napisy.

Ustawienia systemu macOS w sekcji „Oszczędzanie energii”.
Aplikacje mogą utrzymywać ekran w trybie wybudzania.
Jak to zrobić w przeglądarce

Interfejs Screen Wake Lock API uniemożliwia wyłączenie ekranu. Odtwarzanie multimediów w internecie automatycznie uniemożliwia systemowi przejście w tryb gotowości.

Odkrywanie aplikacji w sklepie z aplikacjami

Aplikacja Podcasty jest częścią systemu macOS, ale w systemie iOS trzeba ją zainstalować z App Store. Szybkie wyszukiwanie hasła podcast, podcasts lub apple podcasts natychmiast powoduje wyświetlenie aplikacji w App Store.

Wyszukanie słowa „podcasty” w sklepie z aplikacjami na iOS spowoduje wyświetlenie aplikacji Podcasty.
Użytkownicy już nauczyli się odkrywać aplikacje w sklepach z aplikacjami.
Jak to zrobić w przeglądarce

Apple nie zezwala na aplikacje PWA w App Store, ale w przypadku Androida możesz je przesłać zawartą w zaufanej aktywności w internecie. Skrypt bubblewrap sprawia, że ta operacja jest prosta. Ten skrypt jest też wewnętrznym mechanizmem funkcji eksportu aplikacji na Androida w PWABuilder, której możesz używać bez konieczności wprowadzania zmian w wierszu poleceń.

Podsumowanie funkcji

Poniższa tabela zawiera zwięzłe omówienie wszystkich funkcji wraz z listą przydatnych zasobów, które ułatwią Ci zapoznanie się z nimi w internecie.

Funkcja Przydatne materiały internetowe
Możliwość pracy offline
Dostęp do treści offline i multimediów z możliwością odtwarzania
Proaktywne pobieranie w tle
Udostępnianie i interakcja z innymi aplikacjami
Odświeżanie aplikacji w tle
Stan zsynchronizowany z chmurą
Elementy sterujące sprzętowego klawisza multimedialnego
Wielozadaniowość i skrót do aplikacji
Szybkie czynności w menu kontekstowym
Działanie jako aplikacja domyślna
Integracja z lokalnym systemem plików
Wygląd i działanie platformy
Niestandardowy pasek tytułu
Atrakcyjne animacje
Treści wyświetlane poza aplikacją
Widżet do sterowania multimediami na ekranie blokady
Powiadomienia push
Plakietki na ikonach aplikacji
Odtwarzanie multimediów ma wyższy priorytet niż ustawienia oszczędzania energii
Odkrywanie aplikacji w sklepie z aplikacjami

Podsumowanie

PWA bardzo się zmieniły od czasu ich wprowadzenia w 2015 roku. W kontekście Projektu Fugu 🐡 zespół Chromium z różnych firm pracuje nad usunięciem ostatnich luk. Po zapoznaniu się tylko z niektórymi poradami z tego artykułu możesz stopniowo zbliżyć się do uczuć podobnych do aplikacji i sprawić, że użytkownicy będą zapomnieć, że mają do czynienia z „tylko witryną”, ponieważ tak naprawdę większość z nich nie ma znaczenia, jak zbudowana jest Twoja aplikacja (i dlaczego powinna), o ile wydaje się ona prawdziwa.

Podziękowania

Autor artykułu: Kayce Basques, Joe Medley, Joshua Bell, Dion Almaer, Ade Oshineye, Pete LePage, Sam Thorogood, Reilkinly Grant}