January 4, 2022
  • Engineering
  • Capacitor
  • Ionic

Building the EAS 2021 Conference App

Matt Netkow

The second annual Enterprise App Summit was a roaring success! Thanks to all our speakers and sponsors from the Ionic community who attended.

For this year’s summit, we developed a cross-platform conference application for attendees which included information about each speaker, an event schedule with a description of each session, and even a swag giveaway for registered attendees!

Built with Ionic technology including Live Updates, Capacitor 3, and Ionic’s own UI framework Ionic 6, this app is designed to be updated quickly to bring the latest information to event participants, and provide a seamless experience across any device.

Although the conference is over, this app serves as a reference for any developer looking to build a conference app for their events using Ionic technology.

Download the app on your device to check it out:

Or, you can watch this short fireside chat where I discuss the app’s highlights:

Read on to get a behind-the-scenes look into how we designed, built, and shipped the app.

Meet the Team Behind the App

The EAS 2021 app was built by a team of three members of the Ionic team. They worked closely with the larger EAS conference planning team to get the content updated and deployed. Ben Sperry, Ionic co-founder and chief design officer, designed the app. Liam DeBeasi, Ionic Framework engineer, designed and developed the front-end. Matt Netkow, head of product marketing and developer advocate developed the native components and built the CI/CD processes.

We all have multiple projects to juggle at any given moment, so building this app couldn’t be a full-time effort and needed to be done asynchronously. That said, creating awesome cross-platform apps is kinda our thing, so we weren’t too worried.

The Development Process

We agreed on a simple process. Ben created a conference app design in Figma that we could all reference when building the app.

