Accelerate App Creation with Angular, Firestore and Firebase

In this blog post series, we will explore how to leverage Angular and Firebase tools to quickly and cost-effectively create a relatively small web application. Although the application we will be developing has no business implications, the same methodologies can be used to build real-life business applications in a fraction of the time and cost.

Table of Contents

Application Requirements

TLDR; A web app that renders flags pinned by protests on a Google Maps view.

About a year ago, Yair Dickmann, who used to be my manager at Granot, published a post on his blog where he asked for help with an application that does the following:

  • lightbulb_outlineA view with a map where visitors can see all the flags pinned by protests.
  • lightbulb_outlineA view with the same map, where visitors can see the flags that were pinned in the last hour (live-map).
  • lightbulb_outlineThese views should get updated upon new flags being added.
  • lightbulb_outlineAdditionally to flags on the map, the following numbers should be presented:
  • subdirectory_arrow_rightTotal flags
  • subdirectory_arrow_rightTotal live-flags.
  • subdirectory_arrow_rightTotal unique protests.

The context of Yair’s request were protests against the Ex-Prime Minister threatening Israeli democracy. In those days Israel faced a high incidence of Coronavirus cases, which led to lockdowns and prevented many people from going out to demonstrate.

Although the context of his request might not be relevant anymore (luckily, the majority of voters voted against corruption and the destruction of democracy), I am now looking for a job and thought it could be a fun activity to develop such a little application in the meantime.

Objectives

The final result of this work is available at vdemo.kessler.tech, the code is available on GitHub, in this series of posts, we will go through the following steps:

Let’s start with software architecture.

Software Architecture

The software architecture should cover the following topics:

  • control_pointFunctional requirements – the behavioural parts of our software.
  • control_pointNon-functional requirements –  the quality requirements, such as device compatibility, accessibility, etc.
  • control_pointInterface definition – the APIs expected from our software.
  • control_pointData model definition – a design of the application data and its relations.
  • control_pointHigh-level graphic design.

Functional Requirements

The functional requirements were described earlier in the introduction, let’s repeat them in a slightly different way:

  • spaWhen a visitor loads the app, they should see a map with all flags ever pinned.
  • spaThe visitor should be able to navigate between live flags, my flags, and all flags.
  • spaThe visitor should be able to choose a flag and pin it on the map.
  • spaThe visitor should be able to see the following usage statistics:
  • subdirectory_arrow_right Total flags,
  • subdirectory_arrow_rightTotal live flags,
  • subdirectory_arrow_rightTotal unique protests.

Non-Functional Requirements

There are not many non-functional requirements in this app, it’s not commercial software, and it is not intended to reach high traffic, the only things to consider as non-functional requirements are as follows:

  • spaThe app should be accessible through the internet.
  • spaThe design should be compatible with mobile devices.
  • spaA user should be authenticated, either with email or in any other way, the idea is that we will want to count the number of unique protesters.
  • spaA user can pin one flag within an hour – so we can tell the actual number of live flags.

Interface Definition

Given that we don’t need to do much about rendering the map (we will be using Google Maps API), our software concerns are only users and flags. The following are APIs expected from our software:

Flags API
  • spapostFlag(id, userId, flagLocation, flagOptions, timestamp)
  • spaupdateFlag(id, flagLocation, flagOptions, timestamp)
  • spagetAllFlags()
  • spagetLiveFlags()
  • spagetUserFlags(userId)
Users API

The only purpose for authenticating users is to produce a map with users’ flags, and to count the number of unique users, having that in mind, the following should provide us with the Users API interfaces:

  • spasignInAnonymously(id, timestamp)
  • spasignUpWithEmailAndPassword(id, email, password, passwordConfirmation, timestamp)
  • spasignInWithEmailAndPassowrd(id, email, password, timestamp)
  • spasignOut()
  • spagetUserId()

The user interface also contains sign in / up with email and password, the reason we need it is that signInAnonymously can only track flags the user pinned from the current device. If the user wants to pin flags from different devices, and they want to track all of their flags, they must sign up with credentials.

Data Model Definition

  • spaUser(id!, email?, password?, createdAt, lastLoggedIn).
  • spaFlag(id!, userId!, location!, icon!, createdAt, lastModified).

Data Relations Diagram

data diagram
Data diagram

High-level Design

As said earlier, there is no reason to distribute our software into many tiers, since it’s not expected to get high traffic. Additionally, there are only two domains of responsibility, users and flags which can easily be dealt with in a 3 or 2-tier architecture. So before going into the detailed design, let’s assume an architecture of 3 tiers,

  • GUI Client
  • Mid-level API
  • and Database

Our high-level design should look like this:

High-level design

For the architecture this should be enough, next, we’ll go into lower-level details of our implementation.

chevron_left
chevron_right

Join the conversation

comment 2 comments

Leave a comment

Your email address will not be published. Required fields are marked *

Comment
Name
Email
Website