--- title: "How to: Bring Your Own Task List" slug: "how-to-bring-your-own-task-list" description: "Learn to create a custom Task List component in Unqork, integrating events and operations for enhanced functionality tailored to client needs." updated: 2025-10-15T15:02:30Z published: 2025-10-15T15:02:30Z canonical: "docs.unqork.io/how-to-bring-your-own-task-list" --- > ## Documentation Index > Fetch the complete documentation index at: https://docs.unqork.io/llms.txt > Use this file to discover all available pages before exploring further. # How to: Bring Your Own Task List This how-to guide details how to create a custom **(**[**Bring Your Own**](/v1/docs/bring-your-own-byo-framework)**) Task List component**. It demonstrates how to build an asset that fully integrates with the Unqork platform using its own events and operations. > [!WARNING] > The [Bring Your Own](/v1/docs/introduction-to-the-bring-your-own-byo-framework) feature is intended for developers who have a strong understanding of the Unqork Designer Platform and JavaScript. ## BYO Task List Asset Ideation For this example, the fictional client company "ABC" wants to implement a Task List as a custom component in the Unqork Designer Platform. The component itself should let Creators configure the task list's Express View title, add or remove additional items, and provide the option to set items as completed (checked). The client requests the Task List to support an event that emits when a user clicks on an item in the checklist. They also ask that it include an operation that sets the completed (checked/unchecked) state of a single item in the checklist. As the developer assigned to this task, break down and document the client's ask into actionable sections: - **Asset Types**: What types of assets are needed to implement to meet the client's requirements of a Task List asset? - **Component(s)**: Does the client's request require the creation of something not currently supported in the Unqork platform? - **Event(s)**: Does the asset need to emit an [event](/v1/docs/introduction-to-the-operations-builder#understanding-events) when it's used? What action should emit the event? - **Operation(s)**: Does the asset need to be manipulated by other elements using an [operation](/v1/docs/introduction-to-the-operations-builder#understanding-operations)? - **Inputs & Outputs**: Catalog a list of potential inputs and outputs for the asset. Events are typically an output in this list. - **Naming Scheme**: Create a naming scheme for the asset that does not conflict with Unqork values or potential future custom assets. > To understand naming scheme limitations, view the Important callout in the overview of our [Bring Your Own (BYO): Understanding the manifest.json File](/v1/docs/bring-your-own-byo-understanding-the-manifestjson-file) article. Now that the client has described the ask, create a document detailing all the potential elements the Task List asset requires. ### Example Ideation Documentation The sections below detail the product requirements that meet the client's request. Developers use this information to implement the component’s JavaScript, create the manifest file and package, and package it to the Unqork Designer Platform. #### Component(s) A custom Unqork component that imports an AG Grid data table. | Component Name | Description | | --- | --- | | Task List | A simple list of items with check boxes next to each. End-users click on each item to check or uncheck the item in the list. | #### Event(s) An event used as part of the [Events & Operations Builder](/v1/docs/operations-builder). | Parameter | Object Type | Description | | --- | --- | --- | | Task List Item Toggled | `taskListItemToggled` | An event that emits when an end-user checks or unchecks a task item. The event includes a payload with the text and completed status of the updated item. **Event Payload**: Adds the name of the item that was clicked. | #### Operation(s) An operation used as part of the [Events & Operations Builder](/v1/docs/operations-builder). | Parameter | Object Type | Description | | --- | --- | --- | | Task List Toggle Task List Item | `toggleTaskListItem` | Toggles or explicitly sets the completed state of a single item in a target task list. Includes the following settings: - `targetKey` (string, required): The component key of the task list to modify. - `item` (number\|string, required): Either the index of the item or the exact text to match. - `completed` (boolean, optional): A Boolean to set the `completed` property of the item. If not provided, toggles the existing value to the opposite. For example, `true` (checked) becomes `false` (unchecked), or `false` (unchecked) becomes `true` (checked). | #### Input(s) Creators use the input fields to map and label columns. | Parameter | Object Type | Description | | --- | --- | --- | | `label` | string componentKey | The title that displays above the task list. The default value is "Tasks". | | `value` | string componentKey | An array of objects that defines the task items in the list. Each object in the array contains the following: - `text` (string): The text of the task item. - `completed` (boolean): Whether the task item's checkbox is checked. The default value is `false` (unchecked). | #### Libraries No libraries are required for this component. | Library Name | Description | Documentation Link | | --- | --- | --- | | N/A | N/A | N/A | #### Naming Scheme Verify that all naming values do not conflict with existing Unqork assets or other custom assets in the environment. > [!WARNING] > IMPORTANT > > Unqork does not enforce programmatic name spacing for custom asset types. All type values for components, operations, and events must be globally unique. If multiple custom assets share the same type, or if a custom asset uses a type that conflicts with a native Unqork type, the runtime will render or execute only the first matching definition. Doing so leads to unpredictable behavior, asset shadowing, or broken functionality—especially when bundling or importing multiple packages. > > It is the responsibility of the developer to ensure type uniqueness to prevent collisions. Component, operation, and event types require a unique name to avoid collision issues. > > To avoid namespace issues, prefix custom components with a name unique to your company or application. For example, if a company named **ABC** creates a **Card Panel** component. The component's name space could be `abcCardPanel`. | Asset Type | Asset Name | Naming Scheme | | --- | --- | --- | | Component | Task List | `taskList` | | Event / Output | Task List Item Toggled | `taskListItemToggled` | | Input | Label | `label` | | Input | Task Item Name and Boolean Value | `value` | ## Create the `manifest.json` File The manifest.json file serves as the contract between Unqork and the Task List implementation. ```json {   "name": "TaskList",   "version": "1.0.0",   "main": "taskList.js",   "type": "custom",   "productType": "BYO",   "description": "A simple task list component with an event and an operation.",   "components": [     {       "name": "Example Task List",       "type": "taskList",       "description": "Simple task list with checkboxes.",       "model": {         "type": "object",         "properties": {           "label": {             "name": "Label",             "type": "string",             "description": "Label of Task List",             "default": "Tasks"           },           "value": {             "name": "Value",             "type": "array",             "description": "Array of task items",             "items": {               "type": "object",               "properties": {                 "text": {                   "type": "string",                   "description": "Text to display for the task item"                 },                 "completed": {                   "type": "boolean",                   "description": "Whether the item is completed",                   "default": false                 }               },               "required": ["text"]             },             "default": []           }         },         "required": ["value"]       },       "events": [         {           "name": "Example Task List Item Toggled",           "type": "taskListItemToggled",           "description": "Emitted when an end-user checks/unchecks a task item.",           "stability": "STABLE",           "model": {             "type": "object",             "properties": {               "name": {                 "const": "taskListItemToggled",                 "type": "string",                 "description": "Name of the event"               },               "payload": {                 "type": "object",                 "description": "The event payload.",                 "properties": {                   "item": {                     "type": "object",                     "description": "A task list item.",                     "properties": {                       "text": { "type": "string", "description": "Task name."},                       "completed": { "type": "boolean", "description": "Whether this task is completed."}                     }                   }                 },                 "required": [                   "item"                 ]               }             }           }         }       ],       "operations": [         {           "name": "Example Task List Toggle Task List Item",           "type": "toggleTaskListItem",           "description": "Toggle (or set) the completion state of a specific item on a target task list.",           "stability": "STABLE",           "model": {             "type": "object",             "properties": {               "options": {                 "type": "object",                 "properties": {                   "targetKey": {                     "name": "Target Key",                     "type": "string",                     "description": "Component key of the task list to modify"                   },                   "item": {                     "name": "Item",                     "description": "Index (number) or text (string) of the item to change",                     "type": ["number", "string"]                   },                   "completed": {                     "name": "Completed",                     "type": "boolean",                     "description": "Optional explicit completed value; if omitted, the value is toggled"                   }                 }               },               "type": {                 "const": "toggleTaskListItem",                 "type": "string"               }             },             "required": ["targetKey", "item"]           }         }       ]     }   ] } ``` The following fields are used at the root level of the manifest: | Field | **Type** | R**equired** | Description | | --- | --- | --- | --- | | `name` | string | ![checkedDummy.jpg](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/checkedDummy(1).jpg?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A20Z&se=2026-11-09T04%3A51%3A20Z&sr=c&sp=r&sig=wmiUHh1Y4cpQ9Nxa9zkJh6i1c5yCCOYqGjhq6r7QfXg%3D) | A unique identifier for the package. For example, `MyCompanyNameAssets`. | | `version` | string | ![checkedDummy.jpg](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/checkedDummy(1).jpg?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A20Z&se=2026-11-09T04%3A51%3A20Z&sr=c&sp=r&sig=wmiUHh1Y4cpQ9Nxa9zkJh6i1c5yCCOYqGjhq6r7QfXg%3D) | The semantic version number. For example, `1.0.0`. | | `type` | enum | ![checkedDummy.jpg](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/checkedDummy(1).jpg?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A20Z&se=2026-11-09T04%3A51%3A20Z&sr=c&sp=r&sig=wmiUHh1Y4cpQ9Nxa9zkJh6i1c5yCCOYqGjhq6r7QfXg%3D) | The package type. Currently, the only supported value is `custom`. | | `productType` | enum | ![checkedDummy.jpg](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/checkedDummy(1).jpg?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A20Z&se=2026-11-09T04%3A51%3A20Z&sr=c&sp=r&sig=wmiUHh1Y4cpQ9Nxa9zkJh6i1c5yCCOYqGjhq6r7QfXg%3D) | The target platform feature. Currently, the only supported value is `BYO`. | | `description` | string | ![checkedDummy.jpg](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/checkedDummy(1).jpg?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A20Z&se=2026-11-09T04%3A51%3A20Z&sr=c&sp=r&sig=wmiUHh1Y4cpQ9Nxa9zkJh6i1c5yCCOYqGjhq6r7QfXg%3D) | A description that displays in the Admin Panel after installation. | | `main` | string | ![checkedDummy.jpg](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/checkedDummy(1).jpg?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A20Z&se=2026-11-09T04%3A51%3A20Z&sr=c&sp=r&sig=wmiUHh1Y4cpQ9Nxa9zkJh6i1c5yCCOYqGjhq6r7QfXg%3D) | The relative path to the JavaScript entry file. For example, `index.js`. | | `components` | array | Optional | A list of component definitions included in the package. | | `events` | array | Optional | List of event definitions. | | `operations` | array | Optional | List of operation definitions. | ### **Understand**i**ng the** **components[]** **Definition** This definition defines the Task List component: | **Export** | **Description** | | --- | --- | | `name` and `type` | Define the component's name and its internal identifier. The `type` (`taskList`) must match the export name in the JavaScript file (`taskList.js`) so Unqork can link the JSON definition to the correct code. | | `model` | This object defines a custom event. It exports a model that describes the structure of the event's payload (`name` and `payload`). Doing so lets other parts of the Unqork platform use and understand the event that the component emits. | | ↳ | `label` | A string property that serves as the title for the task list. | | `value` | An array property that contains the list of task items. Each item is an object with a text (string) and completed (boolean) property. This schema ensures that the data passed to the component is always in the correct format. | | `events` | This section defines the events the component can emit. | | ↳ | `name` and `type` | The human-readable name and the unique identifier of the `taskListItemToggled` event. | | `description` | Explains when the event is emitted. | | `model` | A schema that defines the payload of the event, ensuring that the data sent with the event (`item` with `text` and `completed` properties) is structured correctly. Doing so lets other components reliably listen for and use this event's data. | | `operations` | This section defines the actions or operations that can be performed on the component from outside. | | ↳ | `name` and `type` | The name and unique identifier of the `toggleTaskListItem` operation. | | `description` | Explains what the operation does. | | `model` | Defines the options or parameters for the operation. It requires a `targetKey` identifying the component to act on and an `item` (number or string) to identify the specific task to modify. The `completed` parameter is optional. This schema ensures that anyone using this operation provides the necessary information. | > To learn more about the manifest.json file, view the following topic: [Understanding the manifest.json File](/v1/docs/bring-your-own-byo-understanding-the-manifestjson-file). ## **Implement the Task List** For this example, create a file called `taskList.js`. In this file, create a Web Component that does the following: - Creates a Shadow DOM as a part of the BYO implementation requirements. - Initializes the Unqork Runtime API as a part of the BYO implementation requirements. - Subscribes to state changes so that the component can look for changes to the `label` or `value` property, updating the rendering to match. Changes to these properties are made using configuration in the Module Builder. - Converts data into a standardized array of objects. Doing so improves error handling if the data is given as a string instead of an array. - Emits an event back to the Unqork runtime, so configuration can use the event with [Operations Builder](/v1/docs/operations-builder) to trigger downstream logic. - Renders the Task List in Express View as HTML. Review the code example below for more information on each method: > [!NOTE] > NOTE > > The comments in the JavaScript below are written in the JSDoc format. For more information on JSDoc block tags (@param, @return), visit the JSDoc website: [https://jsdoc.app/.](https://jsdoc.app/.) ```javascript class UnqorkTaskListComponent extends HTMLElement {   constructor() {     super()     this.attachShadow({ mode: 'open' })     this.items = []     this.label = 'Tasks'   }   /**    * This is the only required method to integrate with the Unqork system    *    * @param {*} api The interface to the Unqork Runtime, used for both    *                monitoring state and emitting events    */   initialize(api) {     this.api = api     this.config = api.state.currentState()     // Initial label and value from config (if provided)     if (this.config.label != null) this.label = String(this.config.label)     if (this.config.value != null) this.items = this._normalizeItems(this.config.value)     // Method to render component in the DOM.     this.render(this.shadowRoot, this.label, this.items)     // Subscribe to state changes such as SET_PROPERTY     this.subscribeLabel()     this.subscribeValue()   }   /**    * Subscribes to changes in the `label` property of the component's state.    *    * This method listens to the `state$('label')` observable for updates to the `label` property.    * When a new value is emitted, it updates the `label` property of the component and re-renders the component.    *    * @returns {void}    */   subscribeLabel() {     this.api.state.state$('label').subscribe((label) => {       this.label = label ?? ''       this.shadowRoot.innerHTML = this.view(this.label, this.items)     })   }   /**    * Subscribes to changes in the `value` property of the component's state.    *    * This method listens to the `state$('value')` observable for updates to the `value` property.    * When a new value is emitted, it normalizes the value into an array of items and updates the `items` property.    * It then re-renders the component with the updated items.    *    * @returns {void}    */   subscribeValue() {     this.api.state.state$('value').subscribe((value) => {       this.items = this._normalizeItems(value)       this.shadowRoot.innerHTML = this.view(this.label, this.items)     })   }   /**    * Normalizes the input value into an array of objects with a specific structure.    *    * This method ensures that the input `value` is converted into an array of objects,    * where each object contains the following properties:    * - text: The text to actually display in the taskList item (defaults to an empty string if missing).    * - completed: A boolean indicating whether the item is completed (defaults to `false` if missing).    *    * @param value - The input value to normalize. Can be a JSON string or an array.    * @returns The normalized array of items.    */   _normalizeItems(value) {     const arr = typeof value === 'string' ? JSON.parse(value) : value     if (!Array.isArray(arr)) return []     return arr.map((item) => ({       text: String(item?.text ?? ''),       completed: Boolean(item?.completed),     }))   }   render(root, label, items) {     root.innerHTML = this.view(label, items)     root.addEventListener('change', (ev) => {       const el = ev.target       if (!(el instanceof HTMLInputElement) || el.type !== 'checkbox') return       const idx = Number(el.getAttribute('data-index'))       if (Number.isNaN(idx) || !this.items[idx]) return       const updatedItem = { ...this.items[idx], completed: el.checked }       const next = [...this.items]       next[idx] = updatedItem       // Update state with new item value       this.api.state.set({ value: next })       // Emit taskListItemToggled event       this.emitItemToggledEvent(updatedItem)     })   }   /**    * Emits a `taskListItemToggled` event when a to-do list item is toggled.    *    * This method triggers a domain event with the name `taskListItemToggled` and includes    * the toggled item's details in the event payload. The payload contains the updated item    * with its `text` and `completed` properties.    *    */   emitItemToggledEvent = (item) => {     this.api.events.emit({       name: 'taskListItemToggled',       payload: { item },     })   }   // The component view   view(label, items) {     const list = items       .map(         (item, i) => `         
  •                    
  • `,       )       .join('')     return `     
    ${label ?? ''}
        
            ${list}     
      `   } } /**  * This definition defines the state settings (model) for this component  * It mirrors the fuller description in manifest.json and will  * eventually be used to auto-generate the manifest.json schema  */ class TaskListDefinition {   label   value } /**  * This export provides the view and model definitions for the component,  * which are utilized by the Unqork Runtime for configuration and execution.  * Both definitions are `async` to enable on-demand loading, improving initial page load performance.  *  * Component export name MUST match manifest `type`  */ export const taskList = {   model: async () => TaskListDefinition,   view: async () => UnqorkTaskListComponent, } /** ========= Example Task List Item Toggled Event Model ========= **/ // Defines the structure of the payload for the taskListItemToggled event class TaskListItemToggledPayload {   item = { text: '', completed: false } } // This definition describes the schema of the event that is emitted // when the user toggles an item class TaskListItemToggled {   // The name of the event   name = 'taskListItemToggled'   // The details of the toggled to-do list item   payload = new TaskListItemToggledPayload() } // This export is used to expose the event to the Unqork Runtime // Note: event export name MUST match manifest `type` export const taskListItemToggled = {   model: async () => TaskListItemToggled, } /** ======== Example Task List Toggle Task List Item Operation ======== **/ // Operation options/schema for toggling a task list item class ToggleTaskListItemOptions {   // key of the taskList component to modify   targetKey   // number (index) OR string (text) of the item to change   item   // Boolean to set completed property of item to. If not provided, just toggle the existing value (e.g. true -> false and false -> true)   completed } class ToggleTaskListItemOperation {   // MUST match the manifest "type" and the named export below   type = 'toggleTaskListItem'   options = new ToggleTaskListItemOptions() } class ToggleTaskListItemHandler {   /**    * Execute the operation.    * @param {ToggleTaskListItemOperation} operation    * @param {*} api Operation API: { state: { resolveByKey, set, get }, events: { emit } }    */   async execute(operation, api) {     const { targetKey, item, completed } = operation.options.config || {}     if (!targetKey) throw new Error('toggleTaskListItem Operation: "targetKey" is required.')     if (item === undefined || item === null)       throw new Error('toggleTaskListItem Operation: "item" (index or text) is required.')     // Resolve the target component state     const target = api.state.resolveByKey(targetKey)     // Expecting a list of items like the following:     // [     //   { "text": "Buy groceries", "completed": false },     //   { "text": "Complete design doc", "completed": true }     // ]     const list = target?.value ?? []     if (!Array.isArray(list)) throw new Error('toggleTaskListItem Operation: target value is not an array.')     // Find the target index     let index = typeof item === 'number' ? item : list.findIndex((it) => String(it?.text ?? '') === String(item))     // Ensure the index is within bounds, otherwise throw an error     if (index < 0 || index >= list.length) {       throw new Error(`toggleTaskListItem Operation: could not find item "${item}".`)     }     // Get the current item or default to an empty object with default properties     const current = list[index] ?? { text: '', completed: false }     // Determine the next completion state based on the provided `completed` boolean or toggle the current state     const nextCompleted = typeof completed === 'boolean' ? completed : !current.completed     // Create a new list with the updated item at the specified index     const newList = [...list]     newList[index] = { ...current, completed: nextCompleted }     // Update the target component state with the new list     api.state.set(targetKey, { value: newList })   } } // The following class is omitted since the operation handler does not return a result // class ToggleTaskListItemContext { //   ... // } // Named export — MUST match manifest "type" export const toggleTaskListItem = {   model: async () => ToggleTaskListItemOperation,   handler: async () => ToggleTaskListItemHandler,   //This is omitted since the operation handler does not return a result   //contextModel: async () => ToggleTaskListItemContext, } ``` ### Understanding the `UnqorkTaskListComponent` Class and its Methods The `UnqorkTaskListComponent` class Web Component is the core of the Task List BYO component. Learn more about each of its methods below: | Method | Description | | --- | --- | | `constructor()` | This method runs when the component is created. It sets up a Shadow DOM (`mode: 'open'`) to encapsulate the component's styles and markup, preventing them from interfering with other elements on the page. It also initializes internal variables like `items` and `label`. | | `initialize(api)` | This is the most crucial method for Unqork integration. The Unqork runtime calls this method to give the component access to the `api` object. This API is how the component reads its configuration, subscribes to state changes, and emits events back to Unqork. | | `subscribeLabel() and subscribeValue()` | These methods demonstrate how the component subscribes to state changes. They use Unqork's `api.state.state$()` to listen for updates to the `label` and `value` properties. When a user (or another component) changes these properties in Express View, these methods trigger, causing the component to re-render with the new data. | | `_normalizeItems(value)` | This is a private helper method that ensures the data is in the correct format. It takes a raw value (which could be a JSON string or an array) and converts it into a clean, standardized array of objects with `text` and `completed` properties. That way, the data is reliable for rendering. | | `render()` | This method handles rendering the component and adding event listeners. It takes the component's internal data (`label`, `items`) and generates the HTML view. It also sets up a `change` event listener on the root element. When a user clicks a checkbox, this listener triggers. Then, it updates the component's state using `this.api.state.set()` and emits an event. | | `emitItemToggledEvent()` | This method uses the `api.events.emit()` function to send an event back to the Unqork runtime. Doing so lets other parts of the Unqork application respond when a user checks or unchecks a task item. | | `view()` | This method is a pure function that generates the component's HTML markup. It takes the label and items data and uses JavaScript's `map()` and `join()` to create a dynamic list of checkboxes. | ### Understanding the `taskList` and `taskListItemToggled` Exports These exports act as the component's manifest, providing the Unqork runtime with the necessary data to use the component. | Export | Description | | --- | --- | | `taskList` | This object exports the `model` (the component's data schema) and the `view` (the component itself). The Unqork platform uses this data to configure the component's properties and render it correctly. | | `taskListItemToggled` | This object defines a custom event. It exports a `model` that describes the structure of the event's payload. For example, `name` and `payload`. Doing so lets other parts of the Unqork platform use and understand the event that the component emits. | ### Understanding the `ToggleTaskListItemHandler` Class and `toggleTaskListItem` Export This section defines a custom [Unqork operation](/v1/docs/introduction-to-the-operations-builder#understanding-operations), which is a server-side action that can be executed from a workflow or other part of the Unqork application. | Export | Description | | --- | --- | | `ToggleTaskListItemHandler` Class | This class contains the `execute()` method that defines the operation's logic. `ToggleTaskListItemHandler` performs the following: 1. Takes an `operation` object and the api. 2. Validates the incoming `targetKey` and `item` options. 3. Uses `api.state.resolveByKey()` to find the target component's state. 4. Locates the correct item in the list and updates its `completed` property. 5. Uses `api.state.set()` to update the state of the target component, which triggers the component's subscription to re-render. | | `toggleTaskListItem` Export | This object exports the `model` (the operation's data schema) and the `handler` (the class containing the logic). Doing so enables the Unqork platform to execute this custom operation. | > To learn more about implementing assets, view the following resources: > > - [Custom Component SDK](/v1/docs/bring-your-own-byo-component-sdk-software-development-kit): Extend component functionality in the Unqork Designer Platform. > - [Custom Component:](/v1/docs/bring-your-own-byo-custom-component) Understand the state, interface, and events of a custom component. > - [Custom Events](/v1/docs/bring-your-own-byo-custom-events): Learn more about creating custom events for use in the Operations Builder. > - [Custom Operations](/v1/docs/bring-your-own-byo-custom-operations): Learn more about creating custom operations for use in the Operations Builder. ## Create the BYO Task List Package After the asset JavaScript and manifest.json files are complete, compress them into a BYO package. To compile a file using Terminal (Mac) or Command Prompt (Windows): 1. Using the command line prompt, navigate to the directory containing the `taskList.js` and `manifest.json` files. For example, `cd C:\Users\UserName\Desktop\taskListAsset`. 2. Execute the following command: `tar -cvzf taskList.tar.gz manifest.json taskList.js`. ![Terminal command showing file compression and directory navigation in a task list project.](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/taskListPackage_thumb_0_0.jpg?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A20Z&se=2026-11-09T04%3A51%3A20Z&sr=c&sp=r&sig=wmiUHh1Y4cpQ9Nxa9zkJh6i1c5yCCOYqGjhq6r7QfXg%3D)The `taskList.js` file and `manifest.json` are added to the `tar.gz` file in the same folder they're located in. > [!NOTE] > NOTE > > The steps above use the `tar` command and the following options: > > `-c`: Creates a new archive. > > `-z`: Compresses the archive using gzip. > > `-v`: Lists the files in the command line as they are added to archive. > > `-f`: Specifies the file name for the archived files. > Learn more about BYO Packages using the following resource: [Create a BYO Package](/v1/docs/bring-your-own-byo-create-a-package). ## Upload the BYO Task List Package After creating the `taskList.tar.gz` package, upload it to the Unqork Designer Platform using the [Custom Assets Administration](/v1/docs/custom-assets-administration) page: 1. From the UDesigner homepage, click **Administration**. 2. Under Assets, click **Custom Assets Administration**. 3. Click **+ Create new**. The Create Asset modal displays. 4. Under File Upload, **click or drag** a BYO package from your local device to the upload window. 5. Click **Scan File**. The package details display. ![createAssetTaskList1_thumb_0_0.jpg](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/createAssetTaskList1_thumb_0_0.jpg?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A20Z&se=2026-11-09T04%3A51%3A20Z&sr=c&sp=r&sig=wmiUHh1Y4cpQ9Nxa9zkJh6i1c5yCCOYqGjhq6r7QfXg%3D) > [!NOTE] > NOTE > > If an import error occurs, review the package's contents for errors and name mismatches. 6. Click **Review Assets**. 7. Review the asset's details, including **Components**, **Events**, and **Operations**. 8. Click **Confirm & Create**. 9. Review the **Library Usage Acknowledgment and Liability Agreement**. Click the ☐ (**checkbox**) to acknowledge the agreement. 10. Click **Create Asset**. The asset package displays in the Custom Asset's **Packages** list. The package's individual assets display in the Assets tab's **Assets** list. The assets are now available in the Module Builder for all applications in the environment. > Learn more about the Custom Assets Administration page using the following resource: [Custom Assets Administration](/v1/docs/custom-assets-administration) ## Test the Task List Component Now that the BYO Task List component is in the Unqork Designer Platform, test its functionality in the Module Builder and Express View. This example assumes you are configuring a Vega (v2.0) module. For this example, test the following functions: - **Task List Configuration Drawer**: Verify each setting is functional. - `taskListItemToggledEvent` **Event**: Verify the event emits when clicking a task list item. - `toggleTaskListItem` **Operation**: Verify the operation accepts the following keys and values: `targetKey` (task list property ID), `item` (task list item), and `completed` (Checked/Unchecked). ### Configure the Custom Component The Custom Component contains a list of all BYO components in the environment. Select the Example Task List, then configure it to test settings, events, and operations. 1. In the Module Builder, drag and drop a Custom Component onto your canvas. 2. In the **Property ID** field, enter `byoTaskList`. 3. From the **Select Component** drop-down, enter or select `Example Task List`. The component's configuration populates. 4. Under **Object 1**, in the text field, enter `First Item`. 5. Set **Object 1** to ![checkedDummy.jpg](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/checkedDummy(1).jpg?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A20Z&se=2026-11-09T04%3A51%3A20Z&sr=c&sp=r&sig=wmiUHh1Y4cpQ9Nxa9zkJh6i1c5yCCOYqGjhq6r7QfXg%3D) (**Completed**). 6. Under **Object 2**, in the text field, enter `Second Item`. 7. Under **Object 3**, in the text field, enter `Third Item`. #### Configure the byoTaskList Events and Operations While remaining in the configuration drawer, set up the BYO event `taskListItemToggled` to hide a button by setting its `display.hidden` property to false. 1. Navigate to the **Actions** settings. 2. Next to Events & Operations, click **Edit**. The Events & Operations modal displays. 3. From the **Select an Event** drop-down, enter or select `Example Task List Item Toggle`. This custom event was imported as part of the BYO Task List package. 4. Click **Add**. 5. Click **+Add** Operation. 6. From the **Operation Type** drop-down, select `Set Property`. 7. In the **Target Key** field, enter `btnCheckSecondItem`. You'll set the `btnCheckSecondItem` Button component Icon Button component in the next section. 8. In the **Property ID** field, enter `display.hidden`. This value targets the Button component's hidden key, which controls the visibility of the button. 9. In the **Value** field, enter `false`. This value hides the button when the operation triggers. 10. Click **Save**. 11. Click **Close**. 12. Click **Save** Component. ### Configure the Button Component Configure a Button component to emit an On Click event. Configure the event to trigger the BYO `toggleTaskListItem` operation. When this operation triggers, it checks the second item in the task list. Drag and drop a Button component onto your canvas, placing it above the `byoTaskList` Custom Component. 1. In the **Property ID** field, enter `btnCheckSecondItem`. 2. In the **Label Text** field, enter `Check Second Item`. 3. Navigate to the **Actions** settings. 4. From the **Action Type** drop-down, select `Event`. 5. Next to Events & Operations, click **Edit**. The Events & Operations modal displays. 6. From the **Select an Event** drop-down, enter or select `On Click`. This event emits when the user clicks the button. 7. Click **Add**. 8. Click **+Add** Operation. 9. From the **Operation Type** drop-down, select `Example Task List Toggle Task List Item`. This custom operation was imported as part of the BYO Task List package. 10. In the **Config** field, enter the following JSON code: `{"targetKey":"byoTaskList","item":"Second Item","completed":true}`. This value checks the byoTaskList Custom Component's second item in the list. 11. Click **Save**. 12. Click **Close**. 13. Click **Save Component**. 14. **Test** your module. Your completed module looks like the following: ![User interface displaying a task list component with options to check items.](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/moduleBuilderTaskList.jpg?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A20Z&se=2026-11-09T04%3A51%3A20Z&sr=c&sp=r&sig=wmiUHh1Y4cpQ9Nxa9zkJh6i1c5yCCOYqGjhq6r7QfXg%3D) ## Preview and Test the Module Preview your module in Express View. Check for the following functionality: 1. On module load, the list's First Item is set to ![checkedDummy.jpg](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/checkedDummy(1).jpg?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A20Z&se=2026-11-09T04%3A51%3A20Z&sr=c&sp=r&sig=wmiUHh1Y4cpQ9Nxa9zkJh6i1c5yCCOYqGjhq6r7QfXg%3D) (**checked**). Doing so verifies the `byoTaskList` Custom Component's configuration setting Completed is functioning. 2. Click the **Check Second Item** button, and the list's Second Item is set to ![checkedDummy.jpg](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/checkedDummy(1).jpg?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A20Z&se=2026-11-09T04%3A51%3A20Z&sr=c&sp=r&sig=wmiUHh1Y4cpQ9Nxa9zkJh6i1c5yCCOYqGjhq6r7QfXg%3D) (**checked**). This verifies the `toggleTaskListItem` operation is functioning. 3. Click any item in the list, and the **Check Second Item** button disappears. This verifies the `taskListItemToggled` event is functioning. [Video](https://cdn.us.document360.io/15548f06-2fba-434c-b0c1-5df88317dbd7/Images/Documentation/expressViewCheckList.mp4?sv=2026-02-06&spr=https&st=2026-11-09T03%3A51%3A20Z&se=2026-11-09T04%3A51%3A20Z&sr=c&sp=r&sig=wmiUHh1Y4cpQ9Nxa9zkJh6i1c5yCCOYqGjhq6r7QfXg%3D) If the custom asset functions as intended, then it’s ready to be used by Creators in the development of Unqork applications. If the Custom Component generates errors or is missing features: 1. Create a copy of the current package and its contents. 2. Update the package's required files. 3. Change the package's version number. 4. Update the package by referring to the **Package Management** section in our BYO Best Practices article: [BYO Best Practices - Package Management](/v1/docs/best-practices-bring-your-own-byo-framework#byo-package-management). JavaScript is an object-oriented computer programming language. It is most-commonly used for interactive effects in the browser. Also known as Unqork Users, or Designer Users; is anyone who is inside the Unqork platform. Express View is how your end-user views your application. Express View also lets you preview your applications to test your configuration and view the styling. This is also the view your end-users will see when interacting with your application. After configuring a module, click Preview in the Module Builder to interact with the module in Express View. The Boolean data type accepts one of two values: true, or, false. An array is a type of object that stores one or more data types. Data types supported in arrays include numbers, strings, and objects. Programmatic namespacing is a way to group related code together under a common name so it doesn’t conflict with other code. It helps keep programs organized and prevents errors when different parts of a program use the same names. A runtime engine is software that runs on a computer to allow applications to execute. Rendering is the process of loading components and displaying the final result on the front-end screen. In Unqork an application is a program used to perform specific tasks. An application can be one of two types: workflow or module. A string is an object that represents a sequence of characters. Strings typically hold data represented in text form. An enum, or enumeration type, is a data type that consists of a set of named constants that a variable can be assigned to. JSON (JavaScript Object Notation) is an open standard file and data interchange format. Unqork uses JSON for submission (record) data. The Shadow DOM is a web standard that allows you to create encapsulated, hidden DOM subtrees for your web components. It provides a way to scope CSS styles and JavaScript behavior within a component, preventing them from leaking out and interfering with the rest of the page. APIs (application programming interfaces) are a set of protocols and definitions developers use to build and integrate application software. APIs act as the connective tissue between products and services. An object is a type of data structure that represents a single, self-contained entity that acts as a container for the characteristics of that entity. HTML (Hyper Text Markup Language) is the standard markup language for for achieving font, color, graphic, and hyperlink effects when creating web pages. The Vega (v 2.0.0) runtime is the next-generation engine of the UDesigner platform. Vega uses cutting-edge technologies to improve the Creator and end-user experience. A Property ID is the unique field ID used by Unqork to track and link components in your module. ## Related - [Introduction to the Bring Your Own (BYO) Framework](/introduction-to-the-bring-your-own-byo-framework.md) - [BYO Support](/byo-support-articles.md) - [BYO Customization](/byo-customization-articles.md)