Live Chat

We'll need to share your messages (and your email address if you're logged in) with our live chat provider, Drift. Here's their privacy policy.

If you don't want to do this, you can email us instead at


November Update
30th of November 2018

Anvil On Tour: Upcoming Events

We will be presenting at a bunch of development- and Python-related meetups over the next few months. Come and join us!

(Want us at your local meetup? Get in touch, wherever you are:

  • Nov 22nd: London, UK (London Python, pictured above)
    We had a great response at London Python, and a lot of interest afterwards. We’ve already been invited back!

  • Dec 4th: St Louis, MO, USA (STL Python)
    Stefano Menci will be leading a hands-on workshop in St Louis.

  • Jan 8th: Indianapolis, IN, USA (IndyPy)
    This is the Indianapolis pitch competition for PyCon Startup Row. Last year, we built the voting app for the competition, live on stage in London. This year, we’re giving a full-length talk.

  • Jan 10th: Frederick, MA, USA (Python Frederick)
    Meredydd Luff will be demonstrating Anvil, and talking about how it works under the hood.

  • Jan 17th: Manchester, UK (North West Python)
    Meredydd will be demonstrating Anvil, and talking about how it works under the hood.

  • Jan 29th: Sheffield, UK (Python Sheffield)
    Workshop time! Come and try Anvil yourself with friendly hands-on assistance.

  • Feb 21st: Oxford, UK (Oxford Python)
    Meredydd will be demonstrating Anvil, and talking about how it works under the hood.

  • May 3-5: Cleveland, OH, USA (PyCon)
    We’re already confirmed as sponsors for PyCon 2018 – find us in the exhibition hall, and meet up with other Anvil users.

Bring Anvil to your event

We’d love to present at your local Python, data science or development meetup – we do local or remote presentations all over the world. Drop us a line at

We can also offer help and materials if you’d like to lead an Anvil workshop yourself - just get in touch.

We hope to see you at an event soon!

September Update
26th of September 2018

Meetups, Security, Data Grids, and More

Do you attend a coding, Python or data-science meetup? Would you like Anvil to come and present there? We’re presenting at meetups across the UK, and events all over the world (including remote presentations). If you want us to stop by your event or user group, send an email to and let us know!

Meanwhile, here’s what’s new in Anvil this month:

Data Grids

Of course, this month’s big news is the release of Data Grids. It’s our most-requested feature, and a massive help to anyone working with tabular data. Check out our announcement and the Getting Started tutorial.

Enforcing secure passwords for your users

Password security is more important than ever. That’s why we’ve just introduced the “Require Secure Passwords” option in Anvil’s user authentication service.

When you select “Require Secure Passwords”, Anvil prevents your users from re-using a password that’s too short, or has already been leaked in a data breach. We can check for data breaches without revealing passwords to anyone, thanks to the k-anonymity feature from Have I Been Pwned. You can learn more about how it works in this blog post from Cloudflare.

“Require Secure Passwords” is enabled by default for all new apps, and you should turn it on for your existing apps too!


Another much-requested feature: Now, almost every component has a tooltip property. Set it to display some extra text when you hover your mouse over the component!

On-Site Installation

Did you know that you can install Anvil on your own servers? You can now get an on-site trial instance running in 10 minutes or less, easier than ever before! To learn more about running Anvil on your corporate network, or on your own cloud servers, contact us at

That’s it for this month. If you’ve got any questions, come and ask us on the Anvil user forum.

Happy coding!

Announcing Data Grids
12th of September 2018

Create interactive tables with minimal effort

If you’re writing a web app, chances are you’ll have data in tables. And at some point you’ll probably want to show your users a table of data they can page through.

Doing that in Anvil just got even easier. By popular demand, and without further ado:

Introducing the DataGrid component

Data Grids are an easy way to show data that naturally fits into rows and columns. With built-in support for paging, they can handle large numbers of rows while remaining performant.

Data Grids can be populated from any source. It’s easy to link them up to your Data Tables:

self.repeating_panel_1.items =

or you could set up some tabulated data yourself:

    self.repeating_panel_1.items = [
      {'ingredient': 'Flour', 'weight': 225, 'cost': 150},
      {'ingredient': 'Milk', 'weight': 150, 'cost': 100},
      {'ingredient': 'Eggs', 'weight': 175, 'cost': 80},
      {'ingredient': 'Butter', 'weight': 175, 'cost': 250},
      {'ingredient': 'Maple Syrup', 'weight': 250, 'cost': 300},

All of this is covered in our first Data Grid tutorial: Getting Started with Data Grids.

You can also get more advanced. For example, you can nest components inside rows of a data grid to group related data together (as described in our tutorial, Paginated Grouping with Data Grids):

You can create custom widgets that control the behaviour of the Data Grid itself. You can read how to create a search box, an add button, or a page number selector:

Data Grids are only limited by your imagination. Anything you can put together out of Anvil components, you can add to a Data Grid row. And because this is Anvil, you can write Python code to assemble Data Grids and make them behave however you like.

In the example above, we’ve built a full CRUD app in a single component! We’ve got data from a Data Table, displayed in a Data Grid, with a search box, page size selector, and widgets to add, edit, and delete rows.

Click the link to open it in the Anvil editor and have a play:

  Clone Example App

To find out more, take a look at our Data Grid tutorials:

  Read the tutorials

August Update
22nd of August 2018

SQL, T-Shirts, Embedding and more…

Are you going to PyCon UK in Cardiff next month? We’ll be there, showing people how to build full-stack web apps with nothing but Python, at our stall in the Great Hall. As always, we’ll give out a nifty Anvil T-shirt to anyone who builds an app with Anvil during the conference.

This time around, we used SciPy and Anvil to work out how many T-shirts we need to bring. The answer involved a little stats, a little SciPy, and a whole lot of Python, so I wrote it up as a blog post. Check it out: How Many T-shirts Do I Need for a Developer Conference?

Meanwhile, here’s what’s new in Anvil this month:

1. Get the Best out of Material Design

We’ve published a guide to making your apps look their best with Anvil’s Material Design theme. Change your colour palette, build a sidebar menu, or use custom CSS to control your app’s appearance.

Click here to read the guide

2. Direct SQL access to data tables

Anvil’s internal database is powered by Postgres. Now, if you’re a Dedicated Server user, you can connect directly to it and write queries with SQL! Look for the check-box in the Data Table configuration:

3. Embed your Anvil apps in other websites

We’ve made it easier to embed Anvil apps in other websites. When you open the Publish dialog, you now get a checkbox for “Embed this app in” a web page”. Enable it, then copy and paste the HTML snippet into any website to include your Anvil app there!

4. The Free Plan is bigger and better!

It’s great to see what hobby users, prototypers, educators and students have been doing with Anvil. We’ve made Anvil even better for them, by enabling more of our advanced features - like the Uplink and the Users service - on the Free plan. Check it out!

(You’ll still need to upgrade for a full Python server environment, to remove the Anvil banners, or to use your own domain name, though.)

5. Other Updates

As always, we’re making Anvil better all the time. Here are a few things you might have missed:

  • We’ve added a few more example apps to our examples page - including the time we built prototypes of two Silicon Valley startups in a couple of hours each!

  • We’ve made it easier to lay things out in our drag-and-drop designer. Look out for the dotted lines to see which container you’re dropping a container in.

  • If you’re storing encrypted App Secrets in your Anvil app, you can now enter longer, multi-line strings. (Great for private SSH keys!)

  • The modules for our Google and Facebook integrations have moved - they’re now and anvil.facebook. Don’t worry, your existing apps still work!

  • Your apps now load a little faster :)

Happy coding!

Using SciPy to Work Out How Many T-Shirts I Need for a Conference
8th of August 2018

How many T-Shirts do I take to PyCon?

When you’re marketing to developers, you go where the developers are. We make a platform for building full-stack web apps with nothing but Python, so we go to developer conferences – particularly Python ones.

Like many sponsors, we give out nifty Anvil-branded T-shirts. But there’s a twist: in order to earn a T-shirt, you’ve got to build something with Anvil. So far, it’s gone pretty well - here’s what it looked like at EuroPython last week:

Now we’re home, and preparing for PyCon UK in September, it’s time to order more shirts. The trouble is, developers come in all shapes and sizes, and the first time we ordered we were way off the mark. (Apologies to the huge number of people who wanted a Women’s Small!)

This time, we can be smarter. We’re a bootstrapped company, so we can’t just blow VC cash on unnecessary mountains of shirts – but we do want every Anvil user to go home with a T-shirt.

How can we use this data to work out how many shirts we need?

Option 1: Exact numbers.

“If last conference used 13 Men’s Medium shirts, we should bring exactly 13 to the next conference.”

This is obviously a bad idea. If even one more medium-sized man writes an app with Anvil, we’re going to run out of shirts. And feel pretty stupid about it, too.

Option 2: Double up

OK, fine, so let’s order 200% of what we expect to need. This will cause us to order 4 rather than 2 Women’s XS (probably sensible)…and 54 rather than 27 Men’s Large (not so much!). That 54th Men’s Large shirt is much less likely to be claimed than the 4th Women’s XS shirt is. It’s the law of large numbers: Larger samples average out more reliably.

Wait. I’m sure there’s a more helpful way of thinking about this than waving my hands and saying “law of large numbers”. Can we capture this insight in a statistical model?

Option 3: Be a bit smarter

Let’s imagine that every person who comes to the conference is a dice-roll. Some percentage of the time, they build an Anvil app and claim their T-shirt. What size they want is also a dice-roll: X% of the time they want a women’s Medium; Y% of the time they want a men’s Small; and so on. We can estimate how big X and Y are, because we know how many shirts we gave out at PyCon US and EuroPython, and we know how many attendees were at those conferences.

Next month, we’re sponsoring PyCon UK, with 700 attendees. How many men’s Medium-size shirts will we need? We can simulate it by rolling that die 700 times, and counting how many times it comes up “men’s Medium”.

Of course, each time we do that “roll 700 dice” procedure, we could get a different total count. This total follows a binomial distribution:

Here I’ve plotted two binomial distributions, using Anvil’s plotting tools. On the left, we’re expecting to give away about 2 shirts, but we could easily need twice that number. On the right, we’re expecting 35, but we’re unlikely to need more than 40 – we’re much more certain with larger numbers. This is the insight we had before – but now we’ve got a model, we can quantify it!

We can wrangle binomial distributions easily with SciPy. We’ll use SciPy’s ppf function to get the 95th centile of this distribution: If our model is correct, there’s a 95% probability we won’t need more shirts than this.

Let’s compute that number:

  from scipy.stats import binom
  # From 1500 attendees, we gave away 13 men’s Medium shirts
  p_mens_medium = 13 / 1500
  # For 700 attendees, there’s a 95% chance we will need no
  # more than this many men's Medium shirts:
  n_shirts_p95 = binom.ppf(0.95, 700, p_mens_medium)
=> 10.0

So we need to take 10 men’s Medium-size shirts to Cardiff!

Building a T-shirt calculator

Now we have some Python code, we can put a web interface on it really quickly with Anvil. I built a T-shirt calculator that can do this calculation for many sizes of shirt at once. You can use it below, or open the source code in Anvil to see how it works:

Open source code

Feel free to use and share this app. And if you’re going to a developer conference soon, perhaps we’ll see you there!

Building Email-Driven Apps
18th of July 2018

Sending and responding to email in code

Email is the most popular messaging platform on Earth. We use email to arrange events, to exchange files, and to notify each other when something happens.

You should be able to email your applications too. But to receive email, you need to set up a server somewhere, run an SMTP daemon, and somehow connect that to your code.

We’re here to fix that. Today, we’re delighted to show you the easiest way to build email-driven apps. All you need to do is write a Python function. For example, here’s all the code you need to receive emails and store them in a database:
def incoming_email(msg):
  msg.reply(text="Thank you for your message.")

Sending is just as simple:
  subject="New message",
  text="This is awesome",
  html="This is <b>awesome</b>"

Despite its simplicity, it’s also fully featured - you can handle attachments, recipients, and even use DKIM to check that a message is genuine before trusting what it says.


You can scroll down for a cookbook of common examples, or watch as I build a full disposable-email-address service, and publish it on the web, in four minutes:

Example Snippets Watch video

Video example: Disposable Email

App Source Code
Note: We skim past the UI building pretty fast in that video.
If you want to see how it's done, check out our other tutorials for a slower explanation.

Sample Email Code

Here are a few things you might want to do with email. You can follow along from these code snippets, or view them all in the Anvil editor:

Open Example Code

1. Receiving email and saving it in a database
def incoming_email(msg):

2. Replying to an email you’ve received
def incoming_email(msg):
  msg.reply(text="Thank you for your message.")

3. Sending email

def send_a_message(txt):
    cc=["Someone Else <>"],
    subject="Hello World",
    text="Hi there!"

4. Handling attachments

All attachments are Anvil Media objects. This means you can upload them from web browsers, store them in databases, make them downloadable, and more.

def send_by_email(file):
    subject="New upload",

Incoming attachments are just as straightforward. Here’s how to save all attachments in a database:
def incoming_email(msg):
  for f in msg.attachments:

5. Authenticating senders

Email has historically been easy to spoof. Helpfully, many providers now support DKIM, which lets you verify that the email actually came from the domain it says it did.

The dkim property of the message contains details about all that message’s valid DKIM signatures, and a shortcut to check whether it’s signed by the address in msg.envelope.from_address:
def incoming_email(msg):
  if msg.envelope.from_address == ''
      and msg.dkim.valid_from_sender:
    msg.reply(text="You're the real deal!")

There’s a shorthand, if you only want to accept DKIM-authenticated messages (and reject all others):
def incoming_email(msg):
  if msg.envelope.from_address == '':
    msg.reply(text="You're the real deal!")

6. Rejecting (“bouncing”) messages
def incoming_email(msg):
Try it yourself

Start writing email-driven apps for free with Anvil:

Try it now

You can also read more about the Email service in the Anvil reference docs.

Making the Web More Pythonic
15th of May, 2018

The Web is not Pythonic. Can we improve that?

The Web is traditionally a pain to program. It's also seriously un-Pythonic.

At PyCon 2018, I asked: Can we make Web programming easier, by making it more Python-shaped?

Scroll down for transcript
Anvil logo
For more information about Anvil, check out

The Web, I assert, is seriously un-Pythonic. It's also famously a pain to program for. Are these two things related? Could we make the Web a nicer place to program, by making it more Pythonic?

Well, to start with, what do I mean by "the web is un-Pythonic"?

Think about a typical web app. You're going to have to turn your data into a bunch of different shapes along the way:

  1. Your data exists as rows in a database, accessed via SQL.
  2. You then transform it into model objects on the server, with methods and attributes to interact with them.
  3. Now, you have to represent these objects as JSON, and provide a whole bunch of REST endpoints for getting or manipulating them.
  4. On the client, you then transform these HTTP requests into Javascript objects, which have methods of their own.
  5. And then you have to transform these client objects into HTML DOM...
  6. ...and style that to produce pixels on a screen.


At each of these boundaries, a bunch of boring and repetitive translation work happens. And that is an invitation to exactly the wrong sort of magic.

Let's take an entirely unfair pot-shot at SQLAlchemy, which is a library that manages the transformation of an SQL database into Python objects (and back). It's actually really good at it. You can even write neat query expressions like this: filter(Book.value<20).

Of course, the process of turning that Python expression into SQL is black magic. It involves metaclasses, and overloading standard Python operators to do something completely different to what they normally do.

And that's cool, if you do it once. But if you have this amount of magic at every boundary in this stack, you're setting yourself up for a bad time.

But of course, that's exactly what we do:

  • We have ORMs to translate databases into objects;
  • We have REST frameworks to help us represent objects as JSON;
  • We have JS frameworks (like Angular's resources) to help us turn patterns of HTTP requests into Javascript objects;
  • We have templating engines to represent JS objects as HTML DOM;
  • And we have CSS frameworks to help us display this DOM as the right pixels.

And they're all extremely leaky abstractions! To be a reasonably advanced user of any of these frameworks, you need to understand everything they do, on both sides of the transformation.

Aside: This is a leading cause of the "Framework of the Week" anti-pattern. You have a tool which is inherently unsatisfactory, because it's spanning one or more of these transitions and suffers from all these impedance mismatches. And just in order to use this tool, you need to know more or less everything you need to build one yourself. This presents an irresistible temptation. But of course the new one still isn't quite right...and around and around we go.

So, how does this situation stack up against The Zen of Python?

"There should be one obvious way to do it"?

Hoo, boy. Look at all these frameworks!

"Explicit is better than implicit"?

Transforming data implicitly is these frameworks' job.

"If you can't explain the implementation, it's a bad idea"?

Again, look at the sheer amount of magic in every level of this stack!

So, what might something more Pythonic look like?

At Anvil, we start by putting Python everywhere — even in the browser. (We use the Skulpt Python-to-Javascript compiler; check out my previous talk about it.)

OK, so if we're in Python, and making an HTTP request to a Python server, what happens?

Well, we make a function call into the requests library, and then some time later it emerges as a function call to a Flask endpoint.

Wait a second. If a function call was all we wanted, why not explicitly turn the whole thing into function calls?

So that's what we do. Have a function on the server, decorate it with @anvil.server.callable, and call it from the client with a function call.

Now we can pass arguments (even keyword arguments), and return values from the function. We don't have to marshal everything into an HTTP request any more — it's just a Python function call.

(The data still passes over HTTP, of course. Actually, we use an encrypted WebSocket.)

OK, so the next question is, "What sorts of data should you be able to pass into, or return out of, these functions?"

Well, strings, numbers, dicts, and lists are easy. That's just JSON. But we want to avoid translations, so we want to pass proper objects from the server to the client.

Unfortunately, this is a web server, serving lots of clients, so it has to be stateless: the server just can't afford to keep these objects in RAM.

So we support passing a special sort of object: a stateless server object.

What's in a stateless object? Well, it has an immutable ID, some method names, and some permissions. That's all. (So there's nothing else the server has to remember.)

We can call methods on this object from the client: it's just a server function call, like we saw on the last slide. We make sure the client can't call methods on arbitrary objects by signing the ID and permissions, and requiring that signature to call a method on an object. So the client can only call methods on an object that has been returned from a server function.

An excellent use case for this is...database rows! The object's ID is the unique ID of that row in the database; the methods are things like update() and delete(). And by implementing __getitem__() and __setitem__(), we can even use square-bracket lookup to get and set column values.

If we put this together, we can:

  • Make a simple function call to the server,
  • Look up a database row,
  • Return that row to the client as a Python object,
  • ...and use the values from that row in client code.

We've skipped a whole bunch of these translation steps! We've got one object, passed all the way from the database to client code.

And that's a little contribution to making the Web more Pythonic.

For more about Anvil, check out

Thank you very much.

Simple Object Storage
3rd of May 2018

New: Store richer data in Data Tables

Do you find yourself wanting to store more than just strings, numbers and dates in your tables? Perhaps you have complex records with dynamic fields, or perhaps you want to store lists of data without making a whole new table.

Today, we’re introducing a new type of column: the Simple Object. It can store lists, dicts, numbers, strings and (of course) None. (If you’re familiar with JSON, you’ll know this is another way of saying “any JSON value”.)

Add a Simple Object column to your table like this:

Creating a Simple Object column

Now you can store structured data in a single row of your table:

    name = "Kermit the Frog",
    contact_details = {
      'phone': [
        {'type': 'work',
         'number': '555-555-5555'},
        {'type': 'home',
         'number': '555-123-4567'}

Querying them is just as simple. If you supply an object to the Data Tables search() or get() method, you’ll match every value that contains those values, dictionary keys or list items. Here’s an example:

  def get_person_for_number(phone_number):
    # We have a phone call for this number. Who is it?

    return app_tables.people.get(
        contact_details = {'phone': [{'number': phone_number}]}

You can read more about Simple Object columns in the Data Tables reference docs.

YC Prototypes #2: Building Magic in 2.5 hours
23rd of March 2018

Day 2: Let’s make Magic (YC W15)

It’s Y Combinator’s week of Demo Days, and we’re prototyping one YC startup each day. (If you missed it, check out the first in this series, where we prototyped an e-parking service in an hour and a half.)

Magic (YC W15) is an SMS concierge that can do anything. Text them a request, however outlandish, and they will make it happen. Let’s put ourselves into the founders’ shoes, when they were just starting out. We don’t know if anyone wants this service, so we need a working product they can use. What do we need to build?

  • We need to see and respond to texts from our customers.

  • We need to charge customers for the things we provide (with a commission, of course). They shouldn’t need to enter their credit card every time.

  • We need to share this work between several people.

With Anvil, it turns out we can build this all in a couple of hours. Watch me build a fully working product in this time-lapse video, then scroll down for the play-by-play:

1. Two-way Conversation (45 mins)

We use Anvil’s built-in data tables to store customers and events (messages, notes, etc), and build pages to display them. We use the Users service to authenticate operators (ie us).

Within half an hour, we’ve got the basics: We can receive SMS using an HTTP endpoint from a service like Twilio, display the conversation, and send replies.

2. Take Payment (45 mins)

Now a customer can ask for something, we need them to pay for it! To make purchases truly frictionless, we’ll take their credit card once, then keep it on file for anything they need in the future.

Anvil’s Stripe support makes this simple. We make an app to collect the customer’s card details, and then we send them a link to open that app on their phone:

After that, the card is on file, and we can charge them at the click of a button. (We also note our profit margin for future reference.)

3. Coordinate many operators (50 mins)

If this app takes off, we’ll need help. We don’t want any messages to fall through the cracks, so we text all our operators when a new customer arrives. But we don’t want to notify every operator about every message – they’ll get drowned!

Instead, let’s track which customers need attention, and let operators “claim” customers. (We make sure two operators can’t claim the same customer by accident.)

The operator can mark a customer as Done (request resolved, no longer needs attention), or Can’t handle (still needs attention – “un-claim” the customer and text other operators for help).

If we need more information from the customer, the operator can select “Tell me when they reply”. The operator can go do something else: when the customer replies, we send an SMS to this operator only.

Prototype Complete (2 hours 20 minutes)

We’ve built the infrastructure for an SMS concierge in just a couple of hours. We can help people by text, take payment, and even coordinate a large team of operators if it suddenly gets popular. It’s a fully-working product that can take revenue right away, and scale as we grow.

Here’s how our final app works:

You can grab the source code yourself – click below to open the apps in the Anvil editor:

Copy Apps

Want to dig into how these apps work? Our tutorials show you all the pieces these apps are made from, and more.

How We're Building One Y Combinator Startup a Day
20th of March 2018

Prototyping a YC Startup Each Day

Check out Part 2 of this series >

It’s Y Combinator’s Demo Day this week, when the startup incubator’s graduates show their products to the world. To mark the occasion, we decided to try a challenge: How much time does it take to prototype a startup?

For each Demo Day this week, we’ll build a working prototype of a startup from a recent YC batch. “Working” means more than a landing page – we want enough technology to provide the core service to the customer, and to get paid for it.

Our secret weapon is Anvil. It’s a platform for building web apps without the fuss: it’s got a visual interface designer, client- and server-side code is all in Python, and it deploys to the cloud with one click.

We’ll walk you through the design process, show you some screenshots, and give a breakdown of how long each stage took. Today, we start with:

1. Meter Feeder (YC Winter 16)

Build time: 1 hour, 30 minutes.

We’re moving to a cashless world, but urban infrastructure is slow to change. Meter Feeder lets you pay for parking with your smartphone, without costly new infrastructure.

Imagine we’re the Meeter Feeder founders: We need to build a working prototype that we can demonstrate to a city government, and deploy as a proof of concept. This means:

  • The public (customers) need to be able to pay for their parking.

  • Traffic wardens on patrol need to know whether a car’s parking has expired.

Let’s fire up Anvil, and see what we can do.

Design the data model (10 mins)

We’re going to break up parking into “locations”. We’ll identify a location with a number, which can be entered easily on a phone keypad, and displayed on legacy parking infrastructure (translation: put a sticker on the physical parking meter). Each location has a cost for a given unit of time, and a maximum stay (eg “$0.50 per 15 minutes; max stay 2 hours”).

We then create a table of “bookings”, which represent payment for a car to park in a location. Finally, we add user records (with Anvil’s built-in user authentication), and link each booking to the user who made it.

This is all pretty quick to set up with Anvil’s Data Tables:

Design the public interface (30 mins)

Collecting payment is pretty straightforward with Anvil’s Stripe integration. Collecting the registration plate number and parking duration is even simpler. But parking your car is a frequent event, and we don’t want to make the customer re-enter this information every time. What’s more, after a user has paid for parking, they’ll want to check back and see how much time they have left.

So the first thing we do on app load is trigger the login/signup screen. (We use the “Remember me” option, so regular users never have to see it again.) Once we’re logged in, we can find and display your recent bookings. We also offer a quick “park here again” button to repeat an expired booking.

If you choose “New Booking”, we prompt you to enter a location code, or pick from a list of locations you’ve booked recently.

The next screen has big touch-friendly buttons for choosing your time and entering your registration. If there is a Stripe record associated with your account, we show a “pay with the same card as last time” button.

Thanks to the “Park here again” button on the first screen, a returning user can park somewhere they’ve used before with only two touches.

Back-end Logic (25 mins)

This is the back-end to make all those buttons work. This ends up being a 60-line server module, exposing four functions - “get my recent bookings”, “get a location record for this number”, “get the last licence plate I parked with”, and “pay for parking”.

Wiring these up to the front end didn’t take long, because Anvil lets you return live database rows into client code, and then use data bindings to display them in the UI.

Enforcement App (15 minutes)

After all that, the enforcement app came together pretty quickly. It’s a private app, so we can skip the user authentication and make the Locations and Bookings tables readable directly by client code.

When a parking warden arrives at a new location, they can enter the location code to display all valid bookings for that location. We also support as-you-type searching by licence plate number, so they can query a single plate in a busy location.

That’s all, folks! (1 hour 30 minutes)

We’ve built a working, deployable prototype of the MeterFeeder service, in an hour and a half. If we were the MeterFeeder founders, we’d be feeling pretty good by now - we’ve got a compelling demo, without spending weeks or months getting this far. This means we can move straight on to the hard part: selling the concept to local government.

You can see the source to these apps yourself – click to open them in the Anvil editor:

Copy Apps

Want to dig into how these apps work? Our tutorials show you all the pieces these apps are made from, and more.

Live Coding a Stock Portfolio App
31st of January


In this live-coding video, you will watch me prototype a financial "Software as a Service" (SaaS) application in under an hour. At the end of this video, we will have an application for tracking stock prices. It has user accounts, per-user portfolios, and a monthly credit-card charge for using the service.

Follow along as we start from a single stock chart and build up to a full subscription service. You can also copy the source code and explore it yourself:

Copy source code
Copy source code

App Secrets
15th of January 2018

Encrypted Storage, Made Easy.

When your web app is handling sensitive information — be it API credentials, database passwords, or sensitive personal data — it’s important to keep it protected. It certainly shouldn’t be sitting in your source code, for anyone to see. It should be kept encrypted, until the time it’s needed. This is called encryption at rest.

With Anvil, you can store password or API keys encrypted in your app, with a name – for example, I could store my GitHub password in a secret called github_password. Then I can use it in my app, like this:

  username = "meredydd"
  password = anvil.secrets.get_secret("github_password")

  r = anvil.http.request("", json=True,
                         username=username, password=password)

I can also create and store an encryption key, and use it to encrypt and decrypt data. Encrypted-at-rest data storage is this simple:

  # This app has an encryption key named 'my_key':

  def save_secret_data(new_text):
    encrypted_text = anvil.secrets.encrypt_with_key('my_key', new_text)


Watch our video tutorial here, or read our API documentation :

Try it yourself

How it works

App Secrets are encrypted, and stored with the source code for your Anvil app. Secrets and keys are encrypted with a key unique to that application – making the encrypted value useless outside that app.

All encryption is performed with high quality, industry-standard encryption schemes that avoid the pitfalls of using low-level cryptographic libraries. For more details, see our documentation .

We believe security and privacy are important, and we are proud to empower our users to use cryptography easily and safely. We are grateful to the security and privacy researchers who have helped us develop and validate this feature, and we welcome contact from the security community at

Building a Python Autocompleter
8th of November, 2017

Auto-completing Python on the Web

Why do you need autocompletion, and how does it work? My talk at PyCon UK 2017 explains how – and why – we built an in-browser autocompleter for Anvil.

Watch it below, or scroll down for a transcript:

Anvil logo
For more information about Anvil, check out
Skulpt logo
For more information about Skulpt, check out

I'd like to start by taking some time to thank the PyCon UK organising committee. This has been our first time sponsoring PyCon UK, and we've been made to feel very welcome.

We make Anvil – it's a tool for building full-stack web apps with nothing but Python. We did this because we think we can make a better developer experience using full Python than using the traditional tools. And autocompletion is part of that.

Having proper code completion gives you discoverability. It lets you explore the APIs, without having to tab to the documentation all the time. It gives you speed, because you go a lot faster when you can hit the Tab key every few characters. It gives you confidence that what you're doing is right, because there are whole classes of bugs you can fix without even hitting the Run button. And it just feels good to use.

We started out thinking we could make a good developer experience without autocomplete. I'm here to tell you that we were wrong.

If you don't use autocomplete yourself, you might not know what you're missing. I really encourage you to try it out. Even if you spend all your days in a terminal with vim or emacs, you can get Jedi as a plugin. Really, just try it for a week. See what happens. You'll be amazed.

Unfortunately, Jedi wasn't quite what we needed. Earlier I said Anvil was "full stack", and that means that it knows about everything from your database tables... your server-side code... your client-side code. And it's got to autocomplete all of them.

What's more, Anvil is web-based, and Jedi is expecting a filesystem. And when you're hitting the Tab key, there's just not enough time to go back to the server to fetch your completions.

So we had to write it ourselves, in Javascript. Which means that, yes, here I am, talking about my Javascript project at a Python conference. (Please save the rotten fruit until after the photos at the end.)

So, what do we do?

Conveniently, because Anvil runs all your client-side Python code in the browser, we have a Javascript parser for Python just lying around the place. (We use the open-source Skulpt project.)

So we can take your code, insert a random symbol at your cursor position, and then feed it to the Skulpt parser. The parser then produces an abstract syntax tree that represents your module.

We can then recursively walk this tree, and build up a representation of what's in scope at any given point in the code. We actually use Javascript's prototypical inheritance for this: Inside scopes (like inside a function) prototypically inherit all the names that are in scope from outside scopes (like the module globals).

And when we hit a Name node that contains the magic cursor symbol, we can just suggest all the things that are currently in scope.

That's not the only thing we want to autocomplete. For example, you can access Anvil's database rows like dictionaries, using square brackets (aka __getitem__). So we have to store which items are available on each type.

We also compute and store what you get if you iterate over an object, what its attributes are, what you get if you call it as a function, and so on.

Speaking of function calls, we also need to infer between modules. For example, in Anvil you write your server code in Python, and you call it from the client with a Python function call. And if you pass something into that server code, you want to be able to autocomplete it inside that server function.

So, as well as saving the top-level scope of every module (so it can be used in import statements from other modules), we also store every outbound call from a module – including calls to the server.

So when we parse this client code, we store this outbound call, along with the types of its arguments. And then when we're parsing the server code for autocomplete, we can just pull out the type information for those arguments, and stick it into the local scope, where it autocompletes.

We can store a lot of information about types. This leads to a rather philosophical discussion about what, exactly, a type is.

You might say, "that's easy, the type of an object is its Python class". But of course, in Python, you can dynamically add attributes to individual object instances. And, arguably, even two dicts aren't really the same type.

So what we actually do is mostly forget the Python class – our autocompleter is duck-typed. As far as we're concerned, these two dictionaries are two separate types, with separate item mappings, and should be treated as such.

There's so much more I could talk about, but this is a short talk. And so, if you remember only one thing, make it this:

Ladies and gentlemen of Pycon UK 2017, use autocomplete!

Thank you very much.

SMS Surveys in Pure Python
10th October 2017

Telephony integration, deployed in minutes

There are some great telephony services for developers out there these days. A simple HTTP call or webhook is all it takes to send and receive messages, but building and hosting a webapp to do this is still far harder than it should be.

Enter Anvil, a platform for full-stack web development in nothing but Python. An SMS survey is a great example of something that should be really simple to build, so I’ll show you how I did it in just a few minutes with Anvil.

First, head over to to see the finished app. You can also take a look at the source code and try it out yourself.

Let’s take a quick tour through the code to see the highlights. There are two main parts:

  • The main form, displaying voting instructions and current live survey results.

  • The Webhook Server Module where you’ll find the HTTP endpoint that can be called for each incoming SMS. I used the excellent Nexmo API, which makes it really simple to receive SMS messages to a custom webhook.

Receiving SMS Messages

Take a look at the Webhook Server Module. You’ll see that it only took one function to handle incoming messages:

  def incoming_sms(msisdn, text, **kw):

The incoming_sms function is decorated with @anvil.server.http_endpoint, which means external services can make HTTP requests that trigger the function call. After signing up with Nexmo, I simply set the incoming webhook address to the URL of my HTTP endpoint. In my case, that URL is “” – your copy of the app will have its own URL, which you can find displayed at the bottom of the Server Module.

HTTP form parameters are passed as keyword arguments to this function. We have explicitly captured the sender (msisdn) and contents (text) of the message, and used **kw to receive the other paramaters. In fact, form parameters, query string parameters and path parameters are all provided as keyword arguments – see the documentation for more information.

Inside the incoming_sms function we add a row to our data table with the details of the incoming message:

    app_tables.messages.add_row(sender=msisdn,, message=text)

Next we decide whether the incoming message contains a valid vote, and if so increment the appropriate total in the Results table.

    colours = {
      "A": "Red",
      "B": "Green",
      "C": "Blue",
      "D": "Yellow",

    colour = colours.get(text.upper(), None)
    if colour is not None:
      app_tables.results.get(colour=colour)['votes'] += 1

Readers of a nervous disposition should note that the entire incoming_sms function is decorated with @tables.in_transaction, so operations like incrementing values in the database are perfectly safe. If two requests arrive simultaneously, and they try to edit the same table row, one of them will be automatically rolled back and retried. See the Data Tables documentation for more details, and the Data Tables tutorial for examples.

Displaying poll results

Laying out the UI for our web application takes no code at all – Anvil’s visual designer lets you drag and drop components into place until your page looks the way you want it to look. For this app, we’ll add a few containers and labels, and a Plot component for displaying the chart.

Once we’ve created the Plot component, we have the full Plotly API at our fingertips. Drawing a bar chart couldn’t be easier.

Back in the main form, we query for the latest results:

  results = list(

Then it’s just a matter of creating a Plotly Bar Chart object, and populating it with our results. Notice that we use list comprehensions to assemble the necessary data for each axis:

  # Create a Plotly Bar chart with colours along the x-axis
  # and number of votes on the y-axis. = go.Bar(
    x=[v['colour'] for v in results],
    y=[v['votes'] for v in results],
      # Set the colour of the bar to the colour being voted for
      color=[v['colour'].lower() for v in results],
  # Set the axis and plot labels
  self.results_plot.layout = go.Layout(
      # Start y-axis ticks at 0 and increment by 1.
    title="Live Poll Results (%s votes)" % sum([v['votes'] for v in results])

The final piece of the puzzle is to make the chart update live. For this we use a Timer component on the form, and set its interval to 1 second. In the tick event handler, we simply call the method to redraw the plot.

Ready to go

And there you have it. A complete SMS polling app, built and deployed in no time. Anvil lets you build great apps on top of great APIs (like Nexmo) without any of the hassle traditionally required for web development.

See the code

New: Media in data tables
5th of October 2017

Store files in Data Tables. Why not?

We’re used to storing text and numbers in databases, so why not binary media? Whether it’s images, PDF files or whole spreadsheets, now you can store your files directly in Anvil Data Tables like any other data type.

Just create a Media column in your table:

Creating a media column

Create rows in your table by uploading files:

Uploading table media

And view or download the media objects directly from the database:

Downloading table media

A Media object from a table row behaves just like any other Media object in Anvil - you can assign it to the source property of an Image component, get its URL, or even get its contents as a binary string with the get_bytes() method. See the reference documentation   for more details.

Try it yourself

New: Data Bindings
21st of September 2017

Design your data right onto the page

Let’s say you’re writing a web app, and you need to display and edit some data. Wouldn’t it be great if you could drag and drop to design how your page looks, and where the data goes? Especially if we kept the power and flexibility of writing real code?

We thought so too, and today we’re proud to announce Anvil Data Bindings:

Loading video...
Watch the tutorial

Data bindings extend Anvil’s visual designer. As well as positioning your components on the page with drag and drop, you can now set component properties to any Python expression. You can even assign updated values to this expression when you change your component.

Finally, today we are also introducing the RepeatingPanel. This makes it easy to repeat components for every element in a list - now, displaying items in a table or list is a snap!

You can find out more about data bindings with the tutorial . You can also read the reference documentation .

Build a Business Dashboard with Python
22nd of August 2017

You make what you measure.
— Joe Kraus
Dashboards in Python: Visualise Your Performance

Business is like driving - what you’re looking at is what you steer towards. A dashboard is a way to make sure you’re looking at the most important parts of your business. The good news is that they’re quite straightforward to build – especially if you have Python to help you.

I’m going to put the goodies up front, for the geeky and impatient. This is a video of me building a dashboard that pulls data from a business database, and displays it on the web. Watch it now, or read on as we take a step-by-step guide to creating your own business dashboard.

See the code

So, how do I do it?

Step 1: Ask the right question

This is the most important part of measuring your business. You have to ask yourself what information is so important, you should see it every morning.

When you’re building a business, the most important questions aren’t always obvious. There are some great guides out there. I’d recommend Startup Metrics for Pirates (not just for start-ups!), and Adam D’Angelo’s talk on measurement from Y Combinator’s Startup School.

Broadly, though, there are two sorts of questions: Strategic metrics that show you where you want to go, like user acquisition rate, retention, or revenue growth; and tactical metrics that monitor how you’re getting there, such as A/B tests and short-lived marketing initiatives. At very least, you should have a dashboard that shows you your strategic metrics, and how they compare to historical performance.

Don't be afraid of hard questions.

Sometimes, the answer you need is right there in your database, and all you need is to query it. It's great when that happens, and we'll cover this simple case in our walkthrough.

But it's often more complicated than that: Perhaps you'll need data from your application database, your CRM system and an external analytics provider. Because we're using Python to compile the data for our dashboard, we have the flexibility to do that. So you have no excuse: Don't measure the wrong thing, just because it's easier.

Step 2: Get the answer from your database

Let’s imagine we’ve thought about it, and decided that our primary business concern is acquisition: How many new users are we signing up, and how is that changing from week to week?

For 99% of online businesses, this information will be in an SQL database somewhere. Connect with your command-line tool of choice, and write your query. Our example table looks like this, using Postgres:

myapp=> \d users
                 Table "public.users"
   Column    |            Type             | Modifiers                      
 id          | integer                     | 
 email       | text                        | 
 signup_date | timestamp without time zone | 

A little trial and error, and we have a query that gives us the number of user sign-ups by week, for the last three months:

myapp=> SELECT COUNT(*), DATE_TRUNC('week', signup_date) AS d
             FROM users
             WHERE signup_date > NOW() - INTERVAL '3 months'
             GROUP BY DATE_TRUNC('week', signup_date)
             ORDER BY d;
Step 3: Put it online

We want to make this data visible on a web page. Anvil lets us create web apps with nothing but Python. We’re going to create an Anvil app: It will have a server module that uses the standard Python tools to extract the data from our database, and a client-side page to display it on the web (also in pure Python).

To connect to a Postgres database, we use the standard Psycopg2 library. We create a server module and write:

import psycopg2

conn = psycopg2.connect(" dbname=my_app user=postgres password=secret")

Now, we want to run that SQL query on demand. We’ll define a function that gets our data and returns it as a list:

def get_user_signups():
    cur = conn.cursor()
        SELECT COUNT(*), DATE_TRUNC('week', signup_date) AS d
             FROM users
             WHERE signup_date > NOW() - INTERVAL '3 months'
             GROUP BY DATE_TRUNC('week', signup_date)
             ORDER BY d;
    return list(cur)

We’ve marked the function @anvil.server.callable. That’s all we need to make it accessible from client-side code when we build our web page. (No web server required!)

Calculating complex metrics

Remember earlier, when we said you probably want more than just a user count? This is where Python shines.

Cross-reference with a NoSQL database. Query your CRM via its API. Run statistical models with NumPy. Python is the swiss army knife of data analysis – why wouldn't you use it for your dashboard?

Step 4: Draw the plot

All that’s left is to display this data as a graph in our web app. We open Anvil’s visual designer and add a Plot component to our app’s main page. When the app opens, we call the query function we’ve just defined, and construct a line graph with the data:

signups ='get_user_signups')

# Anvil plots use the API:
scatter = go.Scatter(x = [signup_time for (count,signup_time) in signups],
                     y = [count for (count,signup_time) in signups],
                     fill = 'tozeroy')

We want that code to run when the page first opens, so we put it in the __init__ method of our form. (We also import the plot API.)

Here’s the entire page source code, including the parts Anvil provides for you:

from plotly import graph_objs as go

class Form1(Form1):
  def __init__(self, **properties):

    # This code will run when the form opens.
    signups ='get_user_signups')

    # Make a line plot of this data
    scatter = go.Scatter(x = [signup_time for (count,signup_time) in signups],
                         y = [count for (count,signup_time) in signups],
                         fill = 'tozeroy')

    # Display that plot on our page = scatter

That’s it! Here’s what it looks like, now we’re finished:

Screen-shot of the finished app

See source code in the Anvil editor

Step 5: Actually watch it

It feels silly to say it, but I know from personal experience: A dashboard you don’t look at is as bad as no dashboard at all. It’s actually worse, because knowing it’s there gives you a false sense of security.

Set your dashboard as your home page - or if you have a spare screen, display it in the corner of your office. And then, when it tells you something interesting, you might actually react!

I hope you’ve found this guide helpful. You can follow us on Twitter, or email me any questions or comments at Finally, you can see the full source code for this example here:

See the code

Interactive plots for your apps
26th of July 2017

New: Graphs and charts for your Anvil app

Python is the world’s favourite language for data processing and visualisation – and when you use Anvil, Python is all you need to build web apps. Today, we’re making it even easier to present your data on the web.

You can now offer interactive charts right inside your Anvil apps, built and customised in just a few lines of code. The new Plot component is powered by the Plotly Python API, so you have a wealth of examples already online to get you started.

Plots like this are simple to create, and simple to customise:

You can open this example in Anvil right now, or read the docs to learn more.

You can also find more examples in the Plotly library docs .

Try this demo now

HTTP endpoints for your apps
17th of July 2017

New: Make an API for your Anvil app

Sometimes we want to connect other programs with our Anvil apps. Whether it’s a native mobile app, a shell script, or a web service like Twilio, most things expect to make REST or plain HTTP requests.

As of today, this is all it takes to publish an HTTP API that returns some JSON:

def greet(name, **qs):
  return {'message': 'Hello, ' + name + '!'}

We can demonstrate it with the curl command-line program:

$ curl
{"message":"Hello, Joanne!"}

You can open this example in Anvil right now, or read the docs to learn more.

Try this demo now

Make the world better? Remove some Javascript.
27th June 2017

Compiling Python to Javascript

To write full-stack web apps in nothing but Python, you need to run Python code in the browser. Watch my talk at PyCon 2017, or scroll down for a transcript:

For more information about Skulpt, check out

Or you can check out the pull request that implemented these changes.


Back when my friend Ian and I were idealistic students, we sat down and decided to make the world a better place, as you do. And we decided that the best way two developers could make the world a better place was to remove some Javascript from it.

The web is the greatest application delivery platform on Earth, and frankly it’s a stain on our profession that you need to know five different programming languages and three different frameworks if you want to make it do anything. Really, all you should need is to be able to code - ideally, in a friendly, readable language that’s easy to learn and isn’t full of unpleasant surprises.

There was an obvious candidate.

So, we built a tool for building full-stack web applications with nothing but Python.

We built a graphical interface builder for designing your pages, and let you write your client-side code in Python - so all the buttons, text fields etc you put on your page are just Python objects. We built a back-end server environment, also in Python, and a database with a pure Python API, all deployed in the cloud in one click.

But today I want to talk about this front-end code.

If you want to drive the items on your web page as pure Python objects, you’re going to need to run Python in the browser. If you’re going to run something in the browser, it’s going to have to be in Javascript.

Thankfully, there’s a great open-source project called Skulpt, that compiles Python to Javascript. So you can write Python to drive your app, and we can compile it to Javascript so that when you publish it online, your code actually runs in a user’s browser. We give Skulpt Python objects, it represents them as Javascript objects. We give it a Python function, and it produces a Javascript function for the browser to run.

There is a problem, though. Javascript, in its infinite wisdom, is 100% non-blocking. If you kick off a process that finishes later, you’d better provide a callback.

Here’s some code you might write in Python. Go get a record from the database, and if it’s not there, throw an error.

And here’s how you’d do it in Javascript. I count three separate callbacks here. I’m not exaggerating - this is an example straight from the documentation of the postgres library!

OK, so we have a Python-to-Javascript compiler, and it’s open source. What if we could turn this into this, automatically?

So, we go "git clone", and start exploring. It turns out that Skulpt has a classic compiler architecture, modeled quite closely on CPython: There’s a parser that turns Python code into a parse tree (these are all the files in the Skulpt source tree, by the way, if you want to follow along).
Then it walks over this parse tree and makes an abstract syntax tree, which is made of elements you might recognise - like variable assignments, function definitions, function calls, and so on. Then there’s a compiler that then walks this syntax tree and spits out Javascript.

So, this is what we need to modify to implement blocking code. We invent a new Javascript class that a function can return, to say “hey, I’m returning, but I’m not done yet; I’ve just blocked”. We call this a suspension.

So, when we’re compiling the AST, wherever we’re compiling a function call, we generate Javascript code that calls the function, and looks at the return value, and says, "is it a Suspension?". Because if it returned a Suspension, we’re blocking - and I'm going to have to suspend myself. We save all our variables and temporary values, our exception state, and where we are in the function, and then we return our own suspension with all that information in it.

And so our caller will recognise that we have suspended, and so it's going to have to suspend as well, and so on all the way back to the Javascript runtime.

When that operation completes - say the database gives us a response - we resume the Suspension. We call our function with the suspension, which then restores all our variables, jumps to the right place and resumes the original suspension, which restores all of its variables, and so on, until we can resume execution as normal.

So, that’s how we take simple blocking Python, and compile it into non-blocking Javascript so you don’t have to.

This has been a quick overview; if you’re interested you can check out Skulpt at - I’m one of the maintainers now, and we’re always looking for new contributors.

And if you're fed up to the back teeth with all this Javascript, and you want to forget it all and write full-stack web apps with nothing but Python, please check us out at

Thank you very much!

Smart Python Code Completion
15th of February 2017

That's right. It's here.

Every coder knows the pain: You know what you need to do, but you can’t remember the name of that function, or what order it takes its parameters. It’s time to fix that problem.

We are excited to announce that from today, the Anvil web IDE includes smart code completion. Anvil knows about your forms, your components, your variables - even your data tables. Now we’re giving that information to you in real-time, as you type. Our API documentation is great, but the best docs are the ones you never have to look at. Code completion means the options are always at your fingertips.

Smart code completion is available right now - just log in and start creating!

Start Now

Python widgets in HTML layouts
5th October 2016

Speed, meet beauty.

Building a web page with drag and drop is much faster than fighting with HTML, CSS and Javascript. When we set out to build Anvil, we wanted to make it as easy to design a web app as it is to lay out a Powerpoint slide. We’ve combined drag-and-drop design with a library of prebuilt components, a built-in database and a simple Python programming environment. So far, we’re making web app development quicker and easier for people all over the world, from entrepreneurs to doctors. (Want to know more about Anvil? Read our introduction here.)

But sometimes, you need to put your best foot forward. You want to re-use your existing page design and brand assets. Or if you’re building those assets from scratch, you want pixel-perfect control over your page header. In short, you want the flexibility of traditional web design.

So, we asked: What if you could have both?

Introducing HTML templates

We’re excited to announce support for HTML templates in Anvil. You can choose from our menu of ready-to-go templates, or use your existing web design assets. Once you’ve loaded your template, development is as easy as ever: just drag and drop Anvil components into the page, and arrange them how you like. And you can drive all these components with Anvil’s straightforward Python APIs. (No Javascript required.)

Custom HTML

Anvil’s built-in templates make it easier than ever to produce a beautiful web app in record time. But if you know HTML, or have existing web assets, you can go beyond our built-in templates.

If you’re an Anvil Pro user, you can control your page down to the pixel, with any HTML or CSS you like. All you need is a couple of special attributes to tell Anvil where you can drag and drop components.

I can code my web app in Python, and employ a web designer to help me with the HTML/CSS. Anvil is without a doubt the easiest and fastest way to bring my app to life!
— Peter, Startup founder
(Yes, he actually said this)

Here’s all you need to build a drag-and-drop layout. You just need to specify where each group of components goes, and where to drag-and-drop them:

<link rel="stylesheet" href="">

<div class="header" anvil-drop-slot="title">
    <div anvil-slot-repeat="title"></div>

<div class="card" anvil-slot-repeat="default" anvil-drop-here>

(Want to know how that works? Check out our documentation.)

And here’s how it looks in action:

Available now

To build an app with Anvil templates, sign up and try some of our examples, or start from scratch. We’ve got lots of video tutorials to help you out. If you’re into DIY, our reference documentation describes how to use your own HTML and CSS with Anvil.

Try it out

We’d love to hear what you think. Drop us a line at, or you can use my personal address:

Usable configuration with Git
27th July 2016

The configuration dilemma

As developers, almost every app we write has configuration. Often, that configuration should really be accessible to our less technical colleagues: feature flags, rate limits, deployment signoffs, and so forth.

However, these changes also need to be tracked and audited. “The app just broke. Did someone change the config?” “Quick, revert it to last week’s settings!”

As programmers, we know exactly the right tool for this: Text files in version control. They’re diffable, trackable and comprehensible, and if anything goes badly wrong we can dive in with a text editor.

The problem comes when we present this solution to our non-technical colleagues. “So, I open the terminal? And then I type git clone and a string of gibberish you made me memorise?”

It’s tempting to give up and say, “I’ll do it for you”. Developers end up as gatekeepers, with every change coming through us.

This isn’t great either. Years ago, I used to develop SMS-based services for a mobile carrier in south-east Asia. This was the bad old days, before Twilio and friends, and the carrier had to sign off on every minor UI change – often at the very last minute. I spent many late nights waiting for a meeting on the other side of the world to finish, just so I could change one line in a config file.

GitHub API to the rescue

We can fix this. With the GitHub API, we can build an app in minutes that empowers our colleagues to change configuration on their own – with all the power of Git’s versioning and auditing.

Here’s a simple app, hosted on Heroku (source at It has a configuration file (called config.json) that determines vital parameters such as the font and background colour.

Open in new tab

Here’s how I built an Anvil app to edit that configuration, with less than a dozen lines of code:

Getting the config

First, we need to grab the latest version of our config file:

self.gh_record = anvil.http.request("", json=True, username="abc", password="123")

Github returns some information about this file, and its content in base64:

  "name": "config.json",
  "encoding": "base64",
  "size": 67
  ...several other bits omitted...
  "content": "eyJ1cHBlcmNhc2UiOnRydWUsImZvbnQiOiJIZWx2ZXRpY2EiLCJiYWNrZ3Jv\ndW5kIjoiYmxhbmNoZWRhbG1vbmQifQ==\n",
  "sha": "bfb17ee5edf43a54f6756f032603872ca7dce320",

The content is what we care about:

self.item = json.loads(base64.b64decode(self.gh_record["content"]))

The decoded data looks like this:

  "background": "blanchedalmond",
  "font": "Helvetica",
  "uppercase": true

All we need now is to design our configuration interface. With Anvil’s data bindings, it’s all drag-and-drop - we can just specify which JSON key (in self.item) each text-box or check-box corresponds to. That’s all we need for a read-only interface:

See source code for this app
Committing our config

Now we have read-only access to our configuration, the next step is to save our changes. As we interact with the text-boxes and check-box, self.item is automatically updated.

Now we just push this data back to the server, with an HTTP PUT request to the same URL. All GitHub needs is the new content for the file, a commit message, and the previous SHA hash of this file:

new_record = {'content', base64.b64encode(json.dumps(self.item)),
              'message', 'Edit from the web'}
              'sha': self.gh_record["sha"]}

anvil.http.request("", method="PUT", data=new_record, json=True, username="abc", password="123")

And here’s the working app. Why not try changing some settings?

See source code for this app

Once you’ve saved your changes, scroll up and refresh the example app. Be patient - it may take a few seconds to re-deploy with the new config.

Increased security

OK, we’re not quite done. So far, we’re doing everything on the client side, which means everyone with the URL can access our authentication information! Even if we only give that URL out to people we (mostly) trust, it’s far too easy for it to end up in the wrong hands.

Instead, we’ll do our GitHub API calls on the server side, and expose only two functions to the client: save_config and load_config. All the rest is safely on the server, where the user can’t see it:

# This code runs on the server
def load_config():
  gh_record = anvil.http.request("", json=True, username="abc", password="123")

  return (gh_record['sha'], json.loads(base64.b64decode(gh_record['content'])))

def save_config(data, last_sha):
  new_record = {'content': base64.b64encode(json.dumps(data)),
                'message': 'Edit from the web',
                'sha': last_sha}
  r = anvil.http.request("", method="PUT", data=new_record, json=True, username="abc", password="123")

  return r['content']['sha']
Copy the final app to see its full source code

(In fact, I’ve been using this version of the code for all the example apps embedded in this blog post. I’m afraid wasn’t feeling generous enough to share my GitHub authentication tokens with anyone who can View Source. Sorry to disappoint anyone who tried.)

Job done.

There you have it - a secure, functional configuration editor, ready for our non-technical colleagues to use. You don’t need to know Git to use it, but it does have full tracing and history of every change.


#1: We don’t have to sacrifice the benefits of Git for our configuration, just in order to get a user-friendly admin interface. We can have both!

#2: The GitHub API is awesome.

#3: Anvil lets you build useful web apps very, very quickly.

Why not clone this example app, read its source code, and try it out yourself?

Version control and Anvil
11th July 2016

Git access for your apps

Rapid development is great, and Anvil lets you build web apps amazingly fast. But sometimes you need more. You need tracking, collaboration, code review, versioning. In short, you need source control.

Today, we’re announcing availability of Git access for your Anvil apps. It’s simple: each Anvil app is its own Git repository. Just clone the repository, and you can pull, push, edit and merge Anvil apps right from your workstation.

Now you can collaborate on multi-person teams, manage deployment and staging environments, and integrate Anvil into your code review process.

You can sign up for the beta program from the Anvil app editor. Just select Git Access from the drop-down menu, and click the button to request access.

To learn more about Anvil, watch our video tutorial series. (Or, you can sign up and start building right away!)

Watch a tutorial

Anvil On-Site Installation
12th April 2016

Using Anvil behind your firewall

Anvil is, by default, a cloud-hosted service. This makes it incredibly easy to create web-apps that are live in the cloud, accessible from anywhere, and integrate with other cloud services.

If you’re in a corporate environment, your web app may need to access local resources. For example, you might want to use Anvil to query a database on your corporate network. For this, you will normally use the Anvil Uplink. This lets you securely give your Anvil app access to the relevant parts of your database:

The Anvil Uplink is available to all users, and does not store any data in the Anvil cloud. To learn more, watch our 4-minute video or read our documentation.

Sometimes, that's not enough.

Certain enterprise users, however, require more assurance. For example, organisations dealing with healthcare data may not transfer patient records to third-party services without special agreements.

For these users, we offer Anvil On-Site Installation. This allows you to develop and run your app entirely behind your corporate firewall, on servers you control:

An on-site Anvil installation requires no connection to the outside internet, giving you maximum assurance that your data is under your control.

Anvil On-Site Installation runs as a Docker container. It typically takes less than five minutes to get Anvil On-Site working on your network - and Anvil staff will be there to help you every step of the way.

If you want to run Anvil apps on your own network, please get in touch to find out more or arrange a free trial:

Arrange a trial

Introducing Anvil
20th February 2016

Making an interactive website should be easy, right?

Not so much. Let’s say you want a site to take orders for your new widget, or keep track of your customers, or schedule your local football league. Traditionally, you’ll need to know an alphabet soup of languages and technologies: HTML, CSS, JS, PHP, SQL - the list goes on. And that’s before we start on the complex frameworks required to make them usable.

This makes web development slow and complicated for professionals, difficult for other engineers, and entirely inaccessible for beginners.

We need to do better than this. So we built Anvil.

Web apps made simple

Anvil is a tool for making interactive websites in Python. Build your site with drag and drop, placing text, buttons, input boxes, images and more. Then double-click a button and write the Python that executes when that button is clicked.

You can make something really quick this way. Watch us build a page that greets you by name, in 45 seconds flat:

Want to try this yourself? Check out our tutorials

Simple built-in database

Anvil’s built-in database has a simple, spreadsheet-like interface for editing your data. Searching or editing it from your code is a no-nonsense Python statement. You can build a working database-backed to-do list app in five minutes - watch us do it!

If you already have a database, no problem - Anvil can connect to that too. (For those with special requirements, we even offer an on-site solution)

Use the rest of the web

No app is an island, and you shouldn’t have to build things from scratch. Anvil makes it easy for your apps to use services from the rest of the web:

Authenticate with Google login
Accept credit cards with Stripe
Store files in Google Drive
Store data in Google Sheets
Use local resources

You might want to use something that’s only available on your network, or your computer. Perhaps you want to use your company database, or special hardware, or files stored on your computer.

With Anvil, that’s a snap. Just import a library, mark the functions you want to call from Anvil, and away you go.

Watch us control a Raspberry Pi from the web in three minutes.

Try it out

Anvil is free for personal use, and we can’t wait to see what you will build with it. Why not sign up for free and try it out?

Build an app

Learn More

Get the best out of Anvil with our free email course.