Alphabitz — Project A

Sal Aldana
20 min readAug 31, 2022

--

The first entry in the Alphabitz series is going to be a simple arithmetic app that performs various unit conversions with a very simple UI. It’s like the calculator app idea, but with a little more real world scenarios that are useful in any project. As with every app in this series, the goal for this tutorial is to create the same app across multiple platforms to be used as a starting point for your own project 🏗.

Note: This tutorial assumes you have some basic understanding of declarative UI syntax and MVVM design patterns. If this is your first trip in app development you may want to check out some intro-level tutorials and articles for Swift, SwiftUI, Kotlin, Jetpack Compose, and Svelte on Ray Wenderlich or Stack Overflow .

All the source code for all projects can be downloaded here: Arithmetick

Research Stage 🔎

I like to break down my research into two distinct parts, the backend/data part and the frontend/ui part. For this stage I’m doing more of a high level approach to see what I need or how I’ll use certain pieces that can be shared across each platform. For this projects I came up with the following research items:

  1. For the backend logic I wanted to make sure the categories I use were available on all three platforms. Looking at some available frameworks or built in libraries I found the following 6 common categories that can be used: 📏 Length, 🌡 Temperature, ⚖️ Mass, 💧Volume, ☁️Pressure , and ⚡Energy.
  2. For the frontend I need to setup some base components (Colors, Fonts and Icons) that will give each app a similar look and “feel” while still following best practices for each platform. To keep things simple I’ll use the defaults for each platform (so SF Font/Symbols on iOS, Roboto/Material on Android and Serif/FontAwesome for Web). For the actual UI, I’ll use a simple UI with the main screen showing each option as a card, and the conversion screen just containing an input field and list for converted results.

This type of research helps me see how feasible each project would actually be and what effort would be needed on each platform. The research stage is usually a good time to come up with the app name, and for this one I settled with Arithmetick.

Project Setup 🚧

Before I start working on the designs I’ll setup my project folder both online and offline. I’ll use GitHub for hosting my project, so I create an initial project folder locally, add a simple README file to get started and sync the folder online. I use the following folder structure for these types of projects since I can also sync up Klokki to create time trackers for each folder while working.

-- arithmetick 
---- README
---- android
---- design
---- ios
---- web

Design Stage 🎨

I sort of follow the Atomic Design process mixed with the Agile Development practice to iterate through each stage until I get a product that I’m happy with. For the design process I’ll start with the lowest fidelity type of design (wireframe) and then move closer to the hi-fidelity type of design (prototype) until I have enough items to get started on development. I’m currently using Sketch for a majority of my design work.

Lo-Fidelity (Wireframe)

Since I’m a mobile first type of developer my designs also start on the mobile side. I’m also more familiar with the iOS side, so I’ll start with the iOS app wireframe and then use that as a blueprint for the other apps. The wireframe is really simple, just two screens; Category View (Main screen) and Converter View (secondary screen). For the Category View I figured showing the categories as a card like item will give me the ability to use a similar color and icon for each category that will make the apps have a more unified look. For the converter view, again keeping it simple it can be a Text Field for entering values and then a Table showing the different converted values. For web I know this may change a little since a Table with just a single value will have a lot of empty space on larger screens. For now the wireframes are done so I can move on to add a little more details to the designs.

Wireframe

Mid-Fidelity (Mockup)

To keep designs consistent with what’s available on each platform I like to start with the default UI kits for each and then add/tweak the designs where needed. Again, starting with iOS I grab the current iOS Sketch library from here and start with adding the navigation screens, which will give me my Category and Converter view templates all setup. I drop a few card shapes with SF symbol icons to get the idea of the category and modify a table view a little bit to see how the converted results would look.

iOS Mock up

This also gives me a chance to start associating some colors to each category as well, which I can replicate on each platform to make the apps have a more unified look.

I then jump over to the Android side and grab the current Material Design template here and do the same thing I did with the iOS design. This time there are some differences, like how the Cards are displayed using the Material design guidelines but it’s a fairly quick process to get the same UI layout as the iOS app.

Android mock up

The last wireframe needed is for the Web App, and since I took this mobile first approach I know I want it to have a similar layout with the cards for the category items. This area is all still a little new to me but I know I’ll use TailwindCSS for the colors so I can use this sketch library for colors and icons. I’ll just create a few simple placeholders for both small and large layouts and the mock ups are all done 👏.

Web mock up

Design Hand Off 🤝

Once I have enough “design” items in the mockups that I can use to start coding I’ll wrap up the design process with some little extras that are sometimes overlooked. First is the app icon, if you have enough to create it now then it’s a good idea to generate all the assets for the different applications. I’m not doing anything super fancy for these projects, all of the icons will include a simple icon from the Symbolicons library and the colors from my companies brand. There are all kinds of apps and kits available for generating app icons so there’s no need to list where to go to do this, what I would suggest is make sure you are generating the right types of assets for each platform (I like to use templates from Apply Pixels 😄 )

  1. iOS uses various sizes inside the Asset Catalog, some tools will generate all the sizes or just a few sizes and you will have to find/match the different sizes (since some are the same as others just with different names)
  2. Android uses an Adaptive icon so it can be dynamic for the different device types. Most tools will generate the two layers and using the Asset Studio inside Android Studio allows you to assign the layers to the App Icon.
  3. Web will need a favicon, as well as images needed for mobile browsers. Again most tools will generate all these sizes for you, just make sure to add them in the correct folder when ready.

Development Stage 🏗

Similar to the design stage, I’ll use an Atomic Design mixed with Agile Development to iterate through the development of each app. I’ll also start with the iOS App, again since it’s my stronger area and works as a blueprint for the other apps.

iOS App 📱

Minimum Requirements: Xcode 13 & Swift 5

Setting up the project is fairly simple, no need to go into details here, just make sure to choose Swift and SwiftUI as the language and framework options. In the project structure I also uncheck the iPad box, for now this will be an iPhone only type of project. I use the simulator to test frequently, so although not mentioned I would suggest building frequently to validate changes are working on a device and not just the preview windows.

Once the project is opened, one of the first things I like to do is setup my preview window to show both light and dark modes of the app. This can be done with a small tweak to the PreviewProvider on your SwiftUI view using a ForEach loop and adding the .preferredColorScheme() modifier.

Code snippet using a For Each loop with each ColorScheme and the Preferred Color Scheme modifier to create preview windows for light and dark windows
iOS Light & Dark mode previews

SwiftUI makes it easy to code the same way I design, adding a wireframe with the bare minimum and then modify from there. To start off with the category view screen I know I’m going to need a grid so to get started I use a LazyVGrid with a placeholder Text view to view the names of each category. The LazyVGrid uses a GridItem to setup the size of each column and the ForEach loop makes setting up repeating elements super easy.

Code Snippet and Preview Example of the Category Screen with just a basic setup. The Code Snippet uses a For Each loop to show just a Text view with just a sample string of each category.
iOS Wireframe for Category View

I like to use Enum’s whenever possible, it makes code easier to read and helps with making unit tests easier to write. I can setup my enum class to also provide the images and colors that each category will use. iOS also has a built in library for unit measurements, so I can include those in my enum class to ensure each category has the right units for the conversion screen. I’ll also use the SFSafeSymbols package using the Swift Package Manager since this package also makes adding SF Symbols a little easier 😃.

Code Snippet for setting up Enum class for Category Items in Swift.
iOS setup for Category Enum

One caveat here is that the Enum can’t be used in the ForEach loop on the SwiftUI side, it needs to be Identifiable which isn’t allowed on Enums. To work around this we just need to setup a class that can be used on the SwiftUI side and takes the enum as the initializer.

Code Snippet for the Category Item that can be used with SwiftUI components.
iOS Category Item for SwiftUI use

The allItems() function is useful for our SwiftUI view so now all we need to do is a small tweak to the wireframe and we have the Categories all setup with the UI components needed to show them as Cards.

Code Snippet for main Category Screen updated to use the Category Enum class.
iOS Category Screen updated with Category Enum class

Creating the cards is fairly straightforward, using a VStack as the base component will make sure everything is stacked vertically. For the top of the card I wanted to show the icon and the count of available options so those items will get wrapped in a HStack and to make the whole view looks like a card I use a combination of .overlay and .background modifiers with a RoundedRectangle and that gives me everything I need to update the main view again to now use the Card View instead of the Text view.

Code Snippet for iOS Card View layout
iOS Category Card View

