DEV Community

Ivo Meißner for Slicknode

Posted on • Originally published at

How To Build A Media Library With Just 25 Lines of Code - Using GraphQL and Slicknode

Our friends from AXOLIST 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

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.


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!


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

slicknode module create media
Enter fullscreen mode Exit fullscreen mode

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

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!
Enter fullscreen mode Exit fullscreen mode

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.

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

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 for your next project.

Top comments (0)