Skip to content

plutomi/plutomi

Repository files navigation

Plutomi

Plutomi is a multi-tenant applicant tracking system that streamlines your entire application process with automated workflows at any scale.

infra

Motivation

Having worked at a company that needed to recruit thousands of contractors every month, improving our acquisition flow at that scale became a challenge. Many processes had to be done manually because there just wasn't an API available for it. We often hit limits and had to work around them with a myriad of webhooks, queues, and batch jobs to keep things running smoothly. It would have benefited us to have an open platform to contribute to and build upon and this project is my attempt to do just that.

Summary

You can create applications which people can apply to. An application can be anything from a job, a location for a delivery company, or a program like a summer camp.

In these applications, you can create stages which are individual steps that need to be completed by your applicants. You can add questions and setup automatic move rules that determine where applicants go next depending on their responses or after a certain time period.

An application for a delivery company might look like this:

New York City

Stages:

  1. Questionnaire - Collect basic information of an applicant. If an applicant does not complete this stage in 30 days, move them to the Waiting List.
  2. Waiting List - An idle pool of applicants
  3. Document Upload - Collect an applicant's license
  4. Final Review - Manually review an applicant's license for compliance
  5. Ready to Drive - Applicants that have completed your application

Prerequisites

Infra

Plutomi is deployed to AWS using CDK. A couple of resources are created like a Fargate service which runs the web app (NextJS) and api (Rust with Axum) in a private subnet as well as a NAT instance using fck-nat for outbound traffic. We use SES for sending emails and have an event processing pipeline to handle things like opens, clicks, bounces, and custom app events like totp.requested or invite.sent. We use Lambda to process events and they are written in Rust with Cargo Lambda. We use Cloudflare for DNS, CDN, WAF and other goodies - make sure to add a Cache Rule to ignore /api routes.

For the database, we are using MongoDB on Atlas where we store everything in one collection. We write small documents and index a relatedTo attribute that is shared across all items. For most queries, we can get an item and all of the items it is related to without using $lookup. You can check this video for a demonstration of this technique.

Logging is handled by Axiom but this isn't required. Do note that we disabled CloudWatch logging in production due to cost reasons.

Running Locally

The following will start the API and the web app in development mode:

$ scripts/run.sh

You can also run either individually:

$ scripts/run.sh --stack <web|api>

The script also has hot reloading for both so you can make changes and see them reflected immediately once you change and save a file. Update the .env in packages/<api|web>for any environment variables needed.

Deploying

To deploy to AWS, make sure you have configured SSO correctly. Update the AWS_PROFILE variable in deploy.sh to match the profile names you want to use. Update the subdomain you want to use for sending emails in configureEmails.ts.

Change directories into packages/aws, install dependencies, and set up the environment-specific .env files and modify the values as needed.

$ cd packages/aws
$ npm install
$ cp .env.sample .env.development
$ cp .env.sample .env.staging
$ cp .env.sample .env.production

Once that's done, you can go back to the root and deploy using scripts/deploy.sh <development|staging|production>.

After running the deploy script, most of your environment will be setup but you'll need to add a few records to your DNS provider. For a custom domain on the load balancer, make sure to validate your ACM certificate. For SES, your dashboard should look something like this with the records you need to add:

SES DNS Records

Also, make sure to setup DMARC. This is a TXT record with the name _dmarc.yourMAILFROMdomain.com and value v=DMARC1; p=none; rua=mailto:you@adomainwhereyoucanreceiveemails.com See this link for more information.

In MongoDB, make sure to whitelist the IP address of the NAT instance which you can find in the EC2 console. We will eventually migrate over to use PrivateLink.

License

This project is licensed under the Apache 2.0 license. Here is a TLDR.

Contributing & Contributors

To make a contribution, submit a pull request into the main branch. You will be asked to sign a Contributor License Agreement for your PR. You'll only have to do this once.

Thanks goes to these wonderful people who contributed!

Jose Valerio
Jose Valerio

💻 🚇 🚧
praguru14
praguru14

💻 🚧
Jose Valerio
Jose Valerio

💻 🚧 🐛
Jeremy Trenchard
Jeremy Trenchard

💻
CodingRubix
CodingRubix

💻
jlittlewood-scottlogic
jlittlewood-scottlogic

💻 🎨

This project follows the all-contributors specification. Contributions of any kind welcome!

Questions

Open an issue! Or DM me on Twitter or email jose@plutomi.com