File structure

A component is made up of a set of files organized into a directory, with at least a manifest.json file and a Common JS JavaScript file.

Generally, a set of components is stored as a set of multiple directories and deployed into a single Git repository, making it easy to collaborate on a collection of components that form an implementation of a design system.

All the files and all the resources must be in the same directory as the manifest.json file, or in a child directory of that directory.

This image shows a directory structure with the manifest.json and main.cjs files in the root directory
Figure 1. Default directory structure

manifest.json

The manifest.json is a JSON Schema file, which contains metadata that describes how to execute this component.

The following example shows the structure of a basic manifest.json file:

{
  "$schema": "http://localhost:3000/schemas/v1.json#", (1)
  "version": "1.0.0", (2)
  "name": "helloworld1", (3)
  "displayName": "Hello World test component",  (4)
  "namespace": "test-components",  (5)
  "icon": {  (6)
    "id": "list_alt", (7)
    "color": { (8)
      "type": "hex", (9)
      "value": "#2D2D2D" (10)
      }
  },
  "description": "A demonstration component for Hello World tutorial.", (11)
  "mainFunction": "main", (12)
  "functions": [ (13)
    {
      "name": "main", (14)
      "entry": "main.cjs", (15)

      "input": { (16)
        "type": "object",
        "properties": {
          "entryfield": {
            "type": "string"
          }
        },
        "required": ["entryfield"] (17)
      },
      "output": { "responseType": "html" } (18)
    }
  ]
}
1 The location of the JSON schema. This schema defines the set of allowed and required fields for the manifest.json file.
Depending on your development tool, you may get auto-complete and intellisense after you have added the schema location.
2 Use the version field to specify which version of the manifest file this is. Must be changed each time the component is deployed. Use Semantic Versioning.
3 name The name of the component. This should always be in lower case, without spaces.
4 displayName The friendly display name of the component.
5 namespace The namespace of the component.

This is used to distinguish between similarly named components that may be shared across multiple systems. For example, a Squiz-produced 'accordion' component that might conflict with a customer-built 'accordion' component.

6 icon Definition for the icon used by the component, made up of multiple fields.
7 id The ID for the icon - based on the Material UI Two Tone icon set
8 color The color of the icon, made up of multiple fields.
9 type The type of color, can be "hex" to specify a hexadecimal color code, or "enum" to choose from preset colors.
10 value Either a hexadecimal color code or if using "enum", one of "gray", "blue", "green", "orange", "red", "purple", "teal", "yellow", "pink"
11 description Adds more context to the component - one to two sentences.
12 mainFunction The name of the main function which will be used to render your component. The mainFunction is executed at the base URL of the component, while additional functions are executed at a sub path of the URL.
There MUST be a function specified in mainFunction, and it must refer to a function in manifest file functions array.
13 functions A set of named functions that can be used to render the component or API endpoints of the component. The default component used to render your component and the editing interface in Squiz Content Management Service is usually called 'main'. You can add additional functions to the object as needed.
14 name The name of the function. This should always be in lower case, without spaces.
The default function should be called main, and referenced in the mainFunction field.
15 entry The file name of the CommonJS (CJS) JavaScript file containing your function.
Read CommonJS instead of plain JavaScript for more information about expected module conventions.
16 input The input field is where the data model for your component is defined. You can use most JSON schema configurations to generate data structures that will be used to create the editing experience for editors automatically.

type The data type of the input - this should usually be an object.

properties Properties of the input object.

entryfield In this example, "entryfield" is the name of the property. As it is a string type, it will show as an editable text field with the label 'entryfield' for editors to add content to.

type - The data type of the property. This can be any valid type in JSON schema or a few Squiz-specific custom types. Common examples are 'string', 'integer', 'object', and 'array'.

17 The required setting of entryfield shows that a value in "entryfield" is mandatory. The required field is mandatory on all objects - if you create objects inside an array, you must provide a required field for them. It is important to consider which fields should be required and which are optional, as you may get unintended consequences if you do not have required fields set. For example, your code may assume a value for a given input field will be set and fail at runtime.
18 output - Response type "html" returns HTML content. The other valid response type is "json", which returns a JSON endpoint.

If you choose "json", then a "definition" field is also required. The definition field provides a schema for a JSON object.

This example sets a basic property of "my-prop" and marks the property as required in the schema definition.

"output": {
    "responseType": "json",
    "definition": {
      "properties": {
        "my-prop": {
          "type": "string"
        }
      },
      "required": ["my-prop"]
    }
}

CommonJS instead of plain JavaScript

Component Service only supports the CommonJS conventions for server-side modules. Explicitly declaring files with the CJS extension prevents Node.js from throwing errors about detecting CommonJS syntax in a .js file if the runtime environment believes the project is an ES Modules project.

To meet this requirement, adopt the .cjs file extension on all server-side JavaScript files in your component. You can also use the methods described in the Node.js Modules: Packages documentation if you prefer.

JavaScript files

JavaScript files are used to render your component. Usually, you will have one main.cjs file. You may, however, have additional JavaScript files such as one for each of the functions in your component.

It is also important to ensure that any libraries you use are intended to be used outside the browser, such as in a Node.js environment. For example, JavaScript executed server side will not have access to a window object.

The following example shows a simple main.cjs file which outputs one of the values of your component:

module.exports = async function (input, info) {
  return `
  <div>
    <h2>${input.entryfield}</h2>
  </div>
  `;
};

This JavaScript file would output the text value of entryfield as defined in the manifest file above.

The input object contains all the values defined in your manifest input, which are used to generate the editing form.

The info object contains additional information and function helpers, for example dynamically referencing static files.

Preview files

Preview files can be used to mock inputs to your component for local testing previews and deployed previews for demonstrating components in the DXP console. Preview data is in a JSON format, while the preview wrapper is an HTML file used for providing additional context to display your component in.

Read Preview components for more information about the preview files.

Static files

Client-side static files such as CSS, JavaScript and images can be provided along with your component, or they can be provided globally within your site template. If they are managed locally within your component, you have the advantage of being able to modify your client-side and server side code in one single place.

If you have more complex needs for managing your client-side libraries, you may prefer to have a build process for your client-side code that is managed outside the Component Service.

Static files can be configured in your manifest.json file to be served through the Component Service. They must be included in the same directory as the manifest.json and the JavaScript file, or a sub-directory of that directory. When static files are served by the Component Service, you can configure Squiz Content Management Service to include them in the relevant parts of the global design.

Read Use static files with your component for more information about using static files in the Component Service.