Skip to main content

Introduction

The Appwrite data provider enables you to build Refine applications with Appwrite, an open-source backend platform that provides authentication, databases, storage, and more.

Installation

Install the Appwrite data provider package:
npm install @refinedev/appwrite

Setup

1

Create Appwrite project

First, create an Appwrite project at cloud.appwrite.io or self-host Appwrite.
2

Create Appwrite client

Create an Appwrite client with your project configuration:
import { Appwrite } from "@refinedev/appwrite";

const appwriteClient = new Appwrite();
appwriteClient
  .setEndpoint("https://cloud.appwrite.io/v1")
  .setProject("YOUR_PROJECT_ID");
3

Configure data provider

Configure the Refine app with the Appwrite data provider:
import { Refine } from "@refinedev/core";
import { dataProvider, liveProvider, Appwrite } from "@refinedev/appwrite";

const appwriteClient = new Appwrite();
appwriteClient
  .setEndpoint("https://cloud.appwrite.io/v1")
  .setProject("YOUR_PROJECT_ID");

const App = () => {
  return (
    <Refine
      dataProvider={dataProvider(appwriteClient, {
        databaseId: "default",
      })}
      liveProvider={liveProvider(appwriteClient, {
        databaseId: "default",
      })}
    >
      {/* Your app content */}
    </Refine>
  );
};

Basic Usage

Get List

Fetch a list of documents from an Appwrite collection:
import { useList } from "@refinedev/core";

const { data } = useList({
  resource: "posts",
  pagination: {
    current: 1,
    pageSize: 10,
  },
  sorters: [
    {
      field: "$createdAt",
      order: "desc",
    },
  ],
  filters: [
    {
      field: "status",
      operator: "eq",
      value: "published",
    },
  ],
});

Get One

Fetch a single document by ID:
import { useOne } from "@refinedev/core";

const { data } = useOne({
  resource: "posts",
  id: "document-id",
});

Create

Create a new document:
import { useCreate } from "@refinedev/core";

const { mutate } = useCreate();

const handleSubmit = (values) => {
  mutate({
    resource: "posts",
    values: {
      title: values.title,
      content: values.content,
      status: "draft",
    },
  });
};

Update

Update an existing document:
import { useUpdate } from "@refinedev/core";

const { mutate } = useUpdate();

const handleUpdate = (id, values) => {
  mutate({
    resource: "posts",
    id,
    values: {
      title: values.title,
      content: values.content,
    },
  });
};

Delete

Delete a document:
import { useDelete } from "@refinedev/core";

const { mutate } = useDelete();

const handleDelete = (id) => {
  mutate({
    resource: "posts",
    id,
  });
};

Real-time Updates

Appwrite supports real-time subscriptions for automatic data updates:
import { Refine } from "@refinedev/core";
import { dataProvider, liveProvider, Appwrite } from "@refinedev/appwrite";

const appwriteClient = new Appwrite();
appwriteClient
  .setEndpoint("https://cloud.appwrite.io/v1")
  .setProject("YOUR_PROJECT_ID");

const App = () => {
  return (
    <Refine
      dataProvider={dataProvider(appwriteClient, {
        databaseId: "default",
      })}
      liveProvider={liveProvider(appwriteClient, {
        databaseId: "default",
      })}
      options={{
        liveMode: "auto", // Enable automatic real-time updates
      }}
    >
      {/* Your app content */}
    </Refine>
  );
};

Authentication

Implement authentication using Appwrite’s Account service:
import { Refine } from "@refinedev/core";
import { Account, Appwrite } from "@refinedev/appwrite";

const appwriteClient = new Appwrite();
appwriteClient
  .setEndpoint("https://cloud.appwrite.io/v1")
  .setProject("YOUR_PROJECT_ID");

const account = new Account(appwriteClient);

const authProvider = {
  login: async ({ email, password }) => {
    try {
      await account.createEmailSession(email, password);
      return {
        success: true,
        redirectTo: "/",
      };
    } catch (error) {
      return {
        success: false,
        error,
      };
    }
  },
  logout: async () => {
    try {
      await account.deleteSession("current");
      return {
        success: true,
        redirectTo: "/login",
      };
    } catch (error) {
      return {
        success: false,
        error,
      };
    }
  },
  check: async () => {
    try {
      await account.get();
      return {
        authenticated: true,
      };
    } catch (error) {
      return {
        authenticated: false,
        redirectTo: "/login",
      };
    }
  },
  getIdentity: async () => {
    try {
      const user = await account.get();
      return {
        id: user.$id,
        name: user.name,
        email: user.email,
      };
    } catch (error) {
      return null;
    }
  },
  onError: async (error) => {
    console.error(error);
    return { error };
  },
};

const App = () => {
  return (
    <Refine
      dataProvider={dataProvider(appwriteClient, {
        databaseId: "default",
      })}
      authProvider={authProvider}
    >
      {/* Your app content */}
    </Refine>
  );
};

