I don’t talk about this often, but I use a team of caregivers to help with all of my daily personal care needs. I’m fortunate enough to be on a program in the state of Mississippi that provides me (and my brother, Matt) with a certain amount of hours of personal care assistance per day. The program requires that I find my own caregivers, which is great in one sense because I have control of who works with me. But it also means I bare the burden of recruiting.

Recruiting personal care assistants (PCAs) is tough. There has been a nationwide caregiver shortage since at least the 2020 pandemic, if not before. Add to that the fact that the economy has seen rising inflation and increased prices for just about everything. In response, many hospitals and healthcare agencies have risen the pay rate for CNAs and PCAs,1 some going as far as to offer sign on bonuses.

Unfortunately, the program I’m on doesn’t pay its workers very much. I’m not going to provide numbers here but for the area I live in, the hourly rate is below average, anecdotally speaking.2 The program is also somewhat slow to onboard people, which means it can take a week or more from when we find someone until they can start—and another two weeks until they get their first paycheck.

All of this means hiring a caregiver is challenging for me and and my brother. We typically approach this problem by paying for an ad on Indeed and processing applications to find people to interview and ultimately hire. This is a high turnover industry so we’re typically going through at least one round of hiring every year.

Despite the caregiver shortage we get a lot of applications, albeit many low quality ones. Processing these is its own problem and it’s one that, as developers, we could actually solve.

In which we reinvent the wheel because other wheels weren’t quite right

After years of using form providers like Google Forms (Matt) and Wufoo (me), we started using a self-hosted form made with WordPress and Gravity Forms. I was tired of paying so much for Wufoo and didn’t like reading Google Forms entries in a big spreadsheet. So the Gravity Forms setup was meant to save us money and give us more control.

It worked well enough but viewing Gravity Forms entries in the backend of WordPress left such a sour taste in my mouth that I finally got sick of it. And as full-featured as Gravity Forms is, posting new job forms proved to be tedious work. Here’s a short list of my grievances with the Gravity Forms setup:

  • Everything about it was slow
  • Viewing entries was slow
  • In some spots, leaving form instructions meant typing HTML into a tiny box.
  • Did I mention it was slow.

Finally, I’d had enough. Surely two professional web developers could do better. We could make a home-cooked app, just for us. So like developers are wont to do, we threw out all the perfectly adequate ready-made solutions and set out to build our own.

Boring is best

We turned to tried and true tech for this project:

  • PHP (Fat Free Framework a small one we’re both familiar with)
  • HTML forms
  • Classless CSS (awsm, but looks like that repo went private)
  • As little JavaScript as possible
  • SQLite
  • A basic VPS
  • Postmark for transactional email

The goal here was to build something that would require little maintenance, be fast, and make reviewing applications easy.

Because of these choices, we were able to build the app in a weekend, with another weekend for fixes and enhancements.

Job ads and application forms

For privacy reasons, I’m not going to link to the site here. It’s not hard to find though. But it’s not super interesting. It’s mostly just description of the job and what we’re looking for in a PCA.

The homepage shouldn’t be hit much but, if it is, visitors will see our current hiring status.

Screenshot of the homepage. It indicates that we are currently hiring and briefly explains who we are.

Click through to the job ad/description shows details about the job. Here’s a partial screenshot of an ad we’re running at the time of this writing.

Partial screenshot of the job description. It tells who we are and lists the shifts we’re looking to cover and describes some basic info about the job, such as the pay rate (redacted), and the program that provides the job, the Mississippi Department of Rehabilitation Services

The ad contains a few callouts to “Apply Now” which sends visitors to the main part of the app, the application form. Most people will land directly on this form because they are coming from our ad on Indeed.

For this page, we coded up an HTML form. The awsm CSS stylesheet has pretty good form styling. It looks something like this:

Screenshot showing a few basic text fields (name, email, phone) and a radio button question about a valid driver’s license.

Screenshot shows two text areas asking about previous experience and professional references.

There are a few more questions, a resume upload, then a submit button. Applications get submitted and saved to a SQLite database.

Matt and I get an email notification of the application and the applicant gets a confirmation email containing a copy of their responses.

Reviewing applications

Now the fun part. Each job we post has an ID associated with it. That lets us sort applications into what we call “campaigns.” Our admin area presents a list of campaigns. Clicking through to one of those shows a table of applications.

A table showing applications. Personal details have been redacted. Columns are Status, Notes, Name, Email, City, Date

This is a simple table view. It provides high-level info, most importantly the status. Matt and I will log in and review applications, marking the ones that we’d like to contact for an interview.

As an aside, I can see how the status “Nope” can come off as a little harsh. But look, I didn’t set out to be a PCA recruiter. It’s just something I have to do. I use a little humor to cope with it sometimes. This app isn’t for public consumption so the only audience the admin area targets is me and Matt. Applicants never see their status.

Clicking through to an application gives us a view of all the responses, plus a few editable fields like Status and contact info.

Screenshot of a single application, Test Person, with a status of Unreviewed (in a dropdown) and a few fake responses.

We also have the ability to leave internal notes on applications. We use for recording how an interview went or reasoning behind rejecting an application.

Screenshot of the bottom of an application showing a textarea where a note can be left.

Homemade is a feature

There really isn’t anything interesting about the architecture of the application I spent a whole article writing about. It performs a fairly simple task that I suspect many systems perform similarly—and probably do it better.

But ours it does it in the exact way we want. That’s the magic part. If we want to change it, we can. If we want it to stay the same for years, we can keep it that way. This is the best kept secret about being a developer—making your own stuff, just for you (okay it’s a poorly kept secret because developers are always blogging about their stuff).

It never gets old.


  1. A Certified Nursing Assistant (CNA) is a caregiver who has had a certain amount of training and has a license. For the program I’m on, PCAs can have a CNA license, but it’s not required. CNA’s typically make more than PCAs, generally speaking (but the program I’m on pays the same either way). 
  2. I think PCAs are underpaid as it is. They often don’t get the same work benefits that other jobs in the health industry do. But that’s a topic for another day.