Made with Angular

Personal Cookbook

I designed and developed this application to collect, organize, and make preparing my favorite meals easier.

About this Project

I really enjoy cooking dinner with my wife every night. We are nowhere near expert chefs; We rely heavily on following recipes to create anything enjoyable to eat!

I discover recipes from around the internet: Youtube, cooking blogs, and other recipe apps. Many of the recipes I find are great and worth saving; however, when it comes time to cook, re-finding them is inconvenient.

I designed and developed this application to collect, organize, and make preparing my favorite meals easier!


  • Edit and add recipes from multiple devices without touching code
  • Customize recipes for the way that my wife and I cook
  • Consolidate my favorite recipes from around the web
  • Create a shopping list from selected recipes
The recipe details page has tabs for ingredients, preparation instructions, and cooking steps.

Key Features

Saving recipes to a database

To make my cookbook accessible and editable from any device, I save all the recipe data in a database.

For developers, there are many great database options nowadays. For this project, I decided to use Firebase as my database solution.

Firebase Realtime database

Firebase is maintained by Google and provides a suite of backend tools for web applications. One of their tools, Realtime Database, was the perfect fit for this project. A Realtime Database is cloud-hosted, synced across all clients in realtime, and also makes data available offline.
In the Firebase console, I'm able to view all the data for saved recipes. The recipe IDs are generated automatically when initially uploaded.


Any Realtime Database can be used as a REST API. This allows me to easily interact with the the recipe data via HTTPS requests.

For example, I retrieve all recipes in the database by sending a GET request to this URL:

Using Firebase's Realtime Database saved me a lot of development time because I didn’t have to write a custom API to interact with my data.

User Authentication

Along with Firebase's built-in API, I am also able to take advantage of their robust authentication tools. By setting up a single authenticated user in Firebase, I ensure that only I can edit the recipe data when logged into the application.

I built this application in a way that all users are able to interact with the adding and editing features; however, only my changes are saved permanently to Firebase. All local actions done by guests are stored in local memory and cleared when the page is refreshed.

Auto Login and Logout

I implemented an auto login feature which looks for user data in local storage when the application is initially loaded. If user data is found, the user is automatically logged into the cookbook and able to make edits. This feature is helpful because if the application is refreshed, the user doesn’t have to log back in via the Admin Login form.

To help security, Firebase can be configured to have user sessions. When a user’s session runs out, their attempts to edit data are no longer valid. When a user is initially logged in, I set a timer for the length of their session. When the timer expires, the application’s state changes to reflect the user being un-authenticated.


Checkout the User Service

Recipe Editing

I developed an intuitive editing form so I can efficiently add recipes from around the web. The form is able to create, delete, and edit every bit of recipe information in the database. There is never a need for me to touch the database directly, all the interaction is done through the editing form.
The recipe edit form makes all database information editable.

Angular Reactive Forms

One of the main reasons I decided to use Angular to build this project is the framework’s approach to forms. Angular reactive forms provide direct access to the underlying recipe object model retrieved from the database. When I click the save button in the form, the data object is already composed and ready to be sent to the database to be saved.


Form Validation

There is a variety of form validation implemented in the editing form. For example, if you add a preparation step, but do not fill out the information, the save button at the top of the form is disabled. This prevents incomplete data being sent to the database.

Viewing the Preparation Steps

The Prep tab is a unique feature, designed specifically for my style of cooking. In the Prep tab, I’m able to view all the steps to prepare food before starting to cook. Personally, I believe this feature makes cooking less stressful by preventing multi-tasking which can lead to food burning and other mishaps.
The preparation tab shows all steps needed to be completed before cooking.

Preparing a Shopping List

The shopping list compiles the ingredients of selected recipes. In each recipe details page, I can select Add to List to add all the ingredients to the shopping list. If multiple recipe ingredients are added to the list and there is a repeated ingredient, they are combined.

I can also select multiple recipes on the home page and add all ingredients to the shopping list at one time!
Multiple recipes can be compiled into one shopping list.

Features Backlog

This project is still a work in progress. In the coming months, these are some of the features I plan to implement.

Backlog (13)

Skeleton loading

  • UX
  • Design

Improve edit form UI

  • Design

Re-factor moving functions in form

  • Development

Add better error handling when recipe is not found in edit form

  • UX

Add Firebase ID instead of temporary ID

  • Defect

Update ingredient badge as ingredients are crossed off the list

  • UX

Delete ingredients on page navigation way from shopping list

  • UX

Clicking anywhere in the ingredient row should check it off

  • UX

Implement unit testing

  • Testing

Improved ingredient selection

  • Development

Add custom ingredients to shopping list

  • UX

Store shopping list in Firebase so it saves

  • Development

Make dialog accessible from screen readers

  • UX

In Progress (1)

Add background pattern

  • Design
  • Angular
  • Firebase
  • NgRx
  • CSS