Build a Production-ready E-commerce Application with Remix and Appwrite

Odewole Babatunde Samson - Dec 16 '22 - - Dev Community

With improvements in the technologies and financial institutions governing buying and selling, we have evolved from traditional buying and selling markets to e-commerce websites.

Remix is a full-stack React framework for building web applications. It provides several helpful features such as server-side rendering, file system–based routing, TypeScript support, built-in support for cookies and sessions, and more.

What we will be building

This post discusses building an e-commerce application that allows us to create, delete and display our products in a Remix application. A custom backend server is not required.

Repository

The source code can be found here

Prerequisites

To get the most out of this project, the following are required:

  • A basic understanding of CSS, JavaScript, and React.js
  • A Docker Desktop installation. Run the docker -v command to verify whether Docker Desktop is installed. If not, install it from here
  • An Appwrite instance running on our computer. Check out this documentation to create a local Appwrite instance. We will use Appwrite’s powerful database service and experience to manage our catalog

Setting up our Remix app

First, we need to run the command below in the terminal to set up a new Remix application.

npx create-remix@latest
Enter fullscreen mode Exit fullscreen mode

The command above triggers a command-line interface (CLI) where we can configure the application. The images below show the configuration options the CLI provides:

remix-cli

After creating our app, change the directory to the project and start a development server with the following command:

cd <name of our project>
npm run dev
Enter fullscreen mode Exit fullscreen mode

Remix will start a development environment accessible by default at http://localhost:3000.

Installing Tailwind CSS

Tailwind CSS is a "utility-first" CSS framework that allows us to rapidly create user interfaces for web applications.

To install Tailwind CSS in our project, run these terminal commands.

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
Enter fullscreen mode Exit fullscreen mode

These commands create two files in the root directory of our project, tailwind.config.js, and postcss.config.js.

In our tailwind.config.js, we add the paths to all our template files with the code below.

