My Just F*ing Ship It Project

4 min read.

Interview Coach logo

Link to the repo

Last month, I decided to participate in the Women Make Just F*ing ship it challenge. Because the goal was to have a fully-made project by the end of the month, I figured this would be the perfect push to go through the entire ideation, development, and deployment process (I’m sure we can all relate to having a graveyard of Github repos for unfinished projects).

It’s application season, so I decided to create a bot that can help users prep for interviews. For this project, I used a simple flask server via Python, PostgreSQL, and Twilio. I’m a huge fan of how easy it is to create logic-based conversations using Twilio’s Autopilot and thought this would be the perfect project to use it for. I deployed the app on Heroku (my favorite service for quickly launching an app).

Development

First I set up the server and connected it to the database. The two main models used are for the questions and categories.

commit

__init__.py

from flask import Flask
from flask_admin import Admin

from config import DATABASE_URL
from .db import db

def create_app():
    app = Flask(__name__)
    app.config['FLASK_ADMIN_SWATCH'] = 'paper'
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    app.config['SQLALCHEMY_DATABASE_URI'] = DATABASE_URL

    admin = Admin(name = "Interview Coach", template_mode = 'bootstrap3')

    admin.init_app(app)
    db.init_app(app)

    with app.app_context():
        from .models import Category, Question
        db.create_all()

    return app

models.py

from uuid import uuid4

from .db import db

class Base(db.Model):
    __abstract__ = True

    id = db.Column(db.String, primary_key = True, default = lambda: uuid4().hex)
    created_on = db.Column(db.DateTime, default=db.func.now())
    updated_on = db.Column(db.DateTime, onupdate=db.func.now())
    
    def to_dict(self):
        """Converts object to dictionary"""
        return {k: v for k, v in self.__dict__.items() if k[0] != '_'}


class Category(Base):
    """Category model for the different types of interview questions"""
    __tablename__ = 'categories'

    category = db.Column(db.String, unique = True)
    description = db.Column(db.Text)

class Question(Base):
    """Question model for storing information about interview questions"""
    __tablename__ = 'questions'

    question = db.Column(db.String)
    category_id = db.Column(db.String, db.ForeignKey('categories.id'))

The next step was to build in the conversation logic.

  1. User initiates the conversation by texting something like “Practice” or “I want to practice”
  2. The bot walks the user through selecting an interview question category (e.g. personal, behavioral, technical) and the amount of questions
  3. The bot calls the user to start the interview. After asking randomly selected questions with the specified category, the bot stores the user’s responses for further analysis
  4. When the conversation is done, the bot hangs up and sends a text message with feedback on talking speed, response length, and the amount of filler words. Then the user receives a picture of a word cloud of the most used words.

Lastly, I added in a password protected admin panel to CRUD data for the application.

Sign in page Sign in page

Model views for categories and questions Categories admin page Questions admin page

And voila, now we have an Interview Coach bot!

One of the hardest parts about building this application was transferring the state of the conversation between the sms conversation, phone interview, and sms feedback. I didn’t want to store these details in the database, because this data seemed temporary (after the conversation is over, the data wouldn’t be needed in the future). To solve this, I used Twilio Sync as a datastore to hold information like the the category and number of questions. I used the user’s phone number as the distinct key and set the sync document to auto delete after an hour.

Lessons Learned

The biggest lesson was in learning how to be okay with releasing a minimum viable product (MVP). I originally had a laundry list of features that I wanted to incorporate, and overall, I felt extremely confident in my ability to code up each and every one of them. However, the goal was to get this project done in a month, and I didn’t want my want for perfection to hurt my need for completion. So, I had to be honest with myself and pick the few features that were 100% required for me to call this project a success. It was hard but definitely worth it in the end.

Secondly, this was the first time I’ve completed the full project lifecycle on a personal project. I came up with an idea, mapped out the features, developed and tested the application, got user feedback, created a website, and launched a fully finished product. I have a new appreciation for how applications are built, and I feel like I have a better understanding of how each phase impacts each other.

What’s Next?

Next up, I hope to integrate SendGrid to send the user the list of questions asked and their responses via email. I also want to add an analytics tool like Segment or Mixpanel to track activity to see the types and quantities of questions asked and how often a person uses the app. Stay tuned for updates, and in the meantime, you can check out the bot here.