Estipad 1.2
It’s been almost two years since I launched Estipad and well over a year since the last release. Without going into too much detail: progress stagnated while I focused on client work, then due to the pandemic (wife is a key worker, so I stayed at home with the kids).
Because I neglected Estipad for so long, it only had:
- 22 sign ups
- ~40 estimates created
- almost 1 paid customer (added credit card but the first payment failed)
I reached out to a few users to find out more about their experience and what I could do better. Unfortunately, I didn’t hear back from anyone.
From now on, I’m going to focus a lot more on developing the product and talking to users. Recently I’ve been working on some improvements to increase sign-ups. Read on to find out more about those changes.
No more “try before signing up”
Previously, you could try Estipad without signing up. I was proud of this feature, and I thought it was an excellent idea to let users try the product before they sign up. Now, I’m not so sure about it. I think getting a person to sign up makes them more invested. Without signing-up, it’s easy to forget about it and never return when you need it.
I’ve introduced a standard (14-day) free trial, which requires users to create an account. That way, I have the email addresses and can reach out. For example, to do onboarding.
Planless trial
Before v1.2, you needed to pick a subscription plan to start your trial. You didn’t have to enter your payment details, but because of how Stripe subscriptions work, you needed to choose a plan.
It added unnecessary friction to the sign-up process. The user had to stop and think which plan to choose, and that could be enough for them to click away to another tab (I know I’ve done this).
Another problem with this approach was that my Stripe account was polluted with non-customers. All trials, even ones that didn’t convert, are subscriptions in Stripe. I’d rather keep trials and subscriptions separate. In my eyes, a subscription begins when the user enters their card details and becomes a paying customer.
That’s the way it works now. When a user first signs up, I don’t create any Stripe entries for them. The trial is handled within the app, and only when they sign up for a paid plan, a Stripe customer and subscription are created for them.
Updated annual pricing
Before, I showed the annual subscription price as an amount you’ll pay every year. For example, a monthly Solo subscription cost $9, while an annual one — $79. The savings were not immediately apparent.
I’ve updated the pricing page so that the annual plans show the cost per month — it’s much easier to see the savings compared to monthly plans.
Other improvements
Better subscription management
I’ve improved billing and subscription management. It’s now easier to:
- cancel and reinstate your subscription.
- add, edit and remove your payment card
HTTP/2
I’ve switched on HTTP/2 in nginx. Minor configuration change but some significant benefits. However, to truly utilise HTTP/2 I’ll need to make some other changes. More on it below.
Gulp
I use preprocessors for both CSS (Less) and JS (CoffeeScript). I run a gulp task locally that compiles Less and CoffeeScript to plain CSS and JS. Initially, I committed the compiled files to Git, and they were deployed with everything else.
However, having the compiled files in the repository makes no sense. Every time you change a source file, you also have to commit the compiled output. Concatenated, and minified output doesn’t diff very well, either. So it was time to change it.
I updated my Ansible roles to install gulp on target servers and compile the Less and CoffeeScript sources during deployment. I removed the output files from the repo and added them to .gitignore
. It’s an overall much cleaner process.
Of course, concatenating and minifying JS and CSS when using HTTP/2 is not necessary and may hurt performance so I will undo it in a future release.
Bug fixes
One bug that annoyed me enormously affected text fields on a task tile (task title, estimate and long description). Because tasks are draggable, some mouse events on the fields were “swallowed” by the drag events. For example, you couldn’t move the caret (by clicking within a field) or select text. The fix was to make the task non-draggable when the user hovers over a text field:
input.addEventListener('mouseover', function() {
$(input).closest('.task').attr('draggable', false);
});input.addEventListener('mouseout', function() {
$(input).closest('.task').attr('draggable', true);
});
Roadmap
I’m planning two releases by the end of September. My goal is to make smaller but more regular updates.
v1.3
Another feature release:
- ability to delete an account
- ability to archive projects
- bug fixes
v1.4
Maintenance release:
- upgrade Django from 2 to 3
- (if time allows) remove CSS and JS concatenation and minimisation
v1.5 and beyond
A few times, I wanted to make changes to an estimate but also keep the original one. I think there are two scenarios here:
- You have a similar project to estimate.
- Project requirements change.
In the first scenario, it would make sense to clone the estimate. In the second, estimate revisions might be a better solution. I’ll expand on this in a future post.
What features would you like to see in Estipad? Comment below!