The Coffee Shop Kiosk

The Coffee Shop Kiosk

A kiosk application for a coffee shop built using Point of Sale SDK

When I joined the Developers team at Square, the first thing I did was build an application that uses our APIs. Every new engineer on the team does this (you can read about my colleague’s example Android app here) so that we can walk in our customers’ shoes. It’s become a great tool to reinforce feedback from developers when building real world applications. For my project, I chose to build a customer-facing kiosk application as we’re seeing more and more demand for this type of custom application. For the application I built I used our Point of Sale API, which leverages the iOS app-switching API to enable apps to accept in-person payments using the Square Point of Sale app. We’ve also provided a Point of Sale SDK, which is a thin wrapper around our API that makes it incredibly fast and easy to get up and running.

The Coffee Shop is a customer-facing kiosk app that allows customers to order and pay for their drinks at a fictional coffee shop.

The Coffee ShopThe Coffee Shop

The advantage of a kiosk is that customers can place their own orders, leaving baristas free to focus on making drinks and engaging with their customers instead of running the register. Because this is a customer-facing app, the interface needs to be both simple and fast. Customers should be able to easily choose a drink, customize it, and pay.

Data Model

The Drink model defines some basic properties like name and description, as well as an array of DrinkOptionGroups.

struct Drink {
    let name: String
    let drinkDescription: String
    let image: UIImage
    let optionGroups: [DrinkOptionGroup]

When you buy a drink at a coffee shop you usually have a few choices to make:

  • What size drink do you want?

  • Do you want whipped cream?

  • What type of milk do you want?

DrinkOptionGroup is a simple struct that can be used to model each of these use cases:

struct DrinkOptionGroup {
    let name: String
    let selectionType: SelectionType
    let isRequired: Bool
    let options: [DrinkOption]

It defines a group of related options which can be applied to a drink. As an example, here’s a DrinkOptionGroup which defines the sizes that are available for a drink:

let size = DrinkOptionGroup(name: “Size”, 
                            selectionType: .single, 
                            isRequired: true, 
                            options: [
                                DrinkOption(name: “Small”, price: 100),
                                DrinkOption(name: “Medium”, price: 200),
                                DrinkOption(name: “Large”, price: 300),

I’ve added a few different sizes at various price points (in cents) and specified that the customer must choose one and only one option. You can also define a DrinkOptionGroup where multiple options can be selected:

let extras = DrinkOptionGroup(name: “Extras”, 
                              selectionType: .multiple, 
                              isRequired: false, 
                              options: [
                                  DrinkOption(name: “Turbo Shot”, price: 50),
                                  DrinkOption(name: “Whipped Cream”),

To bring it all together, here’s the drink definition for coffee:

let coffee = Drink(name: “Coffee”,
                   drinkDescription: “Smooth and balanced with subtle notes of chocolate.”,
                   image: UIImage(named: “coffee”),
                   optionGroups: [size, milk, sweetness, extras])

In this sample app several drinks are defined statically in a configuration file, but you could also imagine them being pulled from a server.

App Flow

The app has two screens which are managed by the AppFlowController class. AppFlowController is a UIViewController subclass which is responsible for displaying and transitioning between screens in the app. It’s instantiated with an array of Drinks and displays them by showing the SelectDrinkViewController:


Once the customer selects a drink, the CustomizeDrinkViewController is presented with the various options that can be used to customize it:

Customizing a drinkCustomizing a drink

Finally, when the customer taps the checkout button, AppFlowController kicks off a Point of Sale API request which transitions the customer into the Square Point of Sale app so they can pay for their drink. Once the customer completes their payment, the Square Point of Sale app automatically switches back to The Coffee Shop to take the next customer’s order.


Pro tip: Enable “Reduce Motion” in iOS Settings in order to improve the app-switching experience

func checkOut(with order: DrinkOrder) {
    do {
        let request = try makePointOfSaleAPIRequest(for: order)
        try SCCAPIConnection.perform(request)
    catch {
        // Handle error

private func makePointOfSaleAPIRequest(for order: DrinkOrder) throws -> SCCAPIRequest {
    let amount = try SCCMoney(amountCents: order.price, currencyCode: CurrencyCode)
    return try SCCAPIRequest(callbackURL: CallbackURL,
                             amount: amount,
                             userInfoString: nil,
                             merchantID: nil,
                             notes: order.description,
                             customerID: nil,
                             supportedTenderTypes: .all,
                             clearsDefaultFees: false,
                             returnAutomaticallyAfterPayment: true)

Production apps are often much more complex than this simple example. By using Square’s APIs you don’t need to understand or worry about the complexity of accepting payments. Instead, you can focus on building a great experience for your customers.

All of the code for this app is available on Github and documentation is available on our developer portal. Feel free to clone the repo and try building a kiosk like The Coffee Shop for yourself!

We believe that commerce is changing, and that change comes with big, new problems to solve. Come join us at Square as we build a commerce platform that helps developers empower sellers to start, run and grow their businesses.

Table Of Contents