See how Capacitor fits into the entire Ionic Ecosystem ->
Capacitor is part of the Ionic Ecosystem ->
DocsプラグインCLI

Capacitor Blog

Articles by the Capacitor team and community

Build Mobile Apps with Tailwind CSS, Next.js, Ionic Framework, and Capacitor

A very popular stack for building responsive web apps is Tailwind CSS and Next.js by Vercel.

Tailwind, a utility-first CSS framework that replaces the need to write custom class names or even any CSS at all in many cases, makes it easy to design responsive web apps through small CSS building blocks and a flexible design foundation.

Next.js, a React framework for building high performance React apps, is one of the leading environments for building production React apps on the web.

As these technologies have grown, they are increasingly used together for web app development (in fact, Next.js is working on an RFC for official Tailwind integration). This has prompted many users of these projects to ask whether they can be used to build mobile apps, too.

Turns out, they can! And they make a great fit for cross-platform mobile development when paired with Ionic Framework and Capacitor.

As I started playing with these technologies, I realized that each had a natural fit in a combined mobile stack, and I wanted to put together a solid starting foundation for others interested in building real iOS and Android apps using these technologies.

If you’re confused by all the project names and how they work together, don’t worry, I’ll break down each part of the stack each project is concerned with, along with some visuals and code samples demonstrating how all the projects work together. At the end I’ll share a starter project with these technologies installed and working together that can form the foundation of your next app.

The Stack Visualized

Diagram of layers in a Capacitor Tailwind Next.js Ionic app

The above is a live screenshot of an React app built with Next.js that is using Ionic Framework and Tailwind for the UI experience, and Capacitor to natively deploy that app to iOS and provide access to any Native APIs the app uses.

There are a lot of projects working in tandem to provide the full experience here. To visualize it, I’ve tried to overlay the different layers and how they correspond to each project in this diagram above.

We can see that Capacitor is concerned with the entire app and device layer of the app, Next.js is concerned with the entire web/React app our code and UI is running in, then Ionic handles the “platform UI” including navigation toolbar (including system title and toolbar buttons) as well as the bottom tabs.

Finally, Tailwind is used to then style and customize the content of each page, which is where the bulk of the app-specific styling will occur.

Mobile UI and Native Runtime

If your experience building with web technologies is primarily for desktop or responsive sites, you might not be familiar with mobile-focused libraries Ionic Framework and Capacitor.

Ionic Framework is a cross-platform, mobile-focused UI library for the web. It provides ~100 components that implement platform UI standards across iOS and Android. Things like toolbars, navigation/transitions, tabs, dialog windows, and more. The big draw is those components work on the web and work in frameworks like React, Angular, Vue, or plain HTML/CSS/JS.

Ionic Framework is highly popular and powers upwards of 15% of apps in the app store.

Historically, Ionic Framework would be paired with a project like Cordova which provided the native iOS and Android building and runtime capabilities. However, most new Ionic Framework apps use Capacitor for this part of the stack.

Capacitor is a project built by the team behind Ionic Framework focused on the native side of a web-focused mobile app.

Capacitor provides a plugin layer and runtime that runs web apps natively on iOS, Android, Desktop, and Web, and provides full access to device APIs and features (including extending the web environment by writing additional native Swift/Java code).

As such, any popular web technologies and libraries can be used to build mobile apps with Capacitor, and then deploy the same apps with the same code to the web and desktop.

And, to top it all off, Capacitor was just rated the second highest in satisfaction among popular Mobile & Desktop Tools on the State of JS 2020 Survey! If your last experience with this mobile development approach was with Cordova, we think you’ll find Capacitor to be a big improvement.

Introducing the Next.js + Tailwind CSS + Ionic Framework + Capacitor Starter

Now that you have a sense for how these technologies all work together to make it easy for web developers to build mobile apps, let’s take a look at a real demo and starter project (GitHub repo):

Next.js Tailwind Ionic Capacitor Starter

Let’s take a look at the main Feed page (seen above in the screenshot) for an example of how the different technologies in use work together:

import {
  IonPage,
  IonHeader,
  IonToolbar,
  IonTitle,
  IonButtons,
  IonButton,
  IonIcon,
  IonContent,
} from '@ionic/react';
import { useState } from 'react';
import { notificationsOutline } from 'ionicons/icons';
import Notifications from './Notifications';

import Card from '../ui/Card';
import { getHomeItems } from '../../store/selectors';
import Store from '../../store';

const FeedCard = ({ title, type, text, author, authorAvatar, image }) => (
  <Card className="my-4 mx-auto">
    <div>
      <img className="rounded-t-xl h-32 w-full object-cover" src={image} />
    </div>
    <div className="px-4 py-4 bg-white rounded-b-xl dark:bg-gray-900">
      <h4 className="font-bold py-0 text-s text-gray-400 dark:text-gray-500 uppercase">
        {type}
      </h4>
      <h2 className="font-bold text-2xl text-gray-800 dark:text-gray-100">
        {title}
      </h2>
      <p className="sm:text-sm text-s text-gray-500 mr-1 my-3 dark:text-gray-400">
        {text}
      </p>
      <div className="flex items-center space-x-4">
        <img src={authorAvatar} className="rounded-full w-10 h-10" />
        <h3 className="text-gray-500 dark:text-gray-200 m-l-8 text-sm font-medium">
          {author}
        </h3>
      </div>
    </div>
  </Card>
);

