How to Manage Multiple Appwrite Functions in a Single Repository
Tosin Moronfolu
Posted on October 27, 2023
In recent years, serverless computing has revolutionized the developer landscape, gaining widespread adoption for its benefits. Within this serverless paradigm, developers utilize serverless functions to execute tasks while reducing server costs and ensuring the scalability of their applications.
Appwrite, an open-source backend-as-a-service (BaaS) provider, has embraced this serverless revolution to empower developers further. With Appwrite's robust platform, developers can harness the full potential of serverless functions to create highly responsive and cost-effective web applications.
This article explores how to develop serverless functions on Appwrite and manage functions in a single GitHub repository. We'll build a Nuxt.js app that showcases how to create, use, and manage serverless functions with Appwrite.
Prerequisites
To follow along with this article, you’ll need the following:
- A basic understanding of JavaScript and Nuxt.js
- Node.js installed on your machine and a basic understanding of Node.js
- An Appwrite Cloud account (create one here)
Repository
All the code used in this article can be found in this repository:
https://github.com/folucode/quote-todo-app
Function setup
In this article, we’ll demonstrate building a simple to-do suggestion app: an app that suggests random things to do and also gives us motivational quotes to help us get motivated to complete the task. We’ll create two functions, one to suggest a random task and the other to give us a motivational quote. To achieve this, we’ll use Nuxt.js for the frontend of the app.
Creating the functions
First, let’s log in to our Appwrite cloud account and create a new project by clicking Create project and naming it Task-Suggestion
.
Next, on the sidebar, click on Functions and then Create function.
Since we’ll be managing our functions in a GitHub repository, click on the GitHub button, choose GitHub account, and then give it access to all repositories by selecting All repositories. Then, click on Install & Authorize.
After this, we‘ll be redirected to Appwrite for a dropdown list of our GitHub repositories. For this project, we will be using the Node.js runtime for our function.
Click on Node.js in the Quickstart section to set up our function and also create a GitHub repository to manage it. Here are the specifics:
- Configuration: Name the function Get Quote and choose any Node.js runtimes from the dropdown list. Click on Next.
- Variables: We won't use environment variables in our function, so leave it as it is and click Next.
- Connect: Select the option to create a new repository and click Next.
- Repository: Give the repository a name, make it private or public, and then click Next. Since we connected our GitHub account earlier, this new repository will be created in the GitHub account to which we connected the project.
-
Branch: Select the main branch, type
functions/get_quote
as the root directory of the function, and then click Create. Putting each function in its folder inside a central directory named functions is standard practice. This facilitates easy management of each function.
After this, our function is successfully created and deployed. It will also be in a repository on our GitHub profile.
Following the same steps, let’s create a new Get Task
function. In the Connect section, select Add to existing repository. Next, select the previous repository we created for the Get Quote
function. In the Branch section, type functions/get_task
as the root directory and then click Create.
Appwrite will deploy the new function, and it will appear in the same repository. The GitHub repository should now look like this:
and our Appwrite dashboard should look like this:
Writing the function logic
Now that we've created our functions, deployed them, and connected them to GitHub, we have to write the logic for our functions.
We first need to clone the project from GitHub using the following command:
git clone <repo-git-url>
Open the project in a code editor and navigate to functions > get_quote > src > main.js. We’ll see some boilerplate code that was put in there by Appwrite. Replace the boilerplate code with the code below:
export default async ({ req, res, log, error }) => {
try {
const motivationalQuotes = [
{
quote: "Success is not in what you have, but who you are.",
author: "Bo Bennett"
},
{
quote: "Your time is limited, don't waste it living someone else's life.",
author: "Steve Jobs"
},
{
quote: "The only person you are destined to become is the person you decide to be.",
author: "Ralph Waldo Emerson"
},
{
quote: "The best revenge is massive success.",
author: "Frank Sinatra"
},
{
quote: "Don't be afraid to give up the good to go for the great.",
author: "John D. Rockefeller"
}
];
const randomIndex = Math.floor(Math.random() * motivationalQuotes.length);
const randomQuote = motivationalQuotes[randomIndex];
return res.json({
statusCode: 200,
body: JSON.stringify({ quote: randomQuote.quote, author: randomQuote.author }),
});
} catch (error) {
return res.json({
statusCode: 200,
body: JSON.stringify({ error: 'An error occurred while fetching the quote.' }),
});
}
};
In this function, we define an array of motivational quotes, each being an object with a quote and an author. We then select a random quote and author and return a JSON response containing the selected quote and author. In case of any errors during this process, we return a JSON response indicating an error occurred.
Next, navigate to functions > get_task > src > main.js and replace the boilerplate code with this:
export default async ({ req, res, log, error }) => {
try {
const tasks = [
"Buy groceries",
"Go for a run",
"Read a book",
"Call a friend",
"Write a blog post",
"Clean the house",
"Cook dinner",
"Watch a movie",
"Take a walk in the park",
"Plan a vacation",
"Organize your closet",
"Listen to music",
"Practice mindfulness",
"Try a new recipe",
"Write in my journal",
];
const randomTaskIndex = Math.floor(Math.random() * tasks.length);
const randomTask = tasks[randomTodoIndex];
return res.json({
statusCode: 200,
body: JSON.stringify({ task: randomTask }),
});
} catch (error) {
return res.json({
statusCode: 200,
body: JSON.stringify({ error: 'An error occurred while fetching task.' }),
});
}
};
In the function above, we define an array of tasks, then select a random task and return a JSON response containing the chosen task. In case of any errors during this process, we return a JSON response indicating that an error occurred.
After doing this, push the changes to GitHub, and our functions in Appwrite will automatically redeploy with the new changes applied.
Frontend setup
We're using Nuxt.js for our frontend to implement the functions. To install Node, go to the Node.js website and follow the instructions to install the software compatible with our operating system.
Then, verify the installation using:
node -v
To create the Nuxt.js app, run the command below; it will automatically set up a boilerplate Nuxt.js app:
npx nuxi@latest init <project-name>
Next, change the directory to the directory of the app we just created:
cd <project-name>
Now run npm run dev
or yarn dev
to start the development server on http://localhost:3000
.
Building the functionality
Open the app.vue
file and replace the boilerplate code with the code below:
<template>
<div class="parent">
<div class="quote">
<blockquote>{{ quote }}</blockquote>
<p>- {{ author }} - </p>
</div>
<div class="todo">
<p>- {{ task }} - </p>
</div>
<div class="get-quote">
<button @click="getQuote">Get Quote</button>
</div>
<div class="get-todo">
<button @click="getTask">Get Todo</button>
</div>
</div>
</template>
<style>
.parent {
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-template-rows: repeat(2, 1fr);
grid-column-gap: 0px;
grid-row-gap: 0px;
justify-content: center;
align-items: center;
place-items: center;
width: 400px;
margin-top: 150px;
margin-left: 35%;
}
.quote {
grid-area: 1 / 1 / 2 / 2;
}
.todo {
grid-area: 1 / 2 / 2 / 3;
}
.get-quote {
grid-area: 2 / 1 / 3 / 2;
}
.get-todo {
grid-area: 2 / 2 / 3 / 3;
}
.quote {
width: 250px;
border-radius: 5px;
padding: 5px;
text-align: center;
background-color: rgb(96, 206, 206);
margin: 10px;
}
.todo {
width: 250px;
border-radius: 5px;
padding: 5px;
text-align: center;
background-color: rgb(225, 73, 73);
}
blockquote {
font-weight: bolder;
font-size: larger;
color: blanchedalmond;
font-style: italic;
}
p {
font-size: larger;
}
button {
width: 150px;
padding: 10px;
background-color: brown;
color: white;
border: 2px solid white;
border-radius: 5px;
}
button:hover {
cursor: pointer;
}
</style>
In the code above, we set up the UI for the app, define its positioning, and style it. Now, we need to implement the getQuote
and getTask
functions.
After the style tag, add the code below:
<script>
import { Client, Functions } from 'appwrite';
const client = new Client()
.setEndpoint('https://cloud.appwrite.io/v1')
.setProject('[PROJECT-ID]');
const functions = new Functions(client);
export default {
methods: {
async getQuote() {
try {
const response = await functions.createExecution(
'[FUNCTION-ID]',
JSON.stringify({}),
false,
'/',
'GET',
{}
);
const result = JSON.parse(response.responseBody);
const body = JSON.parse(result.body);
this.quote = body.quote;
this.author = body.author;
} catch (error) {
console.error('Error fetching the quote:', error);
}
},
async getTask() {
try {
const response = await functions.createExecution(
'[FUNCTION-ID]',
JSON.stringify({}),
false,
'/',
'GET',
{}
);
const result = JSON.parse(response.responseBody);
const body = JSON.parse(result.body);
this.task = body.task;
} catch (error) {
console.error('Error fetching the quote:', error);
}
},
},
data() {
return {
quote: '',
author: '',
task: '',
};
},
};
</script>
In the code above, we:
- Import the
appwrite
library to create a client and interact with Appwrite functions. - Initialize the Appwrite client with the endpoint and our
project ID
. We get theproject ID
from our Appwrite dashboard by clicking on the Overview tab. - Define the two methods,
getQuote
andgetTask
, which are used to call specific Appwrite functions.-
getQuote
sends a request to theGet Quote
Appwrite function using itsfunction ID
and expects a response containing aquote
andauthor
. It then updates the Nuxt component's data propertiesquote
andauthor
with the retrieved values. We get thefunction ID
from our Appwrite dashboard by clicking the Functions tab. -
getTask
sends a request to theGet Task
Appwrite function using itsfunction ID
and expects a response containing a Task item. It updates the Nuxt component'stask
data property with the retrieved value. We get thefunction ID
from our Appwrite dashboard by clicking the Functions tab.
-
- Initialize the Nuxt component's data properties with empty values, including quote, author, and task.
When we run our app, it should work like so:
https://www.loom.com/share/27fe40dc23574b198d9e5ad9cbb8716a?sid=cf39da90-9d6d-419e-98d0-7f640c929890
Conclusion
In this article, we've learned how to create and manage Appwrite functions all in one place on GitHub. We made two functions that perform specific tasks, helping us understand how to use Appwrite functions in our projects. We also learned that Appwrite deploys our functions automatically whenever we make changes, making our work smooth, and this simplifies the development process and ensures that our applications remain seamlessly up-to-date.
We also saw how we can have our functions in the same repository as our app. This helped to easily manage and sync all changes all in one single repository.
Resources
Posted on October 27, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.