Building an AI-Powered Web Application with Bubble

I had the opportunity to work on an web application powered by ChatGPT during an internship over the summer. I was tasked with setting up the core functionality for a product called Jobquest, a multi-shot AI SaaS tool that aims to score a candidates resume given a job description to see how well the resume would do during an ATS screening during the application process. The rebuild was primarily to see if no-code tools could be used for rapid prototyping and testing of components to quickly push new features and gain insights into what works and what doesn’t.

Reverse Engineering the Codebase

My first task to take the existing codebase written in Python and reverse engineering the code to find the exact workflows involved with the product. To keep track of everything, I neatly organized the discrete components of the system in a Jupyter Notebook. This also served as a sort of prompt debugger, a way to test different prompts for the AI in order to get the desired results.

Learning Bubble

Bubble is a no-code tool that aims to make the process of building web applications fast and easy by eliminating the need for coding. They offer an free Getting Started With Bubble course that teaches you the core systems of the platform that include:

  • Setting up styles and reusable component
  • Building workflows for interactivity and processing
  • Creating datatypes and privacy rules
  • Interacting with the database
  • Navigating between different pages

However, Bubble does have its limitations and quirks. I came across a couple of these while building my app and want to highlight how I worked around them.

Local Processing of Data

One of the limitations with a no-code platform like Bubble is the fact that sometimes it can make local processing of data a little tedious or impossible. Tasks such as processing JSON data becomes very difficult to do without some kind of script to help you. Luckily, Bubble offers an API Connector plugin that allows you to make API requests to other remote services. This allowed me to setup a Python server to perform data processing that couldn’t be done in Bubble directly.

The server was a simple REST API written in Python using the Flask library and hosted on the platform PythonAnywhere. I chose PythonAnywhere over an alternative like AWS to make the hosting both cheaper and to avoid using services that give me more computational resources than I need. I used an iterative process of first implementing a route on the local script, launching the local server, and testing the functionality using Postman (an API platform for building and using APIs.) Once I had tested the new functionality locally, I’d update the hosted server and hook it up to Bubble.

Asynchronous Processing on Lists

When building a Bubble application, you can choose to run code on either the client or the server. “Server” here refers to Bubble’s own backend server that exists for every application you create. The “client” refers to the user’s device.

Bubble allows you to create “API Workflows” which run on the backend, which involve making a backend API call from within the app. These workflows can be really useful for data-intensive tasks and allow you to run them on single objects or lists of objects.

In order to improve performance, Bubble tries to run workflows asynchronously whenever possible. For example, say you define a workflow that has 10 steps where Step 5 involves running a backend workflow in Bubble. That workflow may execute Step 5 before executing the steps before it. This can cause issues if Step 5 is accessing data from the database that hasn’t been created yet. A bigger issue that I faced was that Bubble kept skipping over items in a list because it runs the backend workflow asynchronously on the list items itself. I assume this is because the database is accessed at the same time leading to concurrency issues. The more annoying part of this asynchronous feature is that you can’t turn it off.

A work around for this is setting up a “Recursive Workflow” instead of a backend workflow on a list. This took me a bit of digging around to figure out, but if you send a list to the backend and have a workflow setup that keeps track of which index in the list you’re at (like a for-loop), it will force Bubble to process the list synchronously and ensure no items are skipped over.

Results and Findings

Using Bubble, it took me 2 man-weeks to implement about 70% of the application. The functionality included:

  • Importing and analyzing a resume
  • Importing and analyzing a job description
  • Calculating a job match score for a given resume and job description pair
  • Using AI to auto-customize the resume to fit a given job description
  • Implementing a dashboard, user sign up and login functionality

I was also able to implement a brand new feature - generating a LinkedIn summary - within a day. In contrast, the previous team took 18 man-months to implement the entire application using traditional coding tools. This serves as a testament to the capability of no-code tools for rapid prototyping and efficient feature implementation.