Last edit: 


Modules allow code reuse and sharing, while protecting the IP of creators.

Directory structure

Module code is split into 2 directories to protect IP. To create a module, split module code into public and private folders, and place all that code into the modules/MODULE_NAME directory.

    ├── public
    └── private

These directories have the same structure as the standard marketplace_builder folder, but if developers try to download files after the module has been deployed to an Instance (marketplace-kit pull), they will only see the files from the public folder.

You can create an Instance and deploy the code as you would usually do, and you still can have the marketplace_builder folder on the top level (this code will not be part of the module but you can use it while developing).

This mechanism allows creators to share their module code, make it configurable (by code in the public folder), but still protect the IP in the private folder.

Example: Module directories

An example of module code split into two directories, inside the modules directory:

├── private
│   └── graph_queries
│       ├── get_customizations.graphql
│       └── get_pages.graphql
└── public
    └── views
        └── pages
            └── admin.liquid

Resource naming conventions and paths

Configuration files placed in a module are treated a bit differently than regular files.
To avoid conflicts between the code of a module and regular code (or between modules) a namespacing strategy is used.

Namespacing rules

1. Assets

You can access assets placed at assets directory in a module using asset_url filter.

Paths for those files are prefixed with modules/MODULE_NAME

Example for modules/admin/assets/app.css:

<link rel="stylesheet" media="screen" href="{{ 'modules/admin/app.css' | asset_url }}">

Example for modules/admin/assets/admin.js:

<script src="{{ 'modules/admin/admin.js' | asset_url }}"></script>

2. Partials

Partials can be referenced with their shorter name - the same as the regular ones. For example, to include
partial saved as modules/admin/private/views/partials/comments.liquid, you should use:

{% include 'modules/admin/comments' %}

3. Layouts

Layout name has the same prefix when referenced within a page:

slug: admin/settings
layout_name: modules/admin/settings

4. Other resources (Authorization Policy, Graph Query, etc.)

When creating a module you don't have to add prefix to the name but when you use it (inside or outside of module scope) you have to provide
the modules/module_name/ prefix.


Authorization policy

Authorization policy definition looks like any other:

name: can_view_blog_posts
redirect_to: /blog
flash_alert: Please log in to access this page.
{% query_graph "modules/admin/get_blog_user", result_name: "g" %}

But within page/form it is referenced with a prefix:

  - modules/admin/can_view_blog_posts

Graphql Query

Query looks like any other query:

query get_blog_instance(
  $current_user_id: ID
  $slug: String
  $scope: String
) {
) {

But it is referenced with the prefix:

{%- query_graph 'modules/admin/get_blog_instance', scope: 'blog', result_name: 'bi', slug: url_params.slug -%}

Related topics


We are always happy to help with any questions you may have. Check out our Help page, or contact us.