With this setup all it takes is a single line change on the main view to swap the TextView with the new CategoryCardView and that’s it, the main view is pretty much setup. There are few more things that will be needed, for example wrapping the main view in a NavigationView and adding a NavigationLink to the Card View to transition to the converter view after being tapped.

Code Snippet of the Category View updated to use the new Card View in place of the Text View.
iOS Category View updated to use the Card View

Now it’s time to setup the converter view, and this is where all the hard work is going to take place 😅. In order to make the UI responsive in SwiftUI I need to use an ObservableObject that can use Published variables to trigger updates when the converted values are updated based on the input value. Using the .sink handler will also allow me to execute the conversion code when the input field is updated so the user will see converted values as they type without having to hit the enter key. As for the actual conversion logic, the process is handled with a few steps; first get the value using the selected unit, then filter list of conversion options to exclude selected unit, and lastly use the built in .converted(to: ) method in the Dimension class that will create the list of converted values.

Code Snippet for Converter View Model in Swift
iOS Converter View Model

Now it’s just a matter of hooking up the Published variables with the UI on the converter view, setup the input field to accept just numbers and setup a list view that will show the converted results. The list will also allow you to tap on any option and switch to that Unit. To make the converted results list requires adding a .onTapGesture() modifier and also adding a .contentShape(Rectangle()) makes the entire row respond to the tap.

Code Snippet for Converter View layout in SwiftUI with Preview example
iOS Converter View with Preview

At this point the app is pretty much done, but before wrapping up the iOS app there is one more step to perform, Unit Tests 👨‍🔬. For me I like to get the ViewModel to get as much coverage as possible since that’s where most of the logic for the app takes place. Following the same process as before I’ll start with testing the smaller functions and then iterate to make sure all the category items have similar tests. For now I’ll just use the default XCTestCase for Swift and just some simple XCTAssertEqual and XCTAssertFalse statements to get the results I need.

Unit Test example in Swift
iOS Unit Tests

Now the iOS project is complete, before working on building the published version of the app lets dive into the Android version.

On to the next one

Android App 🤖

Minimum Requirements: Android Studio 2021 (Chipmunk) & Kotlin 1.5. At the time of writing most of these features were marked Experimental and may change over time.

Using my iOS app as a blueprint, I already know what I need to get started with the Android side of things as well. To get started choose an Empty Compose Activity(Material 3) and choose Kotlin with minimum of API 25 (Lollipop). As with the iOS app, I use a simulator to verify and will build often while working through each step.

One of the differences for the Android platform is how the Colors and Themes are used. In order to get the colors I need I use the Material Theme Builder and export using the Jetpack Compose Theme. After dropping this into the app, I can now setup my Dark & Light Preview light previews, which is done by creating different Preview Composable and setting the useDarkTheme variable. I like to use the showBackground and showSystemUi on the Preview windows as well just to get the full preview on each type.

Code Snippet for setting up Light and Dark preview windows in Android
Android Light & Dark Mode Previews

To provide the same navigation and live data I need to add a few Compose libraries by updating the app gradle file with following dependencies to get started.

kotlin {
// ...
dependencies {
implementation 'androidx.navigation:navigation-compose:2.5.0-alpha01'
implementation "androidx.compose.runtime:runtime-livedata:1.0.5"
}
}

Now since I already know that I need a Category model that will handle all the logic for the main screen, instead of building the wireframe I can setup the actual model to use in the view. With Kotlin I can use a Enum as well and I can setup the model that uses the enum values for all my main display items.

Android Category Enum & Model

With the model setup, my wireframe can skip the step of using an array of Strings to test with and I can get my array of Category items to use with a simple Text view for now to show the title. Using the LazyVerticalGrid is experimental right now, but it’s exactly what I wanted to give the same card view so I’ll use it. Setting it up is actually pretty similar to the grid view on iOS as well.

Code Snippet for the Category View in Android and Preview example
Android Grid Wireframe

Next step is to work on the Card view for the Category item. The Material design library comes with a Card view that works in Jetpack Compose and with a mixture of Columns and Rows it’s pretty easy to get a similar layout on the Android side. For the Image resource, I’m using the painterResource option so it works with the view model and an icon resource id. I’ll come back later to add the navigation logic, just to not crowd this step with a little too much complexity right away.

Android Category Card View

Now just like the iOS app, I can go back to my Category View and by changing the Text field to the CardView will give me my Category screen all ready to go 👏

Android Category Card View and Layout

With that piece done, the next piece to work on is the Converter View. Again, since we have the iOS app to use as a blueprint I can go straight to the view model and setup all the converter logic. In Jetpack Compose the UI is made responsive by using MutableLiveData inside of the ViewModel and then use .postValue() on these variables to make the UI respond to those changes. Most of the conversion logic follows the same pattern from iOS with getting all conversion options, set the selected value and then perform the conversion for each option available. The only change I had to make was for the Unit options, seems like the built in ones on Android don’t provide all the same functionality as the iOS library. I found this library measured that works, but it didn’t have all the same units to use so I had to make a few tweaks after adding it.

Code Snippet for Android Converter View Model
Android Converter View Model

Hooking up the Converter View to the View Model requires using either a remember or observeAsState() API method on the live data variables and like the iOS app just a simple TextField for input and a LazyColumn for the result list will give me everything I need. To make the conversions perform while typing, the modifier onValueChange can be used to call the conversion logic on the TextField.

Code Snippet for Converter View layout in Android with Preview example
Android Converter View

There’s another piece that needs to be added before the Converter View can be viewed after tapping a category card, the NavigationController . The Jetpack Compose side uses a NavHost that takes the different Views that are available and the route that is used to get to that view. Using arguments in the NavController we can identify the id of the Category Card selected and then pass that selected category to the Converter View. In the MainActivity.kt first setup the NavHost and then update the main onCreate to use the updated Navigation Component. From here the navController needs to be passed down to the Card View, and in the onClick method add the navigation call with the category id passed in the arguments.

onClick = { navController.navigate(NavigationRoutes.DETAIL.name + "/${item.option.id}") }
Code Snippet for setting up the Navigation Controller in Android
Android Navigation Component

From here the Android app is pretty much ready to go. The Category screen should show all the icons and colors for each type and can navigate to the converter view. The last piece is to add a Unit Test, and again on the Android side I’ll use the default testing library. Since I’m using a ViewModel with some MutableLiveData there’s a Rule that needs to be added to the testing library in order to access the live data values. Once that’s added, writing the tests is fairly straight forward and almost the same as the iOS side again.

Code Snippet for unit tests in Android
Android Unit Tests

Alright, now with the mobile apps done it’s time for the Responsive Web App.

One more to go

Web App 🕸

Minimum Requirements: Visual Studio Code, Vite, Svelte, TypeScript and TailwindCSS.

The Web App is definitely a more “open” playground to use compared to mobile apps since there is far more variety in the frameworks that can be used. While there are some frameworks that are more widely used than others, I chose a stack that I felt worked best for my style of development coming from a mobile only background. For testing, I like to use Sizzy as a development browser since I can see both small and large screens.

  1. Vite — A newer build tool that is extremely fast and provides Hot Reloading (Live Updates)
  2. Svelte — A front end framework for building reactive components
  3. TypeScript — For the backend logic to add type safety, something I’m used to as a mobile developer
  4. TailwindCSS — A CSS Framework to make responsive classes easier to write and read.

To get started I’ll use the Vite scaffold option to setup a project using npm init vite@latest and choose the svelte-typescript option. Once the project is done, adding TailwindCSS can be done with a simple command npx svelte-add@latest tailwindcss and now the only item needed is FontAwesome for icons. For FontAwesome I like to use the local option, downloading the assets and adding the CSS link to the index.html file and now the web app base is ready to go.

Experience from the previous apps helps in letting me know some basic structure that is needed for the web app to work, so I’ll start with the navigation piece. Svelte comes with a svelte-navigator library that can be used for setting up the navigation. I’ll start out just with some simple links and empty pages to make sure it’s all setup correctly.

Web App initial Routing setup

Running the app should result in two simple pages that can be navigated between using the links on each page. Now like with the other apps, I know I need a model for the Category items, and although TypeScript does have a Enum class, it’s not exactly the same as how the other platforms work so I’ll use a exportable namespace to do all the UI exports like I did in the other apps. I’ll also add the UOM library at this point so I can use the units in my Enum class.