I really enjoy Figma since it’s easy for a developer to download image assets right from the tool. You can clearly see the CSS, color values (#1B4DFF for EAS blue), dimensions, and other properties. Figma also allows you to leave a comment on any part of the design which helps communicate questions or concerns throughout the process.

After Ben drafted the design, Liam and I began building the app. Liam wrote a majority of the app including creating each page and adding design details, and I worked on native features like push and local notifications, storage, and app management tasks like CI/CD and app store releases.

App Architecture

UI: Ionic 6 and Angular 13
Ionic 6 was in release candidate (RC) status at the time. We thought it would be great to take it for a spin. Ionic apps work well with any web framework, so we decided on Angular.

Native runtime: Capacitor 3
Since we planned on building a web app before deploying it to mobile, we needed a powerful runtime tool that produces native Android and iOS projects. In addition to tooling, Capacitor offers core plugin APIs (camera, geolocation, haptics) that run on the web, Android, and iOS.

Native features powered by Capacitor
We wanted to take advantage of mobile device features since we were building a mobile app. We implemented push notifications powered by Firebase to send messages to attendees throughout the event and local notifications to set reminders five minutes before talks began. Finally, the storage plugin was used to save the user’s response to the push notifications permissions prompt (following good UX, we only want to ask the user once if we can send push notifications to them).

Though we didn’t use the push notifications feature during the event, we wanted to be sure it was built to use for future events.

App data: JSON
All conference data such as speaker bios, agenda items, and more and images were stored within the app. For the next iteration, we might use a content management system (CMS) to handle the content, but this approach not only made development faster, it automatically gave us offline support since nothing had to be loaded over the network. When updates were required, we managed the data remotely through Appflow’s Live Updates feature.

CI/CD powered by Appflow and Vercel
Even with a small team, it’s important to set up a continuous integration/delivery pipeline. We’re big fans of Vercel at Ionic, so we hosted the web app version with their platform. Each push to the main branch triggered a production Angular build deployed to https://eas21.ionic.io. Appflow, Ionic’s mobile CI/CD service, was used to build the Android and iOS versions then deploy those binaries to the app stores.

App Features

We added a lot of features to the app to give attendees the information they needed when they needed it. To build in this functionality, we relied on a few different technologies to get the job done.

Native Mobile Design Powered by Ionic 6

The app’s UI is powered by Ionic 6, the latest version of our 100+ UI component toolkit. With Ionic’s adaptive styling feature, apps look and feel native to the user as all UI components automatically switch to the design based on the device platform (Cupertino on iOS and Material Design on Android).

Some specific UI flourishes that Ionic 6 includes are the bottom sheet component, new modal styles (especially in dark mode), and header and footer fading effects.

There’s also everyone’s favorite feature: dark mode support! In this app, we use the prefers-color-scheme CSS media query which hooks into the system setting of the user’s device and applies the specified dark theme colors when dark mode is enabled:

/* variables.scss */
@media (prefers-color-scheme: dark) {
  body {
    --ion-color-dark: #f4f5f8;
    --ion-color-dark-rgb: 244,245,248;
    --ion-color-dark-contrast: #000000;
    --ion-color-dark-contrast-rgb: 0,0,0;
    --ion-color-dark-shade: #d7d8da;
    --ion-color-dark-tint: #f5f6f9;

   /* snip - other colors */
Dark Mode

Push Notifications Powered by Capacitor and Firebase

Since the conference featured live online talks, we wanted a way to remind attendees that the conference and various talks were about to start and allow users to enable timed reminders that trigger a few minutes before their favorite talk began.

To send remote notifications to users, we used Capacitor’s Push Notifications plugin coupled with Firebase’s cloud messaging functionality. While push notifications can be complex to implement, Capacitor makes it easy with a step-by-step configuration guide that outlines how to configure the native projects. Then, it’s just a matter of adding different listener methods that fire when registration is successful, a notification is received, or similar events occur:

// push-notification.service.ts
export class PushNotificationService  {
  async promptPushRegistration() {
    // Request permission to use push notifications
    // iOS will prompt user and return if they granted permission or not
    // Android will just grant without prompting
    PushNotifications.requestPermissions().then(result => {
      if (result.receive === 'granted') {
        // Register with Apple / Google to receive push via APNS/FCM
      } else {
        // Show some error
        console.log("error: " + result.receive);

    // Triggers when device is registered with Firebase
    // once this happens, device can receive push notifications
    PushNotifications.addListener('registration', (token: Token) => {
      console.log("push registration success");

    PushNotifications.addListener('registrationError', (error: any) => {
      console.log('Error on registration: ' + JSON.stringify(error));

    // Device has received a push notification
      (notification: PushNotificationSchema) => {
        console.log('Push received: ' + JSON.stringify(notification));

On iOS, when prompting the user for permission, the default “‘EAS 21’ would like to send you notifications” message is used. Unlike other permission prompts, there is no way to customize this. Before requesting permission, the best practice is to first explain the value the user receives by accepting the permission request.

We decided on: “Get reminders when the event is about to start, talk recordings have been published, and more!”

To display this message, we decided to use the new Ionic 6 sheet modal aka “bottom sheet.” Built into the existing ion-modal component, this popular effect is used to display a modal that doesn’t take up the entire screen. Often, as we did here, it overlays on top of one fourth to one half of the screen:

The initialBreakpoint and breakpoints are key. The breakpoints property accepts an array which states each breakpoint that the sheet can snap to when swiped. A breakpoints property of [0, 0.5, 1] would indicate that the sheet can be swiped to show 0% of the modal, 50% of the modal, and 100% of the modal. When the modal is swiped to 0%, the modal will be automatically dismissed. The initialBreakpoint property is required so that the sheet modal knows which breakpoint to start at when presenting.

const modal = await this.modalController.create({
  component: PermissionsModalComponent,
  initialBreakpoint: 1,
  breakpoints: [0, 1],
  cssClass: 'permissions-modal'

return await modal.present();

Here’s the sheet modal and push notification prompt on iOS in action:

Ionic 6 Bottom Sheet Prompt

Local Notifications Powered by Capacitor

While push notifications are sent from a server (Firebase in this case), local notifications are stored on the device and do not need an internet connection. In the EAS app, users can set reminders for the talks they are interested in that trigger five minutes before the talk begins.

When the user taps the “Remind Me” button on an agenda item page, the reminder is registered with the mobile OS internal clock then a toast message (using the ion-toast component) is displayed, confirming that the reminder has been set:

async setReminder(agendaItem: AgendaItem) {
  await this.talkReminderService.scheduleReminder(agendaItem);

  // set reminder for 5 minutes before!
  const toast = await this.toastController.create({
    message: "Reminder set for 5 minutes before the talk begins",
    duration: 2000,
    color: "primary"

  await toast.present();
Local Notification Reminder

The scheduleReminder function uses the user-selected talk’s scheduled start time to create a JavaScript Date object that is set five minutes in the past. That date is fed into the local notification’s schedule property:

// talk-reminder.service.ts
// Set reminder 5 minutes before the talk begins
async scheduleReminder(agendaItem: AgendaItem) {
  // Format examples: 09:00 AM, 12:00 PM, 14:30 PM
  const timeSlice = agendaItem.startTime.substring(0, 5);
  const reminderDate = new Date(`December 8, 2021 ${timeSlice}:00`);
  reminderDate.setMinutes(reminderDate.getMinutes() - 5);

  // Schedule reminder
  await LocalNotifications.schedule({
    notifications: [
        id: 1,
        title: "Talk starting soon!",
        body: agendaItem.title,
        schedule: { at: reminderDate },
        extra: {
          agendaId: agendaItem.id

That’s all it takes to set up local notifications. As a bonus, we add a listener that fires when the user taps on the notification. The app is opened, then the user is taken directly to the talk’s agenda page using the Angular router:

 // Navigate the user to the talk they wanted to be reminded about
 async configure() {
   LocalNotifications.addListener("localNotificationActionPerformed", (notification => {
     this.ngZone.run(() => {

Shipping the App with Appflow

Building and shipping a mobile app to the app stores involves much more than writing code. Tasks like app certificate generation and management, building native binaries, and managing app store releases can take significant time. Managing iOS and Android builds can be especially tedious, so we set up CI/CD processes with Appflow, Ionic’s mobile CI/CD service. With Appflow, we could automate the Android and iOS builds of EAS 2021 then deploy the binaries to the app stores.

After a one-time configuration that includes uploading security certificates, Appflow makes it simple to build native apps. Make a code commit to your repository, choose the target platform and type of build (development, ad-hoc, production, etc.) then check a box if you want the binary to be uploaded to the app store.

This saved us a bunch of time, gave our team one centralized place to manage the build/release process, and ensured we always knew the app’s latest development progress.

Live Updates Powered by Appflow

The Enterprise App Summit featured talks from tech leaders across various industries who use Ionic to build mission-critical apps. As it goes with a conference like this, the schedule changed often: new speakers were added and a talk or two was shifted to a different time to accommodate availability changes.

In order to keep the app up to date with the latest information, we used Appflow’s Live Updates functionality. With Live Updates, you can deploy updates instantly to users without a new app store release, seamlessly in the background. Updates can include HTML, CSS, JavaScript, images, and other files (just not native code, which does require a new app store submission).

New speaker headshot to add? Talk title changed? Bug identified in testing? No problem. After making a new code commit to any repository branch, you log into Appflow and create a new web build. Once the build is complete, app users receive the update in the background and the app is refreshed with the latest version automatically.

Final Thoughts

I had a blast working with Ben, Liam, and the EAS planning team to build the EAS 2021 app. If I had to pick my favorite app feature, it would definitely be its overall performance and incredibly fast startup time. As you can see, you barely have any time to view the splash screen:

Ionic App Launch Time

Web Native apps have come a long way in recent years and so it’s an exciting time to be a web developer building for all platforms. Ionic 6 is available now. Download it today and start building your own slick cross-platform apps!

Matt Netkow