Websites (And ERPNext) [Part 1]

Alain Berger
Nov 12, 2018 · 9 min read

When you’re up to your neck in alligators, it’s hard to remember that your initial objective was to drain the swamp

This famous quote seems to be a pervasive theme in my life.

The original objective was to setup a robust e-commerce website for our Hydroponic farm, where we could sell directly to our customers. I also wanted to have their accounts set up and be able to repeat their orders or provide feedback. Always part of what we wanted to accomplish, our end goal was a good, solid website. Then the reality of downloading and connecting data to an accounting software just dawned on me, and I began focusing more on which software to use, and whether it could be connected to our website. I did want e-commerce transactions visible on our backend accounting as fast as possible. I would obviously eschew SAP and their brethren. I thought about building something myself, however I am not that hardcore. Enter ERPNext.

After having spent the better part of two years implementing the software, and also learning all the nooks and crannies for Frappe framework, developing stand-alone apps for it and learning to do collaboration to the core (for Pull Requests), one thing stood out as “pending” for us:

The Website!

Leave it to the Experts! We’re experts… right?

After coding for the backend, and having a dedicated development team assembled, you would think we are experts in ERPNext! And especially on web tech, given that ERPNext runs on the web. Not really.
We can handle the backend development with consistency. We can work GitHub. But I have zero clue on how to setup a great looking website on the frappe framework.

I did some research today to clarify my options, since our website, as configured from within ERPNext, looks appalling. I will not dare show it in public.

Only a few brave souls have dared to see it.


There are several options when wanting to deploy a website from ERPNext.

Plain Vanilla ERPNext Website setup (with some coding)

We tried to setup the website with the existing tools as per the excellent tutorial by Rushabh Mehta I witnessed live in Mumbai in 2017:

This provides a basic, solid knowledge of managing data between backend and frontend. It is a robust, simple website setup.

Plaid (not Ludicrous) Website setup (extreme coding)

Spaceballs references aside, I truly think that binary thinking takes you places. This is the case when Eric Delisle from DigiThinkIt and his presentation takes center stage, when they showed their beautiful, responsive and heavily coded website. Best of all: running on the same Frappe/ERPNext server. The only “drawback” is the fact that you have to code everything yourself, but for me it means more control and the ability to customize a great looking website.

Eric Delisle — DigiThinkIt and their website built on ERPNext

For now, I shall focus on the Plaid Option and show you how to code a fully customizable page, since Rushabh does a great job of explaining ERPNext native website setup. These are the steps I followed to setup the website.

Start at The Beginning

Ideally, you need to start with a VirtualBox and a production server. You can work with a development server if you are so inclined, but for this I opted for a production server. If you already have a virtualbox ERPNext server or local version running, skip to step 2.

1. Download and Setup a production server

Download Oracle’s VirtualBox and also download a Production Image from

Import the appliance and make sure you have bridged adapter set up for the networking card, so that the virtualbox image is on the same network as your host machine. Start the server. The credentials of the virtual image are:

username: frappe
password: frappe
mysql-root-password: frappe

Do login through the console and find out the IP address:


Use that IP address to navigate to the Production Image for ERPNext. Login using:

user: Administrator
password: admin

For this example we will assume that the IP address for production image server is:

Be sure to replace this in every example with your IP address.

2. Create a new app

I usually do my coding on a Mac OSX and connect using iTerm via SSH to the virtualbox ERPNext server. This way I have more than one terminal for several maintenance tasks. Login to the ERPNext server terminal using the IP address found above:

ERPNext server ready to accept commands

Create a new application:

bench new-app [your-app-name] 

You will be asked for:

An app name, a short description, who publishes it, email of app publisher, app icon, app color, and license.

After that, you are ready to install it on the single site for ERPNext Production Image (site1.local):

bench --site site1.local install-app [your-app-name]

Restart the bench:

bench restart

3. Create Your Webpage

When you created the application, a folder was created like this:


Using either the SHH terminal connection or a Samba shared folder, navigate to it, and within it you will find the following structure:

Your application folder

Navigate (change directory) into the folder shown above, so that you are now located in:


Yes, that’s twice your-app-name! Within this folder you will see this structure:

The www folder within your application

Navigate to the www folder within your app. This is where all your HTML, CSS and other files will go. Any files you add to this folder will be publicly available on the web.

4. Let’s Play

Try browsing to your server by entering the IP address on a browser on any machine on the same network as your production image.

This is the default page shown.

Now, try to add a route or page set, and navigate to it such as:
Frappe’s default 404

This is important, because I want to make sure you witness the changes as they happen. Let’s create a test page using the nano editor:

cd /home/frappe/frappe-bench/apps/[your-app-name]/[your-app-name]/www
nano test.html

Inside the test.html file, just type:

Hello world! within test.html page

Save by pressing CTRL+X, then Y, then ENTER

In your browser, navigate again to:

And this should be your result:

Hello World Web View on ERPnext

Since the .html file was quite spartan, Frappe/ERPNext added bootstrap styling automatically to it. Let’s add some html tags to our file and see what happens.

nano /home/frappe/frappe-bench/apps/[your-app-name]/[your-app-name]/www/test.html
Add some proper html tags

Save by pressing CTRL+X, then Y, then ENTER

Let’s try it again in our browser, and the result should be:

Very basic .html display

Frappe is careful enough to add bootstrap styling if your .html page has content without the <body> tag.

If you are having any trouble, make sure you refresh your browser and if this does not help, then try clearing the cache for your site, like this:

cd /home/frappe/frappe-bench/
bench --site site1.local clear-cache

5. Beyond the basics

So far, we have established the following:

  • You can create your own, custom webpage in a specific folder for your application, available as a public web view from an ERPNext site
  • Frappe provides basic bootstrap styling or steps aside if you provide your own complete html.

Why the application?

The ideal thing about creating a website within a stand-alone application is that you can develop independently from frappe or erpnext. Every time they update their software, you can rest assured that things will run pretty smoothly, side by side. At worst, the underlying connectors or contextual functions, might change, but this is simply a matter of modifying your website’s code to work with the new versions.

Another plus to the application structure, is that you can push it to a GitHub repository and then replicate it. You can also rest assured that any change you make in the master GitHub repository for your web application can be easily pulled by your individual instances for a multi-website-update. This comes in handy for ease of updating and for security reasons too. Only the people who have control of the master repository can allow changes to be merged into it.

6. Adding scripting capability to the page

Now we can try adding scripts to our page. You do this with a .py script, which provides context. This basically is the broker of information between the backend and frontend. You name this file exactly as the .html, like this:

cd /home/frappe/frappe-bench/apps/[your-app-name]/[your-app-name]/www
Add this content to the Python file

Add the following content to the python file:

import frappedef get_context(context):
context['custom1'] = 'Custom Homepage'

Save by pressing CTRL+X, then Y, then ENTER

Now, we must edit the test.html file to include the contextual result.

nano test.html
Adding the Jinja template statement

The full html code should look like this:

<!DOCTYPE html>
Hello world!

Before we test it out, it is necessary to create the file in the same directory. This lets Python know that files in this directory are part of a package, and in its simplest form it is just an empty file.


Let’s test it!

Do a bench restart to make sure everything (the new .py files) is included when bench runs.

cd /home/frappe/frappe-bench/
bench restart

Now point your browser again to the test route and you should see this:

Excellent! We now know that every html page or template can have a related controller which provides context for the template. In other words, the python file is the controller for the html file.

So, if we want a route named /my-route , you create a template (HTML file) named my-route.htmland a controller named

Also, you may do the following: my-route.html and Frappe is quite adept at matching the hyphen in the template name with underscore in the controller name.

Now, let us show all the users in the production image.

Modify by adding the line below so the file looks like this:

import frappedef get_context(context):
context['custom1'] = 'Custom Homepage'
context['users'] = frappe.get_all('User')

Also, modify the test.html to look like this:

<!DOCTYPE html>
Hello world!</br>
Template file editing.

Before testing, make sure you run a bench restart.

The resulting page on your browser would look like this:

Python Custom message and all Users

The result is not showing the final symbol, which instead of a comma should be a right bracket ] . However, it is pretty clear that we are obtaining an array of dictionary objects with all the users in the production image and displaying it.

In similar fashion, you may run any valid Python function, and you may access/write any server data you need. We shall explore some examples in part 2. For now, we shall explore pushing our app changes to a remote repository.

5. Push changes to your repository

What we have accomplished so far is only on our local server instance. At this point, I suggest you push to a remote software source control site such as GitHub, so you may not only back up your work but also replicate your work easily when setting up multiple instances of your web page on different installations.

First, you must initiate your application directory as a Git repository

cd /home/frappe/frappe-bench/apps/[your-app-name]
git init

Then, you must add all the files in that directory with:

git add .

Now, do your first commit

git commit -m “First commit”

If you have not done so already, create a GitHub account, and if you do have one, create a new repository (without initializing with a Copy the link so you can run the command to link your local repository to the remote repository and call the remote “origin”:

git remote add origin[your-github-account]/[new-repo].git

You can now push your changes with:

git push -u upstream master --force

We shall continue this exploration in part 2…

Alain Berger

Written by

Behold! There is a lot of lettuce, basil, kale, arugula, etc. (and plenty of useful, valuable software code too!)

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade