Skip to content

Developers · Modules

Modules Overview

Last updated 7 November 2026

Modules allow for code reuse and sharing while, at the same time, protecting the intellectual property (IP) of creators and developers.

Directory structure

In your codebase, the directory needs to be at the same level as the directory.

You can split module code into two directories to protect IP (Intellectual Property). To create a module, split the module code into and folders, and place all that code into the directory.

app
modules
└── MODULE_NAME
    ├── public
    │   └── assets
    └── private
        └─ assets

and directories have the same structure as the standard folder. Still, if developers try to download or preview files after the module has been deployed to an Instance, they can only access the files from the folder.

In general, when referencing files that are part of a module, Insites uses a prefix that does not include any or folders (for example,  instead of ). This behavior means that creators should not create files with the same name in both folders, as one will overwrite the other. This behavior also gives creators flexibility: if they want to change the scope of the file, they can move it between the private and public folders without changing the code.

Both folders are valid. Put the site itself in . Put code you want to reuse or package in . Code in is not part of any module.

This mechanism allows creators to share their module code and make it configurable (by code in the folder) while protecting the IP in the folder.

Example: Module directories

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

my_admin
├── private
│   └── graphql
│       ├── get_records.graphql
│       └── get_pages.graphql
└── public
    └── views
        └── pages
            └── admin.liquid

Namespacing rules

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

The general rule of accessing files in modules is to prefix paths with . Remember that skipping resource type applies just like it does without modules. This behavior means that when you access a , you type a path to it as if you were in the partial's directory.

When you use app:
Is accessed by path:

When you use module:
Is accessed by path:

The only difference is the prefix.

Examples

This section demonstrates the use of Modules for the following Insites elements:

  • Assets
  • Partials
  • Layouts
  • Records
  • Authorization Policies
  • Translations

Assets

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

Paths for those files are prefixed with

modules/admin/public/assets/app.css

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

modules/admin/public/assets/admin.js

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

Partials

Partials can be referenced with their shorter name - the same as the regular ones.
For example, to include partial saved as , you should use:

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

Layouts

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

modules/admin/public/views/layouts/settings.liquid

slug: admin/settings
layout: modules/admin/settings

Records

A table is defined in the module's folder.

modules/admin/private/schema/resume.yml

name: resume
properties:
  - name: title
    type: string

A query reads it by the table name with the module prefix.

modules/admin/private/graphql/get_resumes.graphql

query get_resumes {
  records(
    per_page: 5
    filter: {
      table: { value: "modules/admin/resume" }
    }
  ) {
    results {
      id
    }
  }
}

Authorization Policies

modules/admin/public/authorization_policies/can_view_blog_posts

---
name: can_view_blog_posts
redirect_to: /blog
flash_alert: Please log in to access this page.
---
true

Within the page/form, it is referenced with a prefix:

authorization_policies:
  - modules/admin/can_view_blog_posts

GraphQL Query

The query looks like any other query:

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

But it is referenced with the prefix:

modules/admin/public/graphql/get_blog_instance.graphql

{%- graphql bi = "modules/admin/get_blog_instance" -%}

Translations

You should place the Translations YAML files for the module in: .

But when used in the module code, they should be prefixed, such as in the example below:

{{ "modules/admin/strings.sample_string" | t }}

Related topic

Creating a Module