Storage Integration

Work with Appwrite Storage for file uploads:
import { useState } from "react";
import { Storage, Appwrite } from "@refinedev/appwrite";
import { ID } from "@refinedev/appwrite";

const appwriteClient = new Appwrite();
appwriteClient
  .setEndpoint("https://cloud.appwrite.io/v1")
  .setProject("YOUR_PROJECT_ID");

const storage = new Storage(appwriteClient);

const FileUpload = () => {
  const [uploading, setUploading] = useState(false);

  const handleUpload = async (file: File) => {
    try {
      setUploading(true);

      const response = await storage.createFile(
        "YOUR_BUCKET_ID",
        ID.unique(),
        file
      );

      const fileUrl = storage.getFileView("YOUR_BUCKET_ID", response.$id);
      
      return fileUrl;
    } catch (error) {
      console.error("Error uploading file:", error);
    } finally {
      setUploading(false);
    }
  };

  return (
    <input
      type="file"
      onChange={(e) => {
        const file = e.target.files?.[0];
        if (file) {
          handleUpload(file);
        }
      }}
      disabled={uploading}
    />
  );
};

Filtering

Appwrite supports various filter operators:
import { useList } from "@refinedev/core";

const { data } = useList({
  resource: "posts",
  filters: [
    {
      field: "title",
      operator: "contains",
      value: "tutorial",
    },
    {
      field: "views",
      operator: "gte",
      value: 100,
    },
    {
      field: "status",
      operator: "in",
      value: ["published", "featured"],
    },
  ],
});

Multiple Databases

Work with multiple Appwrite databases:
import { Refine } from "@refinedev/core";
import { dataProvider, Appwrite } from "@refinedev/appwrite";

const appwriteClient = new Appwrite();
appwriteClient
  .setEndpoint("https://cloud.appwrite.io/v1")
  .setProject("YOUR_PROJECT_ID");

const App = () => {
  return (
    <Refine
      dataProvider={{
        default: dataProvider(appwriteClient, {
          databaseId: "main-database",
        }),
        analytics: dataProvider(appwriteClient, {
          databaseId: "analytics-database",
        }),
      }}
    >
      {/* Your app content */}
    </Refine>
  );
};
Then specify the database in your resource:
const { data } = useList({
  resource: "events",
  meta: {
    dataProviderName: "analytics",
  },
});

Complete Example

import { Refine } from "@refinedev/core";
import {
  dataProvider,
  liveProvider,
  Appwrite,
  Account,
} from "@refinedev/appwrite";
import routerProvider from "@refinedev/react-router";
import { BrowserRouter } from "react-router";

const appwriteClient = new Appwrite();
appwriteClient
  .setEndpoint(process.env.REACT_APP_APPWRITE_ENDPOINT!)
  .setProject(process.env.REACT_APP_APPWRITE_PROJECT!);

const account = new Account(appwriteClient);

const authProvider = {
  login: async ({ email, password }) => {
    try {
      await account.createEmailSession(email, password);
      return { success: true, redirectTo: "/" };
    } catch (error) {
      return { success: false, error };
    }
  },
  logout: async () => {
    try {
      await account.deleteSession("current");
      return { success: true, redirectTo: "/login" };
    } catch (error) {
      return { success: false, error };
    }
  },
  check: async () => {
    try {
      await account.get();
      return { authenticated: true };
    } catch (error) {
      return { authenticated: false, redirectTo: "/login" };
    }
  },
  getIdentity: async () => {
    try {
      const user = await account.get();
      return { id: user.$id, name: user.name, email: user.email };
    } catch (error) {
      return null;
    }
  },
  onError: async (error) => {
    console.error(error);
    return { error };
  },
};

const App = () => {
  return (
    <BrowserRouter>
      <Refine
        dataProvider={dataProvider(appwriteClient, {
          databaseId: "default",
        })}
        liveProvider={liveProvider(appwriteClient, {
          databaseId: "default",
        })}
        authProvider={authProvider}
        routerProvider={routerProvider}
        options={{ liveMode: "auto" }}
        resources={[
          {
            name: "posts",
            list: "/posts",
            create: "/posts/create",
            edit: "/posts/edit/:id",
            show: "/posts/show/:id",
          },
        ]}
      >
        {/* Your routes and pages */}
      </Refine>
    </BrowserRouter>
  );
};

export default App;

Supported Operators

The Appwrite data provider supports the following filter operators:
  • eq: Equals
  • ne: Not equals
  • lt: Less than
  • lte: Less than or equal
  • gt: Greater than
  • gte: Greater than or equal
  • contains: Contains (text search)
  • in: In array
  • nin: Not in array
  • between: Between two values

Next Steps

Data Providers Overview

Learn about other data providers

Appwrite Documentation

Explore Appwrite features

Build docs developers (and LLMs) love