Get your SaaS business up and running with Djaoapp in less than an hour


The goal of a SaaS business is to start providing a service to customers and accepting payments as soon as possible, thanks to Djaoapp you can start doing that in 3 simple steps:

  1. Connecting your Stripe account to Djaoapp
  2. Creating and configuring subscription plans
  3. Customizing the look of Djaoapp pages to match the look of your brand
  4. (Optional) Integrating your SaaS website hosted elsewhere with Djaoapp

Connecting a Stripe account to Djaoapp

Once you’ve logged in to your newly created account, you end up on a dummy landing page.

Implementing a checkout workflow with Vue.js using DjaoDjin API

DjaoDjin, besides various SaaS related functionality, contains a flexible and powerful checkout feature. It supports paying for multiple subscription plans, charging customers for multiple subscription periods in advance and even paying for the product on behalf of the users who are going to use it. We are going to use it to implement a typical checkout workflow on the frontend.

Displaying cart contents

First, let’s create a Django View to serve an HTML template which is going to be used by Vue.

  # saas/views/ ... class CheckoutView(TemplateView): """ A checkout view """ template_name = 'saas/billing/checkout.html' ...…

How to Create File Download Links in Django

In order to create a download link, we need to create a Django view that would serve the files:

  # import mimetypes ... def download_file(request): # fill these variables with real values fl_path = ‘/file/path' filename = ‘downloaded_file_name.extension’ fl = open(fl_path, 'r’) mime_type, _ = mimetypes.guess_type(fl_path) response = HttpResponse(fl, content_type=mime_type) response['Content-Disposition'] = "attachment; filename=%s" % filename return response ...  

After that add a line to urlpatterns in which references the view.

  # ... path(‘<str:filepath>/‘, views.download_file) ... </str:filepath> 

So, all the magic is done by including a…

Improving the UI of a dashboard


The original design has been doing the job for some time, but over the time some of the customers experienced issues with certain parts of the UI. Furthermore, we had ideas of our own of what could be improved. This is the list of issues that we ended up with:

  • The overall user interface could be more elegant and professional
  • The website is hard to use on large screens
  • There is no efficient way to switch between organizations (a user can be associated with multiple organizations)

Over the course of this post I’ll be solving these problems,…

JavaScript, Django and PostgreSQL timezone handling

Please have a look at the first part, which covers date, time and time zone basics in detail. DjaoDjin caters to micro-SaaS products. These are specialized and local products. As an example, A1Ceus targets compliance with New York State professional certification requirements. Usually the teams behind those websites are small (1-3 people) with a pulse on the daily business numbers. Reporting graphs in UTC did not cut it. Questions kept pilling up in the customer support inbox about discrepancies between what those micro-SaaS entrepreneurs were experiencing and what the reports charts were saying.…

Working with time in Python

How time is measured?

Time is usually measured by earth rotation or by astronomical observations. There are a lot of standards which specify how this should be done exactly: GMT, UT, TAI, UTC. In this post we will focus on UTC because of its widespread use in computing.

What time is it now?

The answer to this question will likely be different for people who live in different countries. Various geographical areas have their own time zone and their local time is derived from it.…

How to increase the open files limit on Ubuntu

Increasing file limits might be helpful if you’re running a web server which handles a lot of concurrent connections, because every connection opens a socket and socket is a file. In my case, I needed to increase the open file limit from 1024 to 65536 to make sure that server won’t drop connections in the future. At first, I added this line to /etc/security/limits.conf:

  * - nofile 65536  

Where the first column is the user of the process, in our case wildcard * which makes this a default setting for all processes, the second…

What is the point of using NGINX in front of a Django application

Recently, a friend of mine asked me to tell him more about the rationale behind using NGINX with a Django app and how these two work together. It actually makes perfect sense for someone to raise this question: Python has a builtin web server which can render pages, serve static files on its own. So what’s the point of adding one more component to the stack?

PHP Land

When I started to learn programming, my first language was PHP. The only program I needed to run PHP scripts was Apache. My understanding back then was that Apache can serve static…

Configuring a headless Raspberry Pi

Recently, I got my hands on a brand new Raspberry Pi and was asked to make it usable. I didn’t have an HDMI monitor or keyboard, so I decided to configure it as a headless station. I don’t have an Ethernet cable at home but I have a Wi-Fi router. So, the task was to prepare the Raspberry Pi with MacBook Pro (with card reader), Micro USB cable and 4GB SD card. I picked Raspbian as an OS. There are images available for download on the official site. I used Raspbian Jessie Lite, because the full version wouldn’t…

Creating a test environment for Ansible

I’ve been working with Ansible for the last several days. I’ve been testing my Ansible scripts on DigitalOcean. First, I’d create a fresh $5 droplet, run my script a couple of time against this server and soon after the tests were finished, I’d destroy the droplet. But it wouldn’t end with that, I’d often want to make a quick change in the script and test this change, but the environment is already different and I can’t be sure that my script will work the same on the fresh environment, so I would go and create another droplet and repeat the…