A comprehensive guide to the new syntax in Appwrite Functions 1.4
Tags: tutorial, learning, cloud, serverless
Published: 2023-11-01 11:27:51

In the fast-paced development world, imagine having the power to effortlessly create, deploy, and manage serverless functions within your app, all while streamlining your development process.

## Technology overview

Appwrite functions allow you to run backend code automatically in response to events triggered by Appwrite or by executing the code on a predefined schedule. Your code is securely stored on your Appwrite instance and is executed in an isolated environment.

When users of your application create an account or log in, you can define code in [Appwrite functions](https://appwrite.io/docs/products/functions?utm_source=hackmamba&utm_medium=hackmamba-blog) to run and execute based on system events. Appwrite functions support multiple runtimes (like Node.js, Python, and PHP) and allow you to schedule the functions in your code to run at specific time intervals with your specified runtime. 

Additionally, you can seamlessly create and deploy your functions by running commands in your terminal with the Appwrite [CLI](https://appwrite.io/docs/command-line) (which enables you to work with the Appwrite server).

[Appwrite Cloud](https://cloud.appwrite.io/?utm_source=hackmamba&utm_medium=hackmamba-blog) is an extension of the open-source version of Appwrite. It comes with all the services included in the open-source version but now boasts a fully managed service and minimum friction.

## Project overview

This article takes a closer look at the magic of Appwrite Functions 1.4, demonstrating how to migrate your Appwrite version 1.3 functions to the latest version and take advantage of its new features and syntax changes in a Next.js application.

## GitHub

Check out the complete source code [here](https://github.com/Tundesamson26/appwrite-functions-guide).

## Prerequisites 

To follow along with this tutorial, you should have a working knowledge of the following:

- Basic understanding of JavaScript and Next.js 
- Installation of the [Appwrite CLI](https://appwrite.io/docs/tooling/command-line/installation?utm_source=hackmamba&utm_medium=hackmamba-blog)
- An Appwrite Cloud account; you can sign up [here](https://cloud.appwrite.io/?utm_source=hackmamba&utm_medium=hackmamba-blog)

## What’s new in Appwrite Functions 1.4

In Appwrite 1.4, Functions are more accessible to learn, faster to debug, painless to maintain, and more flexible than ever. The Functions workflow has been reimagined, guided by the community’s help and feedback. 

Below are some notable changes in the Appwrite Functions 1.4:

- First, `template` codes have been introduced to Appwrite 1.4 Functions. You can add Functions engineered by the Appwrite team and community to your Appwrite project. You can start leveraging the powers of Appwrite Functions and the community without writing a single line of code.
- Also, the Functions syntax has been revised based on feedback. The request data will now contain all the expected components of a typical `HTTP` request.
- A new dedicated `log` method has been included, so you’ll never have disappearing logs on a function you’re trying to debug again.
- Finally, in 1.4, you can deploy Appwrite Functions directly from **Git**. Appwrite Functions will now fit into your existing workflow alongside the rest of your code.

In this tutorial, you’ll start with setting up a frontend app for a demo that eventually illustrates the difference and migration from 1.3 to 1.4.

## Frontend setup

The frontend is a basic Next.js form page that handles form submissions and can be used to store a user's information in a collection. The form is submitted to the function using the `POST` method, and the form data will be sent as a URL-encoded string in the request body.

To set up your application, you'll clone this [repository](https://github.com/Tundesamson26/appwrite-functions-guide) using the command below:

```js
git clone https://github.com/Tundesamson26/appwrite-functions-guide.git
```

Then, run the command below in the project directory:

```js
$ cd appwrite-functions-guide
$ npm install
```

This repository contains all the initial setups you'll need for your app, helping you focus on your app's main functionality.

Then, run the development server using the command below:

```js
npm run dev
```
Once the development server runs, you can view it on your browser at [http://localhost:3000](http://localhost:3000/).

## Creating an Appwrite Cloud project

To get started, log into Appwrite Cloud, click the **Create project** button, input `appwrite-functions-guide` as the name, and then click **Create**.

![appwrite-create-project](https://paper-attachments.dropboxusercontent.com/s_B05668B00317FCD740F288B78CCD8EB8477A2E6B19F2E7C4A364E97990C1F627_1696594766745_image.png)


The project dashboard will appear on the console. Next, copy the **Project ID**; you’ll use this to set up your Next.js application.

![appwrite-project-tab](https://paper-attachments.dropboxusercontent.com/s_B05668B00317FCD740F288B78CCD8EB8477A2E6B19F2E7C4A364E97990C1F627_1696594848965_image.png)


You will also need to get an `API Key`, which will be useful in the next step. To create an `API Key`, click on the project overview and then click on `API Key` with the name `functions_guide`.

![appwrite-api-key](https://paper-attachments.dropboxusercontent.com/s_B05668B00317FCD740F288B78CCD8EB8477A2E6B19F2E7C4A364E97990C1F627_1695734360162_image.png)


Next is to choose which permission scopes to grant your application. In this case, choose **Functions** and **Databases** and click on **Create**.

![appwrite-api-key-scope](https://paper-attachments.dropboxusercontent.com/s_B05668B00317FCD740F288B78CCD8EB8477A2E6B19F2E7C4A364E97990C1F627_1695734745487_image.png)

## Creating functions in Appwrite 1.3

To create a function in Appwrite 1.3 version and below, you will start by logging onto Appwrite's console using the Appwrite CLI, like so:

```js
appwrite login
```

Running the command above requires you to use your Appwrite credentials 
(i.e., your Appwrite **email** and **password**) in the terminal.

After logging into the application, you will initialize and link the Next.js application with the previously created Appwrite project. To do so, you will run the command below:

```js
appwrite init project
```

Running the command above will display a list of options from which you will pick those appropriate for your project.

Next, create a function in your Next.js application by running the command below:

```js
appwrite init function
```
Upon the successful execution of the above command, you will see a new folder named `functions/<function-name>/src/index.js` in your Next.js application.

**Appwrite Functions 1.3 logic**

In order for your Appwrite Functions 1.3 to handle the form submissions, navigate to `src/index.js` and paste the code below:

```js
const sdk = require("node-appwrite");
const querystring = require ("node:querystring");

module.exports = async  (req, res) => {
  if (req.method === "GET") {
    return res.send(html, 200, { "content-type": "text/html" });
  }
  if ( req.method === "POST" && req.variables.headers["content-type"] === "application/x-www-form-urlencoded") {
    const formData = querystring.parse(req.body);
    const message = {
      name: formData.name,
      email: formData.email,
      date: formData.date,
      time: formData.time,
      content: formData.content,
    };
    const client = new sdk.Client();
    client
      .setEndpoint(req.variables['https://cloud.appwrite.io/v1'])
      .setProject(req.variables['APPWRITE_FUNCTION_PROJECT_ID'])
      .setKey(req.variables['APPWRITE_FUNCTION_API_KEY'])
      .setSelfSigned(true);
    const databases = new sdk.Databases(client);
    const document = await databases.createDocument(
      "650efb16ae5ebb92185a",
      "650efb593f6c9f97c09c",
      ID.unique(),
      message
    );
    return res.send("Message sent");
  }
  return res.send("Not found", 404);
};
```

The code block above achieved the following:

- Imported the node-appwrite SDK from Appwrite.
- Exported an asynchronous function req and res using the Appwrite serverless function framework
- **GET Request Handling**:
    - If the incoming request method is `GET`, then the function sends an **HTML** response (text/html) with the html content. The response code is set to `200`, indicating a successful response.
- **POST Request Handling**:
    - If the incoming request method is `POST` and the content type in the request headers is 'application/x-www-form-urlencoded', then the function proceeds to handle the `POST` request.
    - It parses the request body (which is assumed to be in URL-encoded format) using `querystring.parse` to extract form data.
    - It creates a message object containing properties like **name,** **email**, **date**, **time**, and **content** by extracting data from the parsed form data.
    - It creates an instance of the Appwrite client using the `sdk.Client()`.
    - It configures the client with an `Endpoint`, `projectID`, and `API key` based on values from the `req.variables` object.
    - It creates a new instance of the `**sdk.Databases**` using the client.
    - Finally, it uses the `createDocument()` method to create a new document in the Appwrite database. The document data is based on the message object created earlier.
- After successfully creating the document, the function returns an `HTTP` response with the text "**Message sent**."
- If the request method is neither `GET` nor `POST` or the content type is not 'application/x-www-form-urlencoded', then the function returns an HTTP response with the text "**Not Found**" and a status code of **404**.

**Deploying the Appwrite Function 1.3**
To deploy the Appwrite function, run the command below:

```js
appwrite deploy function
```

Executing the above command will require you to pick the appropriate function you want to deploy. Upon successful deployment, you will get a message like the one below in your terminal.

```js
✓ Success Deployed <function-name> ( functionID)
```
## Migrating to Appwrite Functions 1.4

On the left side of the Appwrite Cloud dashboard, click on the **Templates** tab to create a starter function.

![appwrite-functions-template](https://paper-attachments.dropboxusercontent.com/s_B05668B00317FCD740F288B78CCD8EB8477A2E6B19F2E7C4A364E97990C1F627_1696595050685_image.png)


Clicking on the **Create function** button will take you to the tab where you can start your configuration, like this.

![appwrite-function-config](https://paper-attachments.dropboxusercontent.com/s_B05668B00317FCD740F288B78CCD8EB8477A2E6B19F2E7C4A364E97990C1F627_1695902429452_image.png)


The next thing you should do is create the variable, and here is where you will paste the `API KEY` you created earlier.

![appwrite-function-variable](https://paper-attachments.dropboxusercontent.com/s_B05668B00317FCD740F288B78CCD8EB8477A2E6B19F2E7C4A364E97990C1F627_1695902717838_image.png)


Then, **Connect** to your repository by choosing either “**Create a new repository”** or **“Add to existing repository”** (in this case, you are connecting with the existing Next.js repository).

![appwrite-function-github-connect](https://paper-attachments.dropboxusercontent.com/s_B05668B00317FCD740F288B78CCD8EB8477A2E6B19F2E7C4A364E97990C1F627_1695903058452_image.png)


Next, choose the GitHub repository to trigger the Appwrite function.

![appwrite-function-github-repo](https://paper-attachments.dropboxusercontent.com/s_B05668B00317FCD740F288B78CCD8EB8477A2E6B19F2E7C4A364E97990C1F627_1695903335737_image.png)


Now, you should complete your configuration by configuring the **Git** production branch and clicking on **Create**.

![appwrite-function-github-branch](https://paper-attachments.dropboxusercontent.com/s_B05668B00317FCD740F288B78CCD8EB8477A2E6B19F2E7C4A364E97990C1F627_1695903556050_image.png)

> **NOTE**:  The **CLI** deployment is still available, but **Git** deployment is preferable.

After completing the configurations, you should have an active **Function** deployed like this.

![appwrite-functions-deployment-tab](https://paper-attachments.dropboxusercontent.com/s_B05668B00317FCD740F288B78CCD8EB8477A2E6B19F2E7C4A364E97990C1F627_1696596232552_image.png)


Completing the above configuration will create a new Appwrite function `src/main.js` file in your repository.

Next, navigate to the **Domains** tab from the Functions page and copy the verified generated URL.

![appwrite-functions-domain-tab](https://paper-attachments.dropboxusercontent.com/s_B05668B00317FCD740F288B78CCD8EB8477A2E6B19F2E7C4A364E97990C1F627_1696596093100_image.png)

## Appwrite Functions 1.4 logic

Following the exact function implementation from the Function version 1.3 above—but this time in Appwrite 1.4—navigate to `src/main.js` and paste the code below:

```js
import { Client, Databases, ID } from "node-appwrite";
import querystring from "node:querystring";

export default async ({ req, res, log, error }) => {
  // You can log messages to the console
  log("Hello, Logs!");
  // If something goes wrong, log an error
  error("Hello, Errors!");
  if (req.method === "GET") {
    return res.send(html, 200, { "content-type": "text/html" });
  }
  if (
    req.method === "POST" &&
    req.headers["content-type"] === "application/x-www-form-urlencoded"
  ) {
    const formData = querystring.parse(req.body);
    const message = {
      name: formData.name,
      email: formData.email,
      date: formData.date,
      time: formData.time,
      content: formData.content,
    };
    const client = new Client();
    client
      .setEndpoint("https://cloud.appwrite.io/v1")
      .setProject(process.env.APPWRITE_FUNCTION_PROJECT_ID)
      .setKey(process.env.APPWRITE_API_KEY);
    const databases = new Databases(client);
    const document = await databases.createDocument(
      "650efb16ae5ebb92185a",
      "650efb593f6c9f97c09c",
      ID.unique(),
      message
    );
    return res.send("Message sent");
  }
  return res.send("Not found", 404);
};
```

These are what changed in the above code compared to version 1.3:

- The parameter passed into functions has changed. `req` and `res` have been replaced by the `context` object.
- To improve privacy and logging reliability, new `context.log()` and `context.error()` functions were provided.
- The old way of `req.variables` has been deprecated; variables are now passed into each function as environment variables.
- Some information, like **triggers** and **events**, are now passed in as headers instead of variables.
- The `req` object has been updated to use terminology consistent with typical HTTP concepts, which include familiar concepts like headers, body, HTTP methods, and others.
- By default, the **request** and **response** information is not logged. This is to protect user information by default.
- A response such as `context.res.send("")` is returned. This prevents confusing errors when functions are terminated prematurely before a response is sent.

 
By now, the application should look like this:

https://www.loom.com/share/570cb616f33241e5b9a334057bcd4471?sid=0d91fbb4-e1c0-43dd-aa2b-3858b1dc9bc3


The Appwrite Cloud Functions Execution completed a new Function like this:

![appwrite-function-executions](https://paper-attachments.dropboxusercontent.com/s_B05668B00317FCD740F288B78CCD8EB8477A2E6B19F2E7C4A364E97990C1F627_1695738348395_image.png)


And the Appwrite Cloud Databases updated the database collection like this:

![appwrite-database-tab](https://paper-attachments.dropboxusercontent.com/s_B05668B00317FCD740F288B78CCD8EB8477A2E6B19F2E7C4A364E97990C1F627_1696596358215_image.png)

## Conclusion

This article discussed how to migrate to [Appwrite Functions](https://appwrite.io/docs/references/cloud/client-web/functions) 1.4 and implement them in a Next.js application. This article also provided a detailed and easy guide on creating an Appwrite Cloud project and utilizing the amazing features and the revised syntax of the Appwrite Functions 1.4.

## Resources

Here are some additional resources that might be helpful:

- [Appwrite Cloud](https://cloud.appwrite.io/?utm_source=hackmamba&utm_medium=hackmamba-blog)
- [Appwrite's Functions](https://appwrite.io/docs/references/cloud/client-web/functions)
- [Appwrite’s Functions Development](https://appwrite.io/docs/products/functions/development)
- [Appwrite Cloud 1.4 update post](https://dev.to/appwrite/appwrite-14-brings-command-center-ai-one-click-migrations-and-upgraded-functions-1ch2#:~:text=In%20Appwrite%201.4%2C%20Functions%20are,introduced%20templates%20to%20Appwrite%20Functions.)