My First Micro-SaaS, Building the MVP
In this post, I will share how I built the MVP for https://hostifi.net, a UniFi controller hosting platform.
The SaaS Stack
If you read how I chose the tech stack for HostiFi, then you already know about how I struggled with Django early on and eventually gave up on it. I ended up getting started with WordPress and a combination of Easy Digital Downloads plugins.
In particular, I purchased Recurring Payments and Stripe
Between these plugins, WordPress, and the Startuply theme I had purchased from ThemeForest, I had all the basic SaaS functions taken care of — landing page, subscriptions, checkout, billing, user account management.
After purchasing a server subscription, the user was taken to a blank PHP dashboard page, where I could begin building a custom interface.
The Server Creation Script
It was time to build the actual product, the UniFi server creation part.
But there was a problem. I had already written the entire server building script in Python weeks beforehand because I was expecting to integrate it into Django later.
The Python script made API calls to Vultr, the VPS provider I had chosen to use. It would create a server, SSH into it, and run the commands to install UniFi and create an admin account for the user who signed up. Then it would need to provide a link to the server and UniFi credentials to the user’s dashboard.
Integrating WordPress and Python
So now I had to figure out how to integrate that Python script that I had written with the WordPress website so that a server could be built after a user purchased a subscription.
At first, I was looking at using Zapier. Easy Digital Downloads makes a plugin for it. It had the ability to receive a hook when a user signed up, and I could pass that information to trigger the Python script.
It seemed like a perfect solution at first, but after looking into Zapier’s pricing plan, for under $50/month, the Zaps only run once every 15 minutes.
That was too long for a customer to wait for their server, so I tried to figure out how I could make my own integration.
I was looking at the WordPress database trying to reverse engineer how it all worked, and I had an idea.
I noticed that a row is created in the table “wp_edd_subscriptions” when a user signs up.
I created my own custom table and named it “servers”.
Then I wrote some code in Python to read the subscriptions and servers tables from the database. The script would save the rows to a list and then compare the two lists.
Now the Python script was able to determine two scenarios:
- If a server exists without a subscription, then it needs to be canceled
- If a subscription exists without a server, it needs to be built
I created a cronj ob to run the Python script once every minute that way it would be constantly checking for new customers.
As simple as it seems, that was really one of the biggest breakthroughs for me on the entire project!
Now I was finally able to automatically create a UniFi server after a customer signed up, and the Python script saved that server address into the server table along with the UniFi credentials, and customer identifier.
The User Dashboard
The only step left was to write the PHP user dashboard.
That part was pretty straightforward, I had a little bit of experience with writing basic PHP, and I was able to get it done with less than 100 lines of code.
The dashboard page PHP code only had to check for a couple of scenarios:
- If the user is logged in, but no servers are being built, display a message asking them to purchase a subscription
- If a server row exists but hasn’t completed yet, display a table and server status as “provisioning” along with a message saying it will take a few minutes. I also included a simple line of Javascript to hard reload the page automatically every 15 seconds until no more servers were being built
- If a server row exists and is complete, display the server info in a table
Closing thoughts
I’m not really recommending this tech stack to anyone, just sharing my experience.
I guess the theme of these posts is that you don’t have to be an incredible programmer to create value. Your customers care about how well you solve the problem that they have, not the web framework or obscure solution design choices that you made along the way.