How To Build A Media Library With Just 25 Lines of Code - Using GraphQL and Slicknode
Tags: graphql
Published: 2021-04-15 12:17:42

Our friends from [AXOLIST](https://axolist.com/) recently asked us to build a custom media library for their Amazon Content Tool. They wanted to give their users the possibility to upload, manage and update images for their products that they sell on the Amazon marketplace. (Those product images that you see when you shop on Amazon.com)

Background: AXOLIST is a SaaS tool for agencies that help brands sell products on the Amazon marketplace, optimize the content of their product listings for users, search rankings, and ensure compliance.

Now let's see how we added this feature to their Slicknode backend with just a few lines of code. 

## Requirements

To enable this type of functionality, we had to create a solution with the following requirements:

- Since AXOLIST is a SaaS tool, every customer needs to have their own independent media library that **can only be accessed by users that are members of that customer account**.
- Images need to be organized in a **hierarchical folder structure** to make it easy to manage large product portfolios.
- Images will be displayed in **multiple resolutions**: Thumbnails for the listview, and a high-resolution image for a zoomed-in view.
- Users should get a visual warning when they upload an image that has a resolution that is too low for the Amazon marketplace. 
- Folders can be **dragged and dropped** into other folders to quickly (re-)organize the media items in an account.
- Images can be **searched** within each folder.
- Folders should have **unique names** within a subfolder. 
- **Soft-delete functionality** should allow admins to restore a folder that might have been accidentally deleted.

Creating this from scratch requires a significant amount of time for building API routes, data models, migrations, image processing, authorization, etc. With Slicknode, this becomes a task that is done in 5 minutes. Let's take a look!

## Implementation

First, we create the media module using the Slicknode CLI:

```
slicknode module create media
```

Then we add the data model to the schema.graphql file:

```graphql
type Media_Directory implements Node
@index(fields: ["account", "parent", "name"], unique: true)
{
  id: ID!
  account: Account_Account!
  parent: Media_Directory
  name: String!

  children: [Media_Directory!]! @relation(
    path: "Media_Directory=parent.Media_Directory"
  )

  """Date when the directory was deleted, for soft delete"""
  deletedAt: DateTime
}

type Media_Asset implements Node
@index(fields: ["directory", "name"], unique: true)
{
  id: ID!

  name: String!
  directory: Media_Directory!
  account: Account_Account!

  image: Image!
}
```

With this data model, Slicknode automatically generates the GraphQL API, database tables, and business logic that we need to build our media library. We have the tenant separation to give each account its own media library. The built-in image module of Slicknode takes care of image upload, storage, and thumbnail generation. With the composite unique index, we can ensure that the folder names are unique within each folder and with the relations directive, we create the hierarchic folder structure that scales easily. 

To secure the assets and make them only accessible for users of the account, we add a permission query for the directory type. 

```graphql
query DirectoryPermission1($user_id: ID!) {
  scope(role: AUTHENTICATED, operations: [CREATE, UPDATE, READ])
  node(filter: {
    deletedAt: {isNull: true}
    account: {
      users: {
        node: {
          id: { eq: $user_id }
        }
      }
    }
  })
}
```

We use the permission query to enable multi-tenancy and only allow users of an account to see their own directories. We can also use the same permission query to hide directories that have the `deletedAt` value set. The filters will automatically be applied by the Slicknode query engine across the entire GraphQL API. 

That's it. This is all we have to do to build the backend for our media library. [Give it a try](https://slicknode.com/docs/quickstart/) for your next project.