Client vs Server Code in Anvil
Tags: webdev, beginners, python
Published: 2022-04-04 16:05:26

### About Anvil

_[Anvil](https://anvil.works?utm_source=dev_to_client_server) is a platform for building full-stack web apps with nothing but Python. No need to wrestle with JS, HTML, CSS, Python, SQL and all their frameworks – just **build it all in Python**. Get started with one of our [tutorials](https://anvil.works/learn/tutorials?utm_source=dev_to_client_server) or check out an [example app](https://anvil.works/learn/examples). For more help, we have detailed [developer documentation](https://anvil.works/beta-docs?utm_source=dev_to_client_server) and a friendly [Community Forum](https://anvil.works/forum?utm_source=dev_to_client_server)._

---

# Introduction to Client-Server Architecture

When you write code in an Anvil web app, there are two different places it can run: [the client](https://anvil.works/beta-docs/client?utm_source=dev_to_client_server) or [the server](https://anvil.works/beta-docs/server?utm_source=dev_to_client_server). **Client code runs on the user's browser** while **server code runs on a central computer that you control.** If you are new to web development, the distinction between client and server can be confusing at first.  When you use Anvil, you don't need to worry about the messiness of traditional web development, but you still need to separate out where your code runs. 

The purpose of this article is to provide an introduction to the **client-server architecture** and to explain why we need to write code for Anvil apps in two different places. We'll then use the [Feedback Form Tutorial](https://anvil.works/learn/tutorials/feedback-form?utm_source=dev_to_client_server) as an example to better understand why we need to use both client-side and server-side code.

In this article, we will cover:

* [The client and client-side code](#the-client)
* [The server and server-side code](#the-server)
* [Communication between the client and server in Anvil](#communicating-between-the-client-and-server)
* [The Feedback Form app as an example](#the-feedback-form-putting-it-all-together)

## The Client

### The front-end

Client-side code runs in the user's browser and is responsible for showing the visual components of an app as well as interacting with the user. This code running on the client makes up the **front-end** of a web app. In Anvil, your app's front-end is made up of [Forms](https://anvil.works/beta-docs/client/components/forms?utm_source=dev_to_client_server) where you can drag and drop Python components to [build a user interface](https://anvil.works/beta-docs/client/ui?utm_source=dev_to_client_server) and write client-side Python code.

When a user opens a web app, all of the front-end code is downloaded to the browser, which means that the user has full control over that code. Because of this, **client code is untrusted**. This is the reason we want some code to run elsewhere on a server. We don’t want the user to have access to code that authenticates users or processes payments, for example.

### Client-side Python

In traditional (non-Anvil) web apps, front-end code is written in HTML and JavaScript because those are the languages that browsers can understand. Anvil lets you write all your front-end code in Python. This works because Anvil translates the Python code in your client-side Forms and Modules into JavaScript for the browser to execute. Not every Python library can be translated, which means that there are certain Python libraries that [cannot be used on the client-side in Anvil](https://anvil.works/docs/client/python#limits-to-python-in-the-browser?utm_source=dev_to_client_server). Server-side Python does not run in the browser, so there is no need for it to be translated into JavaScript. This is why extra Python libraries can be [used in server code](https://anvil.works/docs/server/packages?utm_source=dev_to_client_server) or via [the Uplink](https://anvil.works/beta-docs/uplink?utm_source=dev_to_client_server). *If you're interested, Anvil uses the [Skulpt](http://skulpt.org/) Python-to-JavaScript compiler. It's an open-source project, and [we contribute heavily to it](https://talkpython.fm/episodes/show/235/python-in-your-browser-with-skulpt).*


## Server-side code

### The back-end
Unlike client code, which runs in the user's browser, server-side code runs on a computer that is separate from the user’s device. This is the **back-end** of a web app. Code written in an Anvil app's [Server Module](https://anvil.works/beta-docs/server?utm_source=dev_to_client_server) will never be seen by your app's users. This means that it can act as a gatekeeper for central resources (such as data in your app's [Data Tables](https://anvil.works/beta-docs/data-tables?utm_source=dev_to_client_server)) and enforce permissions checks (for example, checking if a user is an admin before showing information). 


*Learn more about [building secure apps](https://anvil.works/docs/security?utm_source=dev_to_client_server) in our documentation.*

In Anvil, we provide the server to run your server-side code, so you don’t have to worry about where to host it. In your Anvil apps, you just write code in a Server Module, and we provide the computer where it executes. This is called **the Cloud**, or **serverless computing**.

### The Uplink

However, your server-side code doesn't need to live on Anvil's servers. If you want to run your server-side code locally or on a different server, you can use the [Anvil Uplink](https://anvil.works/beta-docs/uplink?utm_source=dev_to_client_server). The Uplink is a way to connect an Anvil app to Python code running on a script somewhere else. For example, you could [connect a script running in a Google Colab notebook](https://anvil.works/learn/tutorials/google-colab-to-web-app?utm_source=dev_to_client_server) to your web app via the Uplink. In this case, the [Google Colab](https://colab.research.google.com/) notebook would be your app's back-end, and Google would be providing the server.

You can also use your own computer as the server by hosting your code locally and connecting it to your app with the Uplink. However, once you shut your computer off or set it to sleep, the Uplink will disconnect and the script will no longer be running. To keep the script running so that your app continues to work properly, you can host your Uplink scripts on a virtual private server such as [AWS Lightsail](https://aws.amazon.com/lightsail/) or [Digital Ocean Droplets](https://www.digitalocean.com/products/droplets). For more information on hosting your Uplinks scripts on an external server, see [our guide on using Docker](https://anvil.works/learn/tutorials/google-colab-web-service?utm_source=dev_to_client_server) to containerise and run your scripts.

## Communicating between the client and server

In Anvil, your app communicates by calling server-side functions from client-side code. You can make a server function available to the client using the [`@anvil.server.callable`](https://anvil.works/docs/server#calling-server-functions-from-client-code?utm_source=dev_to_client_server) decorator, and then call it from client code using `anvil.server.call`. We'll see an example of this in the next section.


![Client-server architecture](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/clx9jk5aghj13tcq771g.png)

<br>

## The Feedback Form: Putting it all together

Let's take the [Feedback Form Tutorial](https://anvil.works/learn/tutorials/feedback-form?utm_source=dev_to_client_server) as an example of a simple web app that uses the client-server architecture. The app has a simple user interface for taking user input and storing it in a Data Table. 

<br>

![Submitting feedback in the[Feedback Form Tutorial app](https://anvil.works/learn/tutorials/feedback-form?utm_source=dev_to_client_server)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qukkhz1cnijvg5h75xad.gif)
 

### Client-side

The front-end of the app is the user interface and the client-side code that collects user input. This code lives on the client because the user is interacting with it. After the user enters input and clicks the "submit" button, we use `anvil.server.call()` to call a server function to add this input to the Data Table:

```python
  def submit_button_click(self, **event_args):
    name = self.name_box.text
    email = self.email_box.text
    feedback = self.feedback_box.text
    # Call the 'add_feedback' server function
    # pass in name, email and feedback as arguments
    anvil.server.call('add_feedback', name, email, feedback)
```

### Server-side

The server function and the Data Table are the back-end of our app. Because the server is separate from the user’s device, we can use it to run code we don’t want to expose to the user. In the case of the Feedback Form, we don't want users to have access to code that modifies the Data Table since it contains other users' data. By default, only server-side code has [permission to access a Data Table](https://anvil.works/beta-docs/data-tables/data-security?utm_source=dev_to_client_server). We can pass the user input to a server function that then updates the Data Table:

```python
@anvil.server.callable
def add_feedback(name, email, feedback):
  app_tables.feedback.add_row(
    name=name, 
    email=email, 
    feedback=feedback, 
    created=datetime.now()
  )
```


## Summary

In this article, we looked at why we need to write code in two different places in Anvil apps. We covered why we write code on both the [client](#the-client) and [server](#server-side-code), and [how to communicate between the two in Anvil](#communicating-between-the-client-and-server). Finally, we saw how the [client-server architecture works in the Feedback Form Tutorial app](#the-feedback-form-putting-it-all-together).