module.exports = {
  content: [
    "./app/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
Enter fullscreen mode Exit fullscreen mode

Next, update the scripts in our package.json file to build our development and production CSS.

{
  "scripts": {
    "build": "npm run build:css && remix build",
    "build:css": "tailwindcss -m -i ./styles/app.css -o app/styles/app.css",
    "dev": "concurrently \"npm run dev:css\" \"remix dev\"",
    "dev:css": "tailwindcss -w -i ./styles/app.css -o app/styles/app.css"
  }
}
Enter fullscreen mode Exit fullscreen mode

Next, we create a ./styles/app.css file and add the @tailwind directives for each of Tailwind’s layers.

@tailwind base;
@tailwind components;
@tailwind utilities;
Enter fullscreen mode Exit fullscreen mode

Lastly, we import the compiled ./app/styles/app.css file in our ./app/root.jsx file.

import styles from "./styles/app.css"

export function links() {
  return [{ rel: "stylesheet", href: styles }]
}
Enter fullscreen mode Exit fullscreen mode

Installing Appwrite

Appwrite is an open-source, end-to-end, backend server solution that allows developers to build applications faster.

To use Appwrite in our Remix application, install the Appwrite client-side SDK for web applications.

npm install appwrite
Enter fullscreen mode Exit fullscreen mode

Creating a new Appwrite project

We go to localhost and create a new account to see our console.

On our console, click on the Create Project button to start a new project.

appwrite-create-project-console

After creating a project, scroll down within the Appwrite console and select Add platform.

appwrite-add-platform

Select Web App and Register the Name and Hostname. Complete the registration for the Web App platform.

In our case, we are using localhost, so we insert *localhost

appwrite-web-config

Our project dashboard appears once we have created the project. At the top of the page, click the settings bar to access the Project ID.

appwrite-settings

Now, copy the Project ID, which we need to initialize the Appwrite Web SDK.

Creating the collection and attributes

In the Appwrite Web Console, click on Database, located on the left side of the dashboard.

appwrite-db-console

We create a collection in our database tab by clicking the Create Collection button. This action redirects us to a Permissions page.

appwrite-permission-tab

We'll also assign Read and Write Access to the collection.

Next, go to the attributes tab to create the properties we want a document to have.

appwite-attr

Create a string attribute of productName, an integer attribute of productPrice, an integer attribute of productQuantity, and a string attribute of productImage. We'll use these base attributes and can add more in the future.

Setting up the E-commerce application

To set up our application, we’ll clone this repository and run the command below in the project directory:

$ cd remix
$ npm install
Enter fullscreen mode Exit fullscreen mode

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

Once the development server is running, we can view it on our browser at http://localhost:3000.

Note: We will run into some errors if we ran the app as is.

The E-commerce app homepage should look like this:

ecomm-homepage

Making the e-commerce interact with our database

Creating an anonymous user session
Appwrite requires a user to sign in before reading or writing to a database to enable safety in our application. However, they allow us to create an anonymous session that we'll use in this project.

Open .routes/index.tsx, located in the app folder. Paste the code below to initialize the Appwrite modules:

import { Client, Account, Databases, Query } from 'appwrite';

const client = new Client();
client
  .setEndpoint('http://localhost/v1') // Your Appwrite Endpoint
  .setProject('[PROJECT-ID]');

const account = new Account(client);
const database = new Databases(client);

account.createAnonymousSession().then(
  (response) => {
    console.log(response);
  },
  (error) => {
    console.log(error);
  }
);
Enter fullscreen mode Exit fullscreen mode

Only signed-in users can interact with the Appwrite database, so we created an anonymous session as a workaround.

Note: The PROJECT_ID resides in the Appwrite console.

Creating database documents
In the app/routes/cart.tsx file, let’s write a handleOrders function to create documents in our collection.

const handleOrders = () => {
      let promise = database.createDocument(
        '[DATABASE-ID]',
        '[PRODUCT-COLLECTION-ID]',
         "unique()",
        {
          productName: basket.cart.name,
          productPrice: basket.cart.price,
          productQuantity: basket.cart.quantity,
          productImage: basket.cart.image
        }
      );
      promise.then(
        function (response) {
          console.log(response); // Success
          alert('order has been successfully saved');
        },
        function (error) {
          console.log(error); // Failure
        }
      );
}
Enter fullscreen mode Exit fullscreen mode

This handleOrders function above does the following:

  • Uses the Appwrite createDocument() method, which creates a document using the collection ID and data fields to be stored. This collection ID is the same ID we copied earlier.
  • Alerts us when we have successfully saved our document, then clears the information in our local state variables.

Next, we pass our handleOrders() function into an onClick event-listener on our Link element.

<Link
    to="/checkout"
    className="bg-text text-primary py-3 mt-10 rounded font-semibold text-center"
    onClick ={handleSubmit}
 >
       Checkout
</Link>
Enter fullscreen mode Exit fullscreen mode

Click on the Checkout button and go to the Documents tab on Appwrite's project dashboard to see the saved documents.

Listing documents
To see all we've done, we need to create a function that would fetch all the orders.

In the app/routes/cart.tsx file, we write a getOrders function to list documents in our collection.

const getOrders = () => {
    let promise = database.listDocuments(
        '[DATABASE-ID]',
        '[PRODUCT-COLLECTION-ID]',
    );
    promise.then(
      function (response) {
        console.log(response); // Success
        alert("orders list");
      },
      function (error) {
        console.log(error); // Failure
      }
    );
  };
  useEffect(() => {
    getOrders();
 }, []);
Enter fullscreen mode Exit fullscreen mode

In the code snippet above, we create a getOrders() function to display our bookmarks. We use Appwrite's listDocuments() method to do this.

We pass the DocumentID and collection ID parameter to the getOrders() method to specify what collection we want to access.

Our useEffect() hook runs the getOrders() function.

Deleting documents
In the app/routes/cart.tsx file, let’s create a handleDelete() function to delete documents we no longer want in our collection.

const handleDelete =  () => {
   let promise = database.deleteDocument(
    '[COLLECTION_ID]', 
    '[DOCUMENT_ID]'
   );
   promise.then(
     function (response) {
       console.log(response); // Success
       alert("order have been deleted successfully");
     },
     function (error) {
       console.log(error); // Failure
     }
   );
};
Enter fullscreen mode Exit fullscreen mode

The handleDelete() function above does the following:

  • Finds a document using its collection ID, and the document ID gets passed into the function.
  • Deletes that document using Appwrite’s deleteDocument() method.
  • Alerts us if we delete an item.

Finally, the production-ready E-commerce application looks like this:

Conclusion

This article taught us how to leverage Appwrite's database features to store, list, and delete orders from an E-commerce application. This app can be the basis for a full-fledged inventory creation system for a store. Modify the documents to include handling a proper checkout flow with payment and shipping.

Resources

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .