Creating reliable and practical applications is of the utmost importance in modern web development. Frameworks and tools that not only speed up the development process but also provide better functionality and performance are constantly sought after by developers. In this situation, the pairing of Appwrite and Svelte stands out as a complete toolkit that enables programmers to create feature-rich web applications quickly.
Appwrite, an open-source backend as a service (BaaS) platform, provides developers with many services like managing user authentication, data storage, file storage, and more with its intuitive APIs that abstract complex backend operations, allowing developers to focus on building scalable frontend applications.
Svelte is a free and open-source frontend component framework used to build user interfaces by compiling components at build time without needing a virtual DOM resulting in faster rendering.
In this article, you will learn how to use Appwrite’s API to create a list app with features like task creation and deletion and storing the data in Appwrite Cloud leveraging Appwrite, Svelte, and Tailwind CSS for styling.
The complete source code for this project is in this GitHub repo.
To try out the live demo, check it out here.
Throughout this tutorial, you will need the following:
With Appwrite Cloud, you do not need to run a local instance on your system using Docker. Everything happens in the cloud.
For setup, go to your Appwrite Cloud admin console and create a new project by clicking the + Create project button.
Creating a database
The database section allows you to edit, create, and view your collections. Navigating into the completed project, click the Databases tab on the console's left pane and create a new database.
Creating collections
Once you have created the database, it is time to add a new collection to your project. Under the Collections tab, click the + Create collection button and give it a name.
Navigate into the Collections to define and create your data structure by adding attributes.
Here’s what your attributes should look like:
Attribute Key |
Attribute type |
Size |
Default value |
Required |
---|---|---|---|---|
item |
string |
255 |
- |
Yes |
Still in the Collections menu, under the Settings tab, change the read and write permissions and the delete permission for your collection.
This step is vital as it would validate the requests coming from the client side into the Appwrite Cloud console.
On the console home page, click on the Overview tab and scroll to the section Integrations. Click on the Add platform and select one of the options from the drop-down.
PS: For this application, select the Web App option.
Web
To add the web platform, give it a Name and Host. The Name can be anything you desire, and the Host can be the domain under which the web project has access during development. The Host can use the asterisk (*) symbol to locally test the web app.
To create a new Svelte project, run this command in the command line interface (CLI) to scaffold the app.
npm create svelte@latest list-app
Follow the instructions on the terminal as described below:
Accept the installation with the y
flag
Select the Skeleton project from the Svelte app template
For type checking with TypeScript, choose No. If otherwise, and you are comfortable using TS, select it
The last option is optional if you decide to add it to the project
Use the following command below to begin the next steps:
cd listsApp
npm install (or pnpm install, etc)
git init && git add -A && git commit -m "Initial commit" (optional)
npm run dev
The command above does the following:
cd
: navigate to the created Svelte project directorynpm
git
commands initialize, stage, and save a snapshot of the current project state and keep track of your changes5173
to preview the app
Appwrite SDK
Launch your terminal and type the following command to install the Appwrite Web SDK to your project:
npm install appwrite
Tailwind CSS
Tailwind is a utility-first CSS framework packed with classes directly in your markup. The best way to install Tailwind CSS onto your project is by using the Tailwind CLI tool. Check out the Sveltekit framework guide and follow this process.
The UI for the list app will display all the data from the documents in Appwrite Cloud and can delete an item with a click.
Create a new folder called lib in the src directory. Next, create a new file named, ItemList.svelte.
Now, update these components ItemList.svelte and +page.svelte with the following code:
src/lib/ItemList.svelte
<script>
export let list;
</script>
<button type="button">
{list}
</button>
The above code snippets do the following:
ItemList
component
src/routes/+page.svelte
<script>
import ItemList from "../lib/ItemList.svelte";
</script>
<div
class="w-4/5 mx-auto max-w-6xl flex flex-col lg:w-6/12 select-none min-h-screen"
>
<p class="text-center my-6">Delete an item with a click.</p>
<img
src="assets/app-launch.svg"
alt="Launch rocket"
class="mx-auto w-3/4 lg:w-2/4"
/>
<input
type="text"
placeholder="enter item"
class="bg-gray-200 p-4 border-0 text-slate-600 rounded-lg text-center text-xl my-3"
/>
<ul class="flex p-0 flex-wrap gap-3 mt-4">
<li
class="md:text-4xl lg:text-2xl bg-slate-100 p-5 rounded-lg grow text-center shadow hover:bg-orange-200 cursor-pointer"
>
<ItemList list={"Watch the superbowl half-time show"} />
</li>
</ul>
<footer class="mt-auto">
<div class="mt-10 text-center text-gray-500">
<address>
Built by
<span class="text-blue-600">
<a href="https://twitter.com/terieyenike" target="_">Teri</a>
</span>
© 2023
</address>
<div>
<p>
Fork, clone, and star this
<a
href="https://github.com/Terieyenike/appwrite-svelte-list-app"
target="_"
rel="noopener noreferrer"
class="text-blue-600">repo</a
>
</p>
</div>
<p class="text-sm">Appwrite x Svelte x Tailwind CSS</p>
</div>
</footer>
</div>
In the code snippets above, the following occurs:
ItemList
list
in the ItemList
component
Here’s what you should see:
PS: So far, the app is static.
Environment variables are dynamic values set in a program, operating system (OS), or application accessible in a runtime environment. They keep sensitive information away from the application code.
Create a new file, .env
, in the root of the project directory and copy-paste this code:
.env
PUBLIC_DATABASE_ID="<DATABASE_ID>"
PUBLIC_COLLECTION_ID="<COLLECTION_ID>"
PUBLIC_PROJECT_ID="<PROJECT_ID>"
PUBLIC_INSTANCE_URL="https://cloud.appwrite.io/v1"
Replace all the values in the quotation marks with the actual values from your Appwrite Cloud admin console.
Initializing the Appwrite client
Let’s create a file named utils.js
in the src directory. Copy-paste this code:
utils.js
import {
PUBLIC_DATABASE_ID,
PUBLIC_COLLECTION_ID,
PUBLIC_PROJECT_ID,
PUBLIC_INSTANCE_URL,
} from "$env/static/public";
import { Client, Databases, ID, Query } from "appwrite";
const client = new Client();
const databases = new Databases(client);
client.setEndpoint(PUBLIC_INSTANCE_URL).setProject(PUBLIC_PROJECT_ID);
export const create = (data) =>
databases.createDocument(
PUBLIC_DATABASE_ID,
PUBLIC_COLLECTION_ID,
ID.unique(),
data
);
export const getList = databases.listDocuments(
PUBLIC_DATABASE_ID,
PUBLIC_COLLECTION_ID,
[Query.orderDesc("$createdAt")]
);
export const deleteList = (database_id, collection_id, data) =>
databases.deleteDocument(database_id, collection_id, data);
The code above won’t allow your application to run in development. But when you want to push your project code to GitHub, use this instead and place the .env file in the .gitignore file.
For now, let’s use this method with the code instead:
utils.js
import { Client, Databases, ID, Query } from "appwrite";
const client = new Client();
const databases = new Databases(client);
client
.setEndpoint("https://cloud.appwrite.io/v1")
.setProject("PROJECT_ID");
export const create = (data) =>
databases.createDocument(
"[DATABASE_ID]",
"[COLLECTION_ID]",
ID.unique(),
data
);
export const getList = databases.listDocuments(
"[DATABASE_ID]",
"[COLLECTION_ID]",
[Query.orderDesc("$createdAt")]
);
export const deleteList = (database_id, collection_id, data) =>
databases.deleteDocument(database_id, collection_id, data);
The code above does the following:
Since this is a CRUD application, let’s handle sending a new item to Appwrite Cloud. Before updating the +page.svelte
page, create another file named store.js
in the src directory.
Copy-paste this code:
src/store.js
import { writable } from "svelte/store";
export const data = writable({
name: "",
});
In Svelte, the writable function is a built-in store creator that enables you to create a writable store with values from outside a component.
Now that is taken care of, update the +page.svelte
components:
src/routes/+page.svelte
<script>
import { create } from "../utils";
import { data } from "../store";
...
function addToList(e) {
if (!$data.name) {
return;
} else if (e.key !== "Enter") {
return;
}
create({
item: $data.name,
}).then(
function (response) {
window.location.reload();
},
function (error) {
console.log(error);
}
);
$data.name = "";
}
</script>
<div
class="w-4/5 mx-auto max-w-6xl flex flex-col lg:w-6/12 select-none min-h-screen"
>
<p class="text-center my-6">Delete an item with a click.</p>
<!-- img src element -->
<input
type="text"
placeholder="enter item"
on:keydown={addToList}
bind:value={$data.name}
class="bg-gray-200 p-4 border-0 text-slate-600 rounded-lg text-center text-xl my-3"
/>
<ul class="flex p-0 flex-wrap gap-3 mt-4">
<li
class="md:text-4xl lg:text-2xl bg-slate-100 p-5 rounded-lg grow text-center shadow hover:bg-orange-200 cursor-pointer"
>
<ItemList list={"Watch the superbowl half-time show"} />
</li>
</ul>
<!-- Footer element -->
</div>
At this point, the code above does the following:
create
function as well as the store dataaddToList
function, nothing happens if no value is present in the input field. Also, with the create
function, the key item reads the value, $data.name
, which is saved in Appwrite if successful. After that, the page reloads immediately.
Let’s try sending an item to Appwrite Cloud. Head over to your Appwrite console to confirm the value is stored.
This section displays the list of items stored in Appwrite on the client side. Again, update the code in the +page.svelte
component.
src/routes/+page.svelte
<script>
import { onMount } from "svelte";
import { getList, create } from "../utils";
...
let lists = [];
onMount(() => {
getList.then(
function (response) {
lists = response.documents;
},
function (error) {
console.log(error);
}
);
});
// addToList function
</script>
<div
class="w-4/5 mx-auto max-w-6xl flex flex-col lg:w-6/12 select-none min-h-screen"
>
<!-- p, img, input element -->
<ul class="flex p-0 flex-wrap gap-3 mt-4">
{#if lists.length == 0}
<p class="m-auto mt-8">No data in the database</p>
{:else}
{#each lists as list (list.$id)}
<li
class="md:text-4xl lg:text-2xl bg-slate-100 p-5 rounded-lg grow text-center shadow hover:bg-orange-200 cursor-pointer"
>
<ItemList {list} />
</li>
{/each}
{/if}
</ul>
<!-- Footer element -->
</div>
In the code snippet above, the following occurs:
onMount
lifecycle function, as well as the getList functiononMount
function is called immediately when a component is first rendered and inserted into the DOMthen()
method returns a promise<ul>
element, loop through the lists array using the #each
expressionItemList
component
View the entire code for the +page.svelte
file in this gist:
Over in the ItemList component, update the file:
src/lib/ItemList.svelte
<script>
import { deleteList } from "../utils";
...
function handleDeleteListItem() {
deleteList(list.$databaseId, list.$collectionId, list.$id).then(
function (response) {
console.log(`${list.item} successfully deleted`);
window.location.reload();
},
function (error) {
console.log(error);
}
);
}
</script>
<button type="button" on:click={handleDeleteListItem}>
{list.item}
</button>
In this scenario, the code above does this:
deleteList
functionhandleDeleteListItem
function will delete an item from the list array on click of a buttonreload()
method
Building a list app using the powerful combination of Svelte and Appwrite brings together the best in frontend development and backend services.
In conclusion, the connection between Svelte and Appwrite enables developers to build web applications efficiently with enhanced performance and robust backend functionality.
Try using Appwrite Cloud today, and you will keep coming back for more, just like this demonstration list app.