Building a Web App Using Only Python

6 minute read

What is Anvil?

I’d much rather just open a blank Ubuntu 16.04 server on DigitalOcean and pull my repository from github. I.e. work like a real developer :)

- Someone on HackerNews

When I started my most recent job, I wanted a way to track what I was accomplishing, so I decided to build Hier.

For context: I’m a bioinformatics engineer. I used to say I was a scientist, though after a PhD in bioinformatics, interning at Google as a SWE, and now working full-time as an engineer, “scientist” isn’t as accurate as it once was. Regardless, more than 95% of my programming experience is backend work in Python. I’m certainly not a web developer. I do, however, love the idea of the web. Writing software that is immediately accessible to anyone in the world with an internet connection still amazes me.

The problem is that I find web development tiresome and difficult. There are many more layers of complexity. Debugging is harder. The “right” way to solve a problem, or the “right” framework to choose, changes from year to year. UI is always a challenge when you’re as artistically underdeveloped as I am.

I settled on using a platform called Anvil to build Hier. It lets you create web apps with nothing but Python. Anvil’s features are exactly what I want, given both my background and future goals. They include:

  • Run Python in the browser (Modify your UI components directly with Python)
  • Built-in database (Backed by Postgres. Query or edit your data with a no-nonsense Python statement)
  • Built-in user authentication (Anvil handles sign-up, log-in, email verification, password reset and more)

(Note: I borrowed these feature descriptions from the Anvil website.)


This writeup is from a first-time user’s perspective. I’ve been using Anvil since June. Undoubtedly, if I wrote this after my 10th app, I would have very different things to say. But these are a few things you might expect to encounter if you decide to give Anvil a try.

I plan on writing a Part II further down the road to share whether my perceptions change at all.


There are a lot of things I like about Anvil, and this certainly isn’t an exhaustive list.

  • When you’re building fairly simple create/read/update/delete (CRUD) apps, which Anvil seems primarily designed for, it’s an extremely fast iteration process. You can make the MVP of a live site in a few hours.
  • Data Tables. These are Anvil’s take on a database. I love, love, love the Data Tables.
    • It’s great to constantly have easy access to view the app’s data.
    • Being able to easily update the tables manually is also great. If I want to add a row that has a date column, a little calendar appears so I can select a date. I don’t know how other high-level website builders work, but this certainly beats firing up an ipython shell and working with Django’s ORM to edit data, which was my previous workflow with Heroku.
    • Relationships between tables has also been made interactive and intuitive.
  • Users, authentication, sessions, etc. I don’t like dealing with any of these things; they’re not interesting to me. When I first started toying around with web development, I assumed that it would be a single line of Python to add all of this functionality to Flask. Every other website on the internet has this functionality; it’s a solved problem, right? After reading through hundreds (thousands?) of lines of Flask documentation and tutorials on the subject (and rather poorly implementing them myself), I’ve realized that they’re complicated to get perfect so that the UI/UX is flawless. Anvil basically offers that one-line solution I dreamed about 5 years ago, and it’s everything I wanted it to be.
    • Anvil also has nice Stripe integration for handling payments. This is one of the most important features to me, because messing up payment handling while you’re learning seems like a terrible experience.
  • The default aesthetics are solid. It helps that I’m partial to Material Design, true. But in general it’s nice that if I toss up a few additional components in the editor I’m going to spend a majority of my time making sure my backend logic is solid, as opposed to being frustrated by how ugly things look.
  • The Uplink. This allows users to run code on servers besides Anvil’s. It could be useful if you have CPU-intensive code or a touchy build environment. I’ve only used this feature briefly, but it seems perfect for doing something like setting up a bioinformatics application backend.
  • Deployment. I’m writing this feature last because it’s become so simple I haven’t had to think about it yet. Specify the git commit you want to deploy, and it’s “published”.


Anvil also has some areas where it could still use improvement. (What doesn’t, right?)

  • Some actions are slow. Clicking “Run” to test your app takes longer than it could. At one point, it was clocking in at >11s. Thankfully, this is just during development and doesn’t affect users.
  • The community still feels small. I was the 160th person to like a post on the forum, according to the badge I received. This is a downside because a lot of seemingly basic questions haven’t been asked and answered yet.
  • Certain patterns that seem like they should work don’t.
    • One example is deeply nesting RepeatPanels, which is an Anvil component. I tried putting one inside of another (inside another, etc.) to make my date tree, and it seemed to work. That is, until I tried to use the editor. While the structure worked perfectly on the site, it made the editor so slow it was impossible to use. I had to delete the components and start over using a hand-coded method.
    • In a second attempt to make the date tree, I wrote a nice OrderedDict-like class that would retain the order of dates but also allow for fast lookups. Again, I got it working, was happy with it, and then tried to run my app. I should have tested earlier, because I immediately ran into a SerializationError. I haven’t dug into the specifics yet, but unsurprisingly not all valid python is valid javascript. This “con” is partially my fault for not checking sooner, but it’s still a limitation.
  • There’s no debugger. There’s not much to say here. I’m okay with print(vars(my_date_obj)), but having a full debugger would be a real improvement.
  • I wish there was a $10/mo plan. This is one is a personal opinion, but $54/mo (paid monthly) for an unproven hobby app is a lot for a new grad. I’d love to pay $10 to remove Anvil’s branding so I can share a non-embarrassing link.


Although I stick by my wish for a $10/mo plan, I want to qualify it by saying that I think the $54 plan is actually a good value. The plan comes with unlimited apps; let’s assume you take the bare minimum advantage of that and build two small sites. If I wasn’t using Anvil, I’d be on Heroku. Initially, Heroku’s $7/mo plan seems much cheaper. But Heroku’s postgres database only comes with 10,000 rows for free. That’s easy enough to outgrow, so add an extra $9/mo. I refuse to go back to editing my database through Django’s ORM, so I’d pay out for Adminium, which is another $10/mo. I could probably get away with rolling my own authentication, but I want registration to be frictionless. It looks like that’s another $12/mo. If you think that’s a silly thing to pay for, you can replace that charge with the Mailgun addon, or Cron to Go. Anvil handles both of those things as well. And we’d have to double our pricing for two apps! Suddenly our Heroku bill is $76/mo, and Anvil isn’t looking quite so expensive.


Try Anvil!

Despite certain shortcomings, my experience building Hier with Anvil has been fantastic. Again, I’m biased because I’m a Python developer who doesn’t particularly care about dealing with web dev issues. But it’s probably fair to assume that a lot of other people also fall into that category.

If that sounds like you, feel free to ping me about any questions you might have. I’d be more than happy to share more in-depth details!

Looking forward to seeing what you build!