const Feed = () => {
  const homeItems = Store.useState(getHomeItems);
  const [showNotifications, setShowNotifications] = useState(false);

  return (
    <IonPage>
      <IonHeader>
        <IonToolbar>
          <IonTitle>Feed</IonTitle>
          <IonButtons slot="end">
            <IonButton onClick={() => setShowNotifications(true)}>
              <IonIcon icon={notificationsOutline} />
            </IonButton>
          </IonButtons>
        </IonToolbar>
      </IonHeader>
      <IonContent className="ion-padding" fullscreen>
        <IonHeader collapse="condense">
          <IonToolbar>
            <IonTitle size="large">Feed</IonTitle>
          </IonToolbar>
        </IonHeader>
        <Notifications
          open={showNotifications}
          onDidDismiss={() => setShowNotifications(false)}
        />
        {homeItems.map((i, index) => (
          <FeedCard {...i} key={index} />
        ))}
      </IonContent>
    </IonPage>
  );
};

export default Feed;

As we can see, we use Ionic Framework controls (IonPage, IonHeader, IonContent, IonToolbar, etc) for the structure of the page (these controls implement iOS and Android platform-specific styles and navigation/transition behavior), then we use Tailwind for the page content that is where our custom design lives (which will tend to be in IonContent).

If we look at another page that is just a simple list, we see that we don’t use Tailwind at all, because the user would expect this page to be a standard iOS/Android list and toggle button (code here):

Settings Page Example

So, we tend to use Tailwind more for pages with a lot of custom design and assets. That’s by design. Generally when building a native mobile app, we want to use platform conventions as much as possible, especially for experience and performance-sensitive elements like Lists, Toolbars, Tabs, and Form inputs. However, for the Feed page, which has a pretty custom UI experience, we end up getting a lot of mileage out of Tailwind.

So, in general, the way to think about when to lean more on Ionic Framework and when to lean on Tailwind is when your UI experience will heavily use typical mobile UI elements (prefer Ionic components) or when it will be more custom (prefer Tailwind).

Finally, this starter also comes with a few small opinions around folder structure and state management. For state management, the library pullstate is used which is a simple yet powerful state management library with a hooks-based API (I wrote more about it here). If want to use something else, removing it is easy.

Deploying to iOS and Android

The app can be easily deployed to iOS and Android using Capacitor and its local CLI tools. After running npm install, you’ll have the npx cap command available, which enables a native development workflow:

To add an iOS or Android native project:

npx cap add ios
npx cap add android

Then, to build the Next.js app, export it, and copy it to the native projects:

npm run build
npm run export
npx cap copy

This command is needed every time the built output changes. However, you can enable livereload during development (see the README for more info).

Then, you can launch Xcode and/or Android Studio to build and run the native project:

npx cap open ios
npx cap open android

Next steps

If you’ve been interested in building mobile apps using popular web dev projects like Next.js or Tailwind, hopefully this starter provides inspiration and a solid foundation for building your next app using web technologies. It’s worth mentioning this exact same approach can be used with other UI libraries (like material, bootstrap, or your own!).

When you’re ready, dig into the starter project, follow the Capacitor and Ionic Framework docs, and get building!

Continue reading ->

Announcing Capacitor 3.0 Beta

Today I’m thrilled to announce that Capacitor 3 is ready for public beta! The Capacitor team is looking forward to hearing feedback on it from our developer community. 💖

A New Milestone

Last year we announced Capacitor 2, which brought important platform updates to the ecosystem such as Swift 5 and AndroidX. Since then, we’ve been delighted to see massive adoption in the community. Usage has more than doubled this year alone! It’s clear that developers who use Capacitor share our commitment to staying modern and providing the very best app experiences.

For 3.0, we are focusing our attention on these areas of improvement:

  • Community involvement
  • Adaptability
  • First-class APIs
  • Developer experience and productivity

Capacitor 3 is more than just the “next version” of Capacitor. It is a crucial milestone for the project: the core team has grown significantly since the 2.0 release and now has the bandwidth and experience necessary to dedicate more time to the community, more time for prototyping and innovation, more time for stability and maintenance, and more time to deliver on Capacitor’s promise of making it easy to build web apps that run natively on iOS, Android, and the Web.

Continue reading ->

Security Advisory CVE-2020-6506

Vulnerability detail: https://nvd.nist.gov/vuln/detail/CVE-2020-6506

A universal cross-site scripting security vulnerability was discovered in Android WebView that allows cross-origin iframes or links to execute arbitrary JavaScript in the top-level document. For an attack to be successful, a user would need to navigate to a website or iframe containing malicious code within WebView. The vulnerability has been fixed in Android WebView as of version 83.0.4103.106, however users must update their Android WebView from the Google Play Store.

For users of the outdated Android WebView, Capacitor apps loading third party content in iframes or directly in the web view are only vulnerable if precautions are not taken. We are currently exploring a solution to help mitigate the vulnerability. We recommend taking the following precautions if your application may be vulnerable:

Capacitor configuration (capacitor.config.json)

The best line of defense is to only allow first-party trusted content in the web view.

  • Do not modify the server.url to a third party or untrusted website.
  • Do not add untrusted websites to server.allowNavigation.

It is recommended that apps behaving as a web browser use the Browser plugin.

HTML iframes

Care should be taken when using iframes in your application. If you need to include an iframe in your page, make sure the content is from a trusted source.

The vulnerability can be mitigated by using the sandbox attribute. Using an empty value is the most restrictive configuration that will prevent an attack.

<iframe sandbox="" src="https://example.com/risky.html"></iframe>

Caution: tokens can be added to the sandbox attribute to lift certain restrictions, however some configurations will cause an app to remain vulnerable, such as “allow-popups allow-top-navigation allow-scripts”.

Further Information

More information about the vulnerability can be found at https://bugs.chromium.org/p/chromium/issues/detail?id=1083819 and https://alesandroortiz.com/articles/uxss-android-webview-cve-2020-6506/. Many thanks to Alesandro Ortiz for bringing this to our attention.

Continue reading ->

Integrating CapacitorJS Plugins with NuxtJS

The following is a guest blog post from Dan Pastori of Server Side Up. Server Side Up is an online community that shares tutorials and resources about Vuejs, Laravel, Wordpress, and more recently have started creating resources on how to deliver native apps with Capacitor.

Using CapacitorJS with NuxtJS is a perfect combination. NuxtJS allows you to develop powerful, modern fronteneds using VueJS. Combined with CapacitorJS, you can take those modern frontends, compilie them to mobile, and deploy to the platform of your choice.

Working with CapacitorJS, the power of native device features is there for you to integrate into your application. These features include GPS, Haptics, Camera, Filesystem, etc. When I structure a NuxtJS frontend, I like to design it in a way that allows me to re-use important modules through-out components, pages, and layouts.

Continue reading ->

Turn your Angular App Native

Angular is used to build seriously large applications, but did you know you can target iOS and Android (and PWA) from your codebase without many changes to your existing Angular app?

With Capacitor, any Angular app can be turned into an iOS and Android app with full access to native APIs and OS controls. Capacitor does this by providing a native runtime for web apps with a bridge to communicate from the web app to the native layer, along with many Native APIs and access to hundreds more from the community.

Perhaps a surprise to many Angular developers, Angular is already used to power a significant number of app store apps (at least 15%). This is because Ionic Framework has been widely used as a mobile UI framework for Angular since the AngularJS days and many Cordova apps used Angular over the years.

Continue reading ->

How Capacitor Works

Capacitor is a cross-platform native runtime for Web Native apps.

At a high level, that means Capacitor takes a modern web app, and then packages it up to run on iOS, Android, and PWA with access to native platform features and OS-level controls.

Capacitor then acts as the runtime facilitating communication between the web app and the underlying OS.

Let’s dig in and explore how Capacitor works under the hood.

Continue reading ->

Native React Apps Without React Native

In the React world, the primary way to build native iOS and Android apps has been React Native. Created by Facebook in 2015, React Native enables developers to use their React skills to build iOS and Android apps using platform native UI elements. React Native is popular and widely used, and it’s a great solution for many teams.

However, React Native comes with a number of tradeoffs. First, it requires developers to build in a React Native specific way, using views/JSX for each platform, and using libraries that support react-native (as opposed to most React libraries that support react-dom). But perhaps most importantly, React Native is not a web environment, so it’s not possible for teams to take their web-based React apps and libraries to deploy native apps.

The net effect is that it’s not possible to take, say, a Material-UI React web app, and deploy it natively to the Apple App Store or Google Play Store with React Native.

To do that, we need to take a look at Capacitor – a native runtime for cross-platform web apps, including any and all React web apps.

Continue reading ->

Announcing Capacitor 2.0

Today we are excited to announce Capacitor 2.0!

Capacitor 2.0 offers some key platform updates as well as security and bug fixes. These include:

  • Swift 5 and Xcode 11+ support
  • Android 10 (SDK 29) and AndroidX support
  • Bug fixes and usability improvements to 23+ core plugins
  • Support for generating splash screens and icons

We documented the whole update and talked about what’s next for Capacitor over on the Ionic blog.

Check it out:

https://ionicframework.com/blog/announcing-capacitor-2-0/

Continue reading ->

Announcing Capacitor 1.0

Today I’m thrilled to announce the 1.0 release of Capacitor, Ionic’s new Native API Container that makes it easy to build web apps that run on iOS, Android, and the web as Progressive Web Apps—with full access to native functionality on each platform.

We documented this momentous occasion over on the Ionic blog, complete with a comparison to Cordova and where Capacitor is headed from here.

Take a look: https://ionicframework.com/blog/announcing-capacitor-1-0/.

Continue reading ->

Get our newsletter

Never spam. Only the good stuff.