To build the UI, I’m going to use the DaisyUI framework which adds some extra utilities to TailwindCSS and the Notus Svelte template to take some of the work out building an entire UI from scratch. To keep the UI simple, and have a similar feel to the mobile apps I’m going to just have the main page show some simple text and a few card like shapes for each category. To handle the navigation I’ll use the built in svelte-store to keep track of the selected category, selected unit and current value entered in the input field. First I setup the card layout.

Svelte Category Card View

One of the nice parts of using Svelte is the ability to use a #each loop to create multiple category cards without having to retype all the same classes for each item.

Svelte Category Cards

With the Category items done the next piece, like with all the other apps is the Converter View. I’ll start with the ViewModel, since like the other apps I need to setup the logic for performing the conversions and getting all the results formatted for the result table. The logic still follows a very similar pattern, first get the current selected unit and the input value for that amount, get all conversion options for the selected category and then filter out the selected item from the results.

Code snippet for Converter View Model in TypeScript
TypeScript Converter View Model

Hooking up the ViewModel to the UI components is the same as the other platforms, an input field to enter a value and then a list to show the results. Since there isn’t really a default “grid” to use on the web, and since a table would end up with a lot of extra space I’m going to use a card style design instead. For the input view, in order to provide the same functionality as the mobile apps and convert the value as the user enters a value I’ll use the on:input event to call the conversion logic in the view model. For the converted list (or cards), I’ll use the Svelte store to setup a .subscribe event on the selected unit value that will let the user swap the input value with any of the conversion options. Here’s just the main pieces for each of the views

Svelte Converter Input & Converted Results
Svelte Converter View Preview

This will pretty much wrap up the Web App functionality with the mobile apps, but there are a few more items needed for a web app to be complete. Basically it’s just wrapping all this content with a Navigation Bar and Footer area that contains basic data. After these basic items are added the last piece to add is some Unit Tests for the web app, and for this I’ll use the Vitest framework. The Vitest framework uses a very easy to understand format, using describe to setup a test class and it and expect functions to explain what kind of test is being executed in each it function.

Code snippet for Unit Tests in TypeScript
TypeScript Unit Test

With the Unit Tests completed we know have 3 apps ready to be published and pushed out to the public.

Deployment Stage 🚀

Following the same pattern as before, I’ll go through the deployment options for each app, starting with the iOS App first.

iOS App Package 📦

Publishing an iOS App requires the App Store, regardless of the type of distribution that you want to use. For this app I’ll use the Ad Hoc distribution option so I can install the app on just my own specific devices. Using the Product menu choose the Archive option to start the build process. In the Archive window choose the Ad Hoc option and follow the instructions to end up with a .ipa file that can be installed to a device using the Apple Configurator app.

Android App Package 📦

Publishing an Android App is a little bit more open than the iOS side and doesn’t require having to use the Google Play store to build a Ad Hoc version of the app. To get started use the Build menu to go to Generate Signed APK and then choose the App Bundle option. The next screen will ask you to setup a keystore for the app that is needed for future updates to the package so make sure this is safely stored somewhere. Last step is to choose where to save the APK file and which version to use for the build (use the release build) and that’s it for the Android side. The app can be installed on a device manually or uploaded to the Google Play store for public distribution.

Web Package 📦

For the web app, Vite comes with scripts already setup for generating a build and to preview the build as well. Once the build script is finished the final step is to find a host for the web app. There are quite a few options available from free to commercial, depending on the needs of the project and the resources available. For this project, a simple free hosting option can be used with Vercel and using the CLI option all you need to do is run the vercel command from the project dist folder and follow the prompts to launch the app. The live preview can be found here: Arithmetick preview

Wrapping it up 🤔

Even with just a high level overview of each app, this was quite a bit to take in if you followed along for all three apps. The nice thing is this project is small enough that it can be taken in any direction now if you want to add more features to this app. Here’s a few ideas of areas that can be expanded on:

  1. More conversion options — This might require more libraries or different libraries.
  2. Ability to add favorites — Another feature that adds more navigation options, is creating a favorites screen to easily access conversions that are used often.
  3. More tests — UI tests can be added, or some automated testing from the GitHub side.

Whatever you do, I just hope this was a good starting point to help visualize some ideas you might have. I’ll continue the series with B , which is currently in pre-design stage. Stay tuned for more 😄.

--

--