{"id":3608,"date":"2021-03-03T20:11:49","date_gmt":"2021-03-03T20:11:49","guid":{"rendered":"https:\/\/ionicframework.com\/blog\/?p=3608"},"modified":"2021-03-04T14:11:27","modified_gmt":"2021-03-04T14:11:27","slug":"start-build-deploy-your-first-capacitor-pwa-with-ionic","status":"publish","type":"post","link":"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic","title":{"rendered":"Start, Build &#038; Deploy Your First Capacitor PWA with Ionic"},"content":{"rendered":"<blockquote><p>\n  This is a guest post from Simon Grimm, Ionic Developer Expert and educator at <a href=\"https:\/\/ionicacademy.com\/\">the Ionic Academy<\/a>. Simon also created the <a href=\"https:\/\/devdactic.com\/practical-ionic\/\">Practical Ionic<\/a> book, a guide to building real world Ionic applications with Capacitor and Firebase.\n<\/p><\/blockquote>\n<p>In this tutorial we will build a simple Capacitor PWA with Ionic and Angular. We will integrate functionality to capture an image and share our current position using Capacitor plugins which work inside both native apps and PWAs!<\/p>\n<p><img decoding=\"async\" style=\"--smush-placeholder-width: 512px; --smush-placeholder-aspect-ratio: 512\/994;width:300px\" data-src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/03\/capacitor-pwa-example.gif\" alt=\"\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" class=\"lazyload\" \/><noscript><img decoding=\"async\" style=\"width:300px\" src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/03\/capacitor-pwa-example.gif\" alt=\"\" \/><\/noscript><\/p>\n<p>Finally we will bring our PWA to the outside world by hosting it on <a href=\"https:\/\/www.netlify.com\/\">Netlify<\/a>, so we got a full trip from start to hosted PWA in one go.<\/p>\n<p><!--more--><\/p>\n<h2>Ionic App Setup<\/h2>\n<p>To get started, simply use the Ionic CLI to create a blank new project with Angular integration and Capacitor directly enabled:<\/p>\n<pre><code class=\"language-sh\">\/\/ Install the Ionic CLI globally if needed\nnpm i -g @ionic\/cli\n\n\/\/ Start a blank new Ionic app\nionic start ionicPwa blank --type=angular --capacitor\n<\/code><\/pre>\n<p>This will create a new Ionic application that already comes with all configuration for Capacitor in place. In this tutorial we won&#8217;t get into building native apps, but you could easily <a href=\"https:\/\/capacitorjs.com\/docs\/basics\/building-your-app\">build your app for iOS and Android<\/a> from this codebase using Capacitor in the end as well!<\/p>\n<p>We will use Capacitor 3.0 in this tutorial, so check the dependencies inside your <strong>package.json<\/strong> for <code>@capacitor\/core<\/code> and <code>@capacitor\/cli<\/code> and if they are still below v3, install the latest version like this:<\/p>\n<pre><code class=\"language-sh\">npm install @capacitor\/cli@next @capacitor\/core@next\n<\/code><\/pre>\n<p>At the time writing Capacitor 3 was still in beta, but we&#8217;re living on the edge today!<\/p>\n<h2>Make Your Ionic App PWA Ready<\/h2>\n<p>The process of making an Angular app PWA ready is quite easy given the Angular schematics that automatically change all necessary parts of your project and inject a Service Worker in the right place:<\/p>\n<pre><code class=\"language-sh\">\/\/ Install Angular CLI globally if needed\nnpm i -g @angular\/cli\n\n\/\/ Run the Angular schematic for PWAs\nng add @angular\/pwa\n<\/code><\/pre>\n<p>If you now check out your updated <strong>app\/app.module.ts<\/strong> you&#8217;ll see that the Service Worker will be injected into our app when built for production:<\/p>\n<pre><code class=\"language-ts\">@NgModule({\n  declarations: [AppComponent],\n  entryComponents: [],\n  imports: [BrowserModule, IonicModule.forRoot(),\n    AppRoutingModule,\n    ServiceWorkerModule.register(&#039;ngsw-worker.js&#039;,\n      { enabled: environment.production }\n    )],\n  providers: [{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }],\n  bootstrap: [AppComponent],\n})\nexport class AppModule { }\n<\/code><\/pre>\n<p>That means, we just need to make sure we run the correct build in the end before publishing our PWA &#8211; we\u2019ll come back to this as it\u2019s important for Netlify.<\/p>\n<h2>Adding Capacitor Plugins<\/h2>\n<p><a href=\"https:\/\/capacitorjs.com\/docs\/plugins\">Capacitor plugins<\/a> allow us to use native APIs or the according Web API implementation if we are running as a PWA (or standard website).<\/p>\n<p>That means, the same call\/code to capture an image or get the user&#8217;s geolocation works across different devices, and triggers the right functionality depending on the current run environment.<\/p>\n<p>A tiny change is that since version 3 of Capacitor, all plugins need to be installed separately and don&#8217;t exist inside the core package anymore. But that doesn&#8217;t make the process any more complicated as you will see.<\/p>\n<h3>Capturing Photos with PWA Elements<\/h3>\n<p>Yes, we can easily access the camera from within our PWa using Capacitor. The only problem is that there&#8217;s no decent web UI when capturing an image, and so we install another package called <a href=\"https:\/\/capacitorjs.com\/docs\/web\/pwa-elements\">PWA Elements<\/a> next to the camera plugin in our app now:<\/p>\n<pre><code class=\"language-sh\">npm i @capacitor\/camera\n\n\/\/ Overlay for image capturing on the web\nnpm install @ionic\/pwa-elements\n<\/code><\/pre>\n<p>To enable those elements, we need to import the <code>defineCustomElements<\/code> and call it inside our <strong>src\/main.ts<\/strong> like this:<\/p>\n<pre><code class=\"language-ts\">import { enableProdMode } from &#039;@angular\/core&#039;;\nimport { platformBrowserDynamic } from &#039;@angular\/platform-browser-dynamic&#039;;\n\nimport { AppModule } from &#039;.\/app\/app.module&#039;;\nimport { environment } from &#039;.\/environments\/environment&#039;;\n\n\/\/ Add the import\nimport { defineCustomElements } from &#039;@ionic\/pwa-elements\/loader&#039;;\n\nif (environment.production) {\n  enableProdMode();\n}\n\nplatformBrowserDynamic().bootstrapModule(AppModule)\n  .catch(err =&gt; console.log(err));\n\n\/\/ Call the loader\ndefineCustomElements(window);\n<\/code><\/pre>\n<p>Now we can import everything we need from the package and call <code>getPhoto()<\/code> to capture an image and set the resulting <code>webPath<\/code> to a local variable.<\/p>\n<p>Go ahead and change your <strong>home\/home.page.ts<\/strong> to:<\/p>\n<pre><code class=\"language-ts\">import { Component } from &#039;@angular\/core&#039;;\nimport { Camera, CameraResultType, CameraSource } from &#039;@capacitor\/camera&#039;;\n\n@Component({\n  selector: &#039;app-home&#039;,\n  templateUrl: &#039;home.page.html&#039;,\n  styleUrls: [&#039;home.page.scss&#039;],\n})\nexport class HomePage {\n\n  myImage = null;\n\n  constructor() {}\n\n  async takePicture() {\n    const image = await Camera.getPhoto({\n      quality: 90,\n      allowEditing: true,\n      resultType: CameraResultType.Uri,\n      source: CameraSource.Camera\n    });\n\n    this.myImage = image.webPath;\n  }\n}\n<\/code><\/pre>\n<p>Finally we need a simple button and <code>ion-img<\/code> to display the captured image inside our app, so change the <strong>home\/home.page.html<\/strong> to:<\/p>\n<pre><code class=\"language-html\">&lt;ion-header&gt;\n  &lt;ion-toolbar color=&quot;primary&quot;&gt;\n    &lt;ion-title&gt;\n      Capacitor PWA\n    &lt;\/ion-title&gt;\n  &lt;\/ion-toolbar&gt;\n&lt;\/ion-header&gt;\n\n&lt;ion-content&gt;\n  &lt;ion-button (click)=&quot;takePicture()&quot; expand=&quot;block&quot;&gt;\n    &lt;ion-icon name=&quot;camera&quot; slot=&quot;start&quot;&gt;&lt;\/ion-icon&gt;\n    Capture image\n  &lt;\/ion-button&gt;\n\n  &lt;ion-img *ngIf=&quot;myImage&quot; [src]=&quot;myImage&quot;&gt;&lt;\/ion-img&gt;\n&lt;\/ion-content&gt;\n<\/code><\/pre>\n<p>You can already try this inside your browser by bringing up the preview with <code>ionic serve<\/code> now!<\/p>\n<p>Of course the image capturing only works if you have some kind of webcam attached or inside your computer.<\/p>\n<h3>Geolocation<\/h3>\n<p>To show that the usage of every <a href=\"https:\/\/capacitorjs.com\/docs\/plugins\">Capacitor plugin<\/a> is really that easy, let&#8217;s install two more plugins to get the current user location and natively share it:<\/p>\n<pre><code class=\"language-sh\">\/\/ Install the geolocation plugin\nnpm i @capacitor\/geolocation\n\n\/\/ Install the share plugin\nnpm i @capacitor\/share\n<\/code><\/pre>\n<p>Just like before we can directly import the necessary functions from the two packages to first grab the position by calling <code>getCurrentPosition()<\/code> and then store that value so we can share it later with the share plugin.<\/p>\n<p>For this, bring up the <strong>home\/home.page.ts<\/strong> again and add the new code:<\/p>\n<pre><code class=\"language-ts\">import { Component } from &#039;@angular\/core&#039;;\nimport { Camera, CameraResultType, CameraSource } from &#039;@capacitor\/camera&#039;;\nimport { Geolocation, Position } from &#039;@capacitor\/geolocation&#039;;\nimport { Share } from &#039;@capacitor\/share&#039;;\n\n@Component({\n  selector: &#039;app-home&#039;,\n  templateUrl: &#039;home.page.html&#039;,\n  styleUrls: [&#039;home.page.scss&#039;],\n})\nexport class HomePage {\n\n  myImage: string = null;\n  position: Position = null;\n\n  constructor() {}\n\n  async takePicture() { ... }\n\n  async getCurrentPosition() {\n    const coordinates = await Geolocation.getCurrentPosition();\n\n    this.position = coordinates;\n  }\n\n  async share() {\n    await Share.share({\n      title: &#039;Come and find me&#039;,\n      text: `Here&#039;s my current location: \n        ${this.position.coords.latitude}, \n        ${this.position.coords.longitude}`,\n      url: &#039;http:\/\/ionicacademy.com\/&#039;\n    });\n  }\n}\n<\/code><\/pre>\n<p>Now we need some additional buttons to trigger our new functionality and to display the result, which we can easily do inside an <a href=\"https:\/\/ionicframework.com\/docs\/api\/card\">ion-card<\/a>.<\/p>\n<p>Open the <strong>home\/home.page.html<\/strong> again and change it to:<\/p>\n<pre><code class=\"language-html\">&lt;ion-header&gt;\n  &lt;ion-toolbar color=&quot;primary&quot;&gt;\n    &lt;ion-title&gt;\n      Capacitor PWA\n    &lt;\/ion-title&gt;\n  &lt;\/ion-toolbar&gt;\n&lt;\/ion-header&gt;\n\n&lt;ion-content&gt;\n  &lt;ion-button (click)=&quot;takePicture()&quot; expand=&quot;block&quot;&gt;\n    &lt;ion-icon name=&quot;camera&quot; slot=&quot;start&quot;&gt;&lt;\/ion-icon&gt;\n    Capture image\n  &lt;\/ion-button&gt;\n\n  &lt;ion-img *ngIf=&quot;myImage&quot; [src]=&quot;myImage&quot;&gt;&lt;\/ion-img&gt;\n\n  &lt;ion-button (click)=&quot;getCurrentPosition()&quot; expand=&quot;block&quot;&gt;\n    &lt;ion-icon name=&quot;locate&quot; slot=&quot;start&quot;&gt;&lt;\/ion-icon&gt;\n    Get position\n  &lt;\/ion-button&gt;\n\n  &lt;!-- present the geolocation information --&gt;\n  &lt;ion-card *ngIf=&quot;position&quot;&gt;\n    &lt;ion-card-content&gt;\n      &lt;ion-item&gt;\n        &lt;ion-icon name=&quot;location&quot; slot=&quot;start&quot;&gt;&lt;\/ion-icon&gt;\n        Lat: {{ position.coords.latitude }}\n      &lt;\/ion-item&gt;\n      &lt;ion-item&gt;\n        &lt;ion-icon name=&quot;location&quot; slot=&quot;start&quot;&gt;&lt;\/ion-icon&gt;\n        Lng: {{ position.coords.longitude }}\n      &lt;\/ion-item&gt;\n\n      &lt;ion-button (click)=&quot;share()&quot; expand=&quot;block&quot; color=&quot;secondary&quot;&gt;\n        &lt;ion-icon name=&quot;share&quot; slot=&quot;start&quot;&gt;&lt;\/ion-icon&gt;\n        Share!\n      &lt;\/ion-button&gt;\n    &lt;\/ion-card-content&gt;\n  &lt;\/ion-card&gt;\n&lt;\/ion-content&gt;\n<\/code><\/pre>\n<p>With those two functionalities you might get into some trouble, because:<\/p>\n<ul>\n<li>Only recent browser versions support the new Web Share API<\/li>\n<li>Safari doesn&#8217;t capture a location on unsecure URLs (http), which localhost normally is<\/li>\n<\/ul>\n<p>That means, we really need to run our PWA on a real device soon. But before, a quick recommendation for testing your PWA locally in general.<\/p>\n<h2>Testing your Capacitor PWA<\/h2>\n<p>While developing your app, the Service Worker is not injected unless you make a production build. That means, when you run the standard <code>ionic serve<\/code> command it&#8217;s not a full PWA yet.<\/p>\n<p>If you want to test out the different PWA functionalities locally I recommend to simply install the <a href=\"https:\/\/github.com\/http-party\/http-server\">http-server package<\/a>, which can then host your application.<\/p>\n<p>Once installed, you just need to create a production build and run the local server like:<\/p>\n<pre><code class=\"language-sh\">ionic build --prod\nhttp-server www\n<\/code><\/pre>\n<p>This won&#8217;t change the previously mentioned problems of browser version or security, but it&#8217;s something you need to know about building &amp; testing your PWA anyway for the future.<\/p>\n<p>But people from outside still can&#8217;t access localhost, <em>right<\/em>? So let&#8217;s release our Capacitor PWA to the world!<\/p>\n<h2>Deploying your Capacitor PWA<\/h2>\n<p>If you got your own server, you could simply copy the <strong>www<\/strong> folder you get after creating a build of your app and upload it there.<\/p>\n<p>Since most of the time that&#8217;s not the case, we can fall back to a simple static hosting service like <a href=\"https:\/\/www.netlify.com\/\">Netlify<\/a> instead.<\/p>\n<p>Because Netlify needs to build our app in the end, we need to add a new script to the scripts object of our <strong>package.json<\/strong> right now:<\/p>\n<pre><code class=\"language-json\">&quot;build:prod&quot;: &quot;ng build --prod&quot;\n<\/code><\/pre>\n<p>This makes it easier to run a production build automatically.<\/p>\n<p>For now, we need to head over to <a href=\"https:\/\/github.com\/\">Github<\/a> or <a href=\"https:\/\/bitbucket.org\/\">Bitbucket<\/a> (whatever you prefer) to create a repository over there which we can connect to Netlify afterwards.<\/p>\n<p>I&#8217;ve used Github for this example and created a new repository without any files:<\/p>\n<p><img decoding=\"async\" data-src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/03\/github-repository.png\" alt=\"\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" class=\"lazyload\" style=\"--smush-placeholder-width: 1946px; --smush-placeholder-aspect-ratio: 1946\/2090;\" \/><noscript><img decoding=\"async\" src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/03\/github-repository.png\" alt=\"\" \/><\/noscript><\/p>\n<p>Now we need to upload our files to Github, and since Ionic already initialised a Git repository in our local project, we just need to add and commit our code.<\/p>\n<p>Then, follow the instructions from Github\/Bitbucket to connect your new repository, set it as the remote and push your code:<\/p>\n<pre><code class=\"language-sh\">git add .\ngit commit -am &#039;Initial commit.&#039;\n\ngit branch -M main\n\n# Copy this from your repository!\ngit remote add origin https:\/\/github.com\/saimon24\/capacitor-pwa.git\ngit push -u origin main\n<\/code><\/pre>\n<p>Our code is inside the repository, now we can connect it to Netlify.<\/p>\n<p>Inside your account, click on <strong>New site from Git<\/strong> to start the wizard that will add your project. You will need to authorise Netlify to access your Github (Bitbucket) account and you can select the previously created project.<\/p>\n<p><img decoding=\"async\" data-src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/03\/connect-netlify.png\" alt=\"\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" class=\"lazyload\" style=\"--smush-placeholder-width: 2460px; --smush-placeholder-aspect-ratio: 2460\/2610;\" \/><noscript><img decoding=\"async\" src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/03\/connect-netlify.png\" alt=\"\"  \/><\/noscript><\/p>\n<p>The important part is now to configure the build correctly in the next step:<\/p>\n<ul>\n<li>Build command: npm run build:prod<\/li>\n<li>Publish directory: www<\/li>\n<\/ul>\n<p>Based on this information, Netlify can now pull in your code, run a production build (<em>using the additional script we added to the package.json!<\/em>) and host the output <strong>www<\/strong> folder to serve our Capacitor PWA!<\/p>\n<p>Once you deploy the site, you can see the log and finally get the URL to your deployment. The <a href=\"https:\/\/awesome-mclean-aeb1a5.netlify.app\/\">example PWA for this tutorial is right here<\/a>.<\/p>\n<p>If you want to test it correctly, add it to your home screen and start it from there.<\/p>\n<p><img decoding=\"async\" style=\"--smush-placeholder-width: 824px; --smush-placeholder-aspect-ratio: 824\/1602;width:300px\" data-src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/03\/capacitor-installed-pwa.png\" alt=\"\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" class=\"lazyload\" \/><noscript><img decoding=\"async\" style=\"width:300px\" src=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/03\/capacitor-installed-pwa.png\" alt=\"\" \/><\/noscript><\/p>\n<p>The camera and geolocation plugin will automatically ask for permission, and you could use the same code inside a native app now as well!<\/p>\n<h2>Conclusion<\/h2>\n<p>With Capacitor, you can easily access native device functionalities inside your PWA or native app, and by adding a static site hosting to the mix you get a simple and reliable workflow for building hosting your Ionic PWA!<\/p>\n<p>Instead of Angular, you could also use any other framework (or none at all) in combination with Capacitor as it&#8217;s rapidly becoming the framework of choice for anyone who wants to build web apps that run natively on iOS, Android, and the Web.<\/p>\n<p>If you want to learn even more about Ionic and Capacitor with a library of 60+ video courses, templates and a supportive community, you can <a href=\"https:\/\/ionicacademy.com\/\">join the Ionic Academy<\/a> and get access to a ton of learning material to boost your Ionic development skills.<\/p>\n<p>And don\u2019t forget to <a href=\"https:\/\/www.youtube.com\/user\/saimon1924\">subscribe to my YouTube channel<\/a> for fresh Ionic tutorials coming every week!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is a guest post from Simon Grimm, Ionic Developer Expert and educator at the Ionic Academy. Simon also created the Practical Ionic book, a guide to building real world Ionic applications with Capacitor and Firebase. In this tutorial we will build a simple Capacitor PWA with Ionic and Angular. We will integrate functionality to [&hellip;]<\/p>\n","protected":false},"author":11,"featured_media":3613,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"publish_to_discourse":"0","publish_post_category":"26","wpdc_auto_publish_overridden":"","wpdc_topic_tags":"","wpdc_pin_topic":"","wpdc_pin_until":"","discourse_post_id":"499261","discourse_permalink":"https:\/\/forum.ionicframework.com\/t\/start-build-deploy-your-first-capacitor-pwa-with-ionic\/205863","wpdc_publishing_response":"","wpdc_publishing_error":"","_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[124],"tags":[60,151,22,33],"class_list":["post-3608","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","tag-angular","tag-capacitor","tag-progressive-web-apps","tag-pwa"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v23.0 (Yoast SEO v23.0) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Start, Build &amp; Deploy Your First Capacitor PWA with Ionic - Ionic Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Start, Build &amp; Deploy Your First Capacitor PWA with Ionic\" \/>\n<meta property=\"og:description\" content=\"This is a guest post from Simon Grimm, Ionic Developer Expert and educator at the Ionic Academy. Simon also created the Practical Ionic book, a guide to building real world Ionic applications with Capacitor and Firebase. In this tutorial we will build a simple Capacitor PWA with Ionic and Angular. We will integrate functionality to [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic\" \/>\n<meta property=\"og:site_name\" content=\"Ionic Blog\" \/>\n<meta property=\"article:published_time\" content=\"2021-03-03T20:11:49+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-03-04T14:11:27+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/03\/photo-1522542550221-31fd19575a2d.webp\" \/>\n\t<meta property=\"og:image:width\" content=\"2550\" \/>\n\t<meta property=\"og:image:height\" content=\"1700\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/webp\" \/>\n<meta name=\"author\" content=\"Simon Grimm\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@schlimmson\" \/>\n<meta name=\"twitter:site\" content=\"@ionicframework\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Simon Grimm\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic#article\",\"isPartOf\":{\"@id\":\"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic\"},\"author\":{\"name\":\"Simon Grimm\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/24d44b251756bd6488dcb741eec0bef6\"},\"headline\":\"Start, Build &#038; Deploy Your First Capacitor PWA with Ionic\",\"datePublished\":\"2021-03-03T20:11:49+00:00\",\"dateModified\":\"2021-03-04T14:11:27+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic\"},\"wordCount\":1400,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/ionic.io\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic#primaryimage\"},\"thumbnailUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/03\/photo-1522542550221-31fd19575a2d.webp\",\"keywords\":[\"Angular\",\"Capacitor\",\"Progressive Web Apps\",\"PWA\"],\"articleSection\":[\"Tutorials\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic\",\"url\":\"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic\",\"name\":\"Start, Build & Deploy Your First Capacitor PWA with Ionic - Ionic Blog\",\"isPartOf\":{\"@id\":\"https:\/\/ionic.io\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic#primaryimage\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic#primaryimage\"},\"thumbnailUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/03\/photo-1522542550221-31fd19575a2d.webp\",\"datePublished\":\"2021-03-03T20:11:49+00:00\",\"dateModified\":\"2021-03-04T14:11:27+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic#primaryimage\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/03\/photo-1522542550221-31fd19575a2d.webp\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/03\/photo-1522542550221-31fd19575a2d.webp\",\"width\":2550,\"height\":1700},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/ionic.io\/blog\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Start, Build &#038; Deploy Your First Capacitor PWA with Ionic\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/ionic.io\/blog\/#website\",\"url\":\"https:\/\/ionic.io\/blog\/\",\"name\":\"ionic.io\/blog\",\"description\":\"Build amazing native and progressive web apps with the web\",\"publisher\":{\"@id\":\"https:\/\/ionic.io\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/ionic.io\/blog\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/ionic.io\/blog\/#organization\",\"name\":\"Ionic\",\"url\":\"https:\/\/ionic.io\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png\",\"width\":1920,\"height\":854,\"caption\":\"Ionic\"},\"image\":{\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/x.com\/ionicframework\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/24d44b251756bd6488dcb741eec0bef6\",\"name\":\"Simon Grimm\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/ionic.io\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/08\/simon-150x150.jpg\",\"contentUrl\":\"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/08\/simon-150x150.jpg\",\"caption\":\"Simon Grimm\"},\"sameAs\":[\"https:\/\/x.com\/schlimmson\"],\"url\":\"https:\/\/ionic.io\/blog\/author\/schlimmson\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Start, Build & Deploy Your First Capacitor PWA with Ionic - Ionic Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic","og_locale":"en_US","og_type":"article","og_title":"Start, Build & Deploy Your First Capacitor PWA with Ionic","og_description":"This is a guest post from Simon Grimm, Ionic Developer Expert and educator at the Ionic Academy. Simon also created the Practical Ionic book, a guide to building real world Ionic applications with Capacitor and Firebase. In this tutorial we will build a simple Capacitor PWA with Ionic and Angular. We will integrate functionality to [&hellip;]","og_url":"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic","og_site_name":"Ionic Blog","article_published_time":"2021-03-03T20:11:49+00:00","article_modified_time":"2021-03-04T14:11:27+00:00","og_image":[{"width":2550,"height":1700,"url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/03\/photo-1522542550221-31fd19575a2d.webp","type":"image\/webp"}],"author":"Simon Grimm","twitter_card":"summary_large_image","twitter_creator":"@schlimmson","twitter_site":"@ionicframework","twitter_misc":{"Written by":"Simon Grimm","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic#article","isPartOf":{"@id":"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic"},"author":{"name":"Simon Grimm","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/24d44b251756bd6488dcb741eec0bef6"},"headline":"Start, Build &#038; Deploy Your First Capacitor PWA with Ionic","datePublished":"2021-03-03T20:11:49+00:00","dateModified":"2021-03-04T14:11:27+00:00","mainEntityOfPage":{"@id":"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic"},"wordCount":1400,"commentCount":0,"publisher":{"@id":"https:\/\/ionic.io\/blog\/#organization"},"image":{"@id":"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic#primaryimage"},"thumbnailUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/03\/photo-1522542550221-31fd19575a2d.webp","keywords":["Angular","Capacitor","Progressive Web Apps","PWA"],"articleSection":["Tutorials"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic#respond"]}]},{"@type":"WebPage","@id":"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic","url":"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic","name":"Start, Build & Deploy Your First Capacitor PWA with Ionic - Ionic Blog","isPartOf":{"@id":"https:\/\/ionic.io\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic#primaryimage"},"image":{"@id":"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic#primaryimage"},"thumbnailUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/03\/photo-1522542550221-31fd19575a2d.webp","datePublished":"2021-03-03T20:11:49+00:00","dateModified":"2021-03-04T14:11:27+00:00","breadcrumb":{"@id":"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic#primaryimage","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/03\/photo-1522542550221-31fd19575a2d.webp","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/03\/photo-1522542550221-31fd19575a2d.webp","width":2550,"height":1700},{"@type":"BreadcrumbList","@id":"https:\/\/ionic.io\/blog\/start-build-deploy-your-first-capacitor-pwa-with-ionic#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/ionic.io\/blog"},{"@type":"ListItem","position":2,"name":"Start, Build &#038; Deploy Your First Capacitor PWA with Ionic"}]},{"@type":"WebSite","@id":"https:\/\/ionic.io\/blog\/#website","url":"https:\/\/ionic.io\/blog\/","name":"ionic.io\/blog","description":"Build amazing native and progressive web apps with the web","publisher":{"@id":"https:\/\/ionic.io\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/ionic.io\/blog\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/ionic.io\/blog\/#organization","name":"Ionic","url":"https:\/\/ionic.io\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/10\/white-on-color.png","width":1920,"height":854,"caption":"Ionic"},"image":{"@id":"https:\/\/ionic.io\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/x.com\/ionicframework"]},{"@type":"Person","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/24d44b251756bd6488dcb741eec0bef6","name":"Simon Grimm","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ionic.io\/blog\/#\/schema\/person\/image\/","url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/08\/simon-150x150.jpg","contentUrl":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2020\/08\/simon-150x150.jpg","caption":"Simon Grimm"},"sameAs":["https:\/\/x.com\/schlimmson"],"url":"https:\/\/ionic.io\/blog\/author\/schlimmson"}]}},"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/ionic.io\/blog\/wp-content\/uploads\/2021\/03\/photo-1522542550221-31fd19575a2d.webp","_links":{"self":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/3608","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/users\/11"}],"replies":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/comments?post=3608"}],"version-history":[{"count":0,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/posts\/3608\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/media\/3613"}],"wp:attachment":[{"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/media?parent=3608"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/categories?post=3608"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ionic.io\/blog\/wp-json\/wp\/v2\/tags?post=3608"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}