# Node.js -------------------------------------------------------------------------------- title: "Introduction" description: "Build a basic web app that uses Catalyst components to generate a PDF document from a dynamic custom payslip template, and email the generated document to the end-user." last_updated: "2026-03-18T07:41:08.686Z" source: "https://docs.catalyst.zoho.com/en/tutorials/payslip-generator-app/nodejs/introduction/" service: "All Services" related: - Project Directory Structure (/en/cli/v1/project-directory-structure/introduction/) - Node.js SDK (/en/sdk/nodejs/v2/overview/) -------------------------------------------------------------------------------- # Payslip Generator App ### Introduction This tutorial will help you build an application in Catalyst that generates employee payslips. The application will allow users to style the template of the company's payslip, input employee details in a form, and send the payslip to the respective employees via email. The client application will look like this: <br /> The email sent to the employee will look like this: <br /> The payslip that is generated and emailed as a PDF will look like this: <br /> You can access a working application and test their functionality here: {{%link href="https://payslip.catalystserverlessapp.com/" %}}Try the App!{{%/link%}} The Payslip Generator application utilizes the following Catalyst Services and their components: 1. {{%link href="/en/smartbrowz/getting-started/introduction/" %}}**Catalyst SmartBrowz**{{%/link%}}<br /> - **Templates**: {{%link href="/en/smartbrowz/help/templates/create-templates/" %}}Templates{{%/link%}} is used to create a custom template of a payslip. - **PDF & Screenshot**: {{%link href="/en/smartbrowz/help/pdfnscreenshot/introduction/" %}}PDF & Screenshot{{%/link%}} will be used to test the template and to generate PDFs of the template in the backend. 2. {{%link href="/en/serverless/getting-started/introduction/" %}}**Catalyst Serverless**{{%/link%}}<br /> - **Advanced I/O Function**: The {{%link href="/en/serverless/help/functions/advanced-io/" %}}Advanced I/O function{{%/link%}} can be coded using Node.js. It contains the APIs that allow you to feed the details to your customized template and trigger the Mail component to send an email to the employee. 3. {{%link href="/en/cloud-scale/getting-started/introduction/" %}}**Catalyst Cloud Scale**{{%/link%}}<br /> - **Web Client Hosting**: The front/client end of the application will be hosted on Catalyst using {{%link href="/en/cloud-scale/help/web-client-hosting/introduction/" %}}Web Client Hosting{{%/link%}}. You can initialize and create your web client as a {{%link href="/en/cli/v1/initialize-resources/initialize-client/#basic-client-applications" %}}Basic web app{{%/link%}} using Catalyst native plugins. - **Mail**: {{%link href="/en/cloud-scale/help/mail/introduction/" %}}Mail{{%/link%}} is used to set up the email address from which the automated emails will be sent to the employees. We will use the {{%link href="https://console.catalyst.zoho.com/" %}}Catalyst web console{{%/link%}} and the {{%link href="/en/cli/v1/cli-command-reference/" %}}Catalyst Command Line Interface{{%/link%}} (CLI) to build this application. You will be given the code for the files to be included in the function and client components in this tutorial. You will have to copy the code given here and paste it into the appropriate files as directed. ### Application Architecture The payslip generator application's logic is described below: <br /> * **Submitting the form**: The end-user will input the employee details on the form displayed in the client-side, such as name, designation, ID, email ID, basic salary, deductions, allowances, and mode of payment. Once the details are inputted the user will click **Submit**. * **The PDF & SDK Screenshot SDK will be triggered**: In the backend, the {{%link href="/en/sdk/nodejs/v2/smartbrowz/generate-pdfnscreenshot/" %}}PDF & Screenshot SDK{{%/link%}} will be triggered, and a {{%link href="/en/smartbrowz/help/headless/introduction/" %}}headless browser{{%/link%}} will be launched. Using the {{%link href="/en/smartbrowz/help/templates/create-templates/" %}}Template ID{{%/link%}} generated by Catalyst, the details collected in the form will be rendered in the template, and converted as a PDF. * **The email will be sent**: The generated PDF will be emailed as an attachment to the email ID inputted in the form using the {{%link href="/en/sdk/nodejs/v2/cloud-scale/mail/send-email/" %}}Send Mail SDK{{%/link%}}, which invokes the *Mail* component. The user will be notified that the email has been sent, and the form will refresh and be ready to receive the next user details. <br /> -------------------------------------------------------------------------------- title: "Prerequisites" description: "Build a basic web app that uses Catalyst components to generate a PDF document from a dynamic custom payslip template, and email the generated document to the end-user." last_updated: "2026-03-18T07:41:08.686Z" source: "https://docs.catalyst.zoho.com/en/tutorials/payslip-generator-app/nodejs/prerequisites/" service: "All Services" related: - CLI Command Reference (/en/cli/v1/cli-command-reference/) - Install Catalyst CLI (/en/getting-started/installing-catalyst-cli/) - Login CLI (/en/cli/v1/login/login-from-cli/) -------------------------------------------------------------------------------- # Prerequsities Before you begin building the application, you must have the following prerequisites installed on your system: 1. **Catalyst CLI**: {{%link href="/en/cli/v1/cli-command-reference/" %}}Catalyst CLI{{%/link%}} contains a host of tools that enable you to initialize, develop, test, and deploy the components of your application from your local machine. We will be working with Catalyst CLI in this tutorial.<br />You must perform these actions: - **Install Catalyst CLI**: Catalyst CLI is installed through NPM. You must therefore have NPM and Node.js installed on your system before you install the CLI. Refer to the {{%link href="/en/getting-started/installing-catalyst-cli/" %}}Install Catalyst CLI help page{{%/link%}} for details on the pre-requisites and the steps to install it. - **Login Catalyst CLI**: After you install Catalyst CLI, you must authenticate the CLI with your Catalyst account before using it. Refer to the {{%link href="/en/cli/v1/login/login-from-cli/" %}}CLI Login help page{{%/link%}} for the steps to log in from Catalyst CLI and the various options available for it. 2. **Any IDE tool for Node.js and client code development**: Download and install an IDE of your choice in your system. You can use any IDE to work with the function and the client code. Some popular choices include Visual Studio Code, IntelliJ IDEA, Eclipse, and Sublime Text. {{%info image="/images/tutorials/todo-list/vscode.png"%}}If you are a Visual Studio Code IDE user, you can install the {{%bold%}}Catalyst Tools{{%/bold%}} extension, and use your IDE itself in place of the CLI. You can find more details about the Catalyst VS Code extension from this {{%link href="/en/catalyst-extensions/vs-code-extension/introduction/" %}}help section{{%/link%}}.{{%/info%}} -------------------------------------------------------------------------------- title: "Create a project" description: "Build a basic web app that uses Catalyst components to generate a PDF document from a dynamic custom payslip template, and email the generated document to the end-user." last_updated: "2026-03-18T07:41:08.686Z" source: "https://docs.catalyst.zoho.com/en/tutorials/payslip-generator-app/nodejs/create-project/" service: "All Services" related: - Catalyst Console (/en/getting-started/catalyst-projects/) -------------------------------------------------------------------------------- # Create a Project Let’s {{%link href="/en/getting-started/catalyst-projects/#creating-a-catalyst-project" %}}create a Catalyst project{{%/link%}} from the Catalyst console. 1. Log in to the {{%link href="https://console.catalyst.zoho.com/baas/index" %}}Catalyst console{{%/link%}} and click **Create New Project**. <br /> 2. Enter the project’s name as "**PayslipGenerator**" in the pop-up window, and click **Create**. <br /> Your project will be created and opened. To access the project later, click **Access Project**. <br /> <br /> -------------------------------------------------------------------------------- title: "Create a Template" description: "Build a basic web app that uses Catalyst components to generate a PDF document from a dynamic custom payslip template, and email the generated document to the end-user." last_updated: "2026-03-18T07:41:08.686Z" source: "https://docs.catalyst.zoho.com/en/tutorials/payslip-generator-app/nodejs/create-template/" service: "All Services" related: - Catalyst SmartBrowz (/en/smartbrowz/getting-started/introduction/) - Templates (/en/smartbrowz/help/templates/create-templates/) -------------------------------------------------------------------------------- # Create a Template You need to create a custom template using the {{%link href="/en/smartbrowz/getting-started/introduction/" %}}Catalyst SmartBrowz{{%/link%}} component, {{%link href="/en/smartbrowz/help/templates/create-templates/" %}}Templates{{%/link%}}. This template will contain the design and the style of the payslip. This is the template that will be generated as a PDF and emailed to the end-users. To create a template: 1. Click the *Catalyst SmartBrowz* service icon in the console, and click **Start Exploring**. <br /> 2. Click **Templates** under Convert to access the *Templates* component, and click **Create Template**. <br /> 3. Select *Custom*, enter "**Payslip**" as the name of the template, and click **Create**. <br /> You will be able to view the template editor and the template preview window. <br /> 4. Copy the given code and paste it in the appropriate editors as explained below: * Paste the following HTML code in the HTML editor {{% panel_with_adjustment header="HTML" footer="button" scroll="set-scroll" class="language-xml line-numbers" %}}&lt;!DOCTYPE html&gt; &lt;html&gt; &lt;head&gt; &lt;title&gt;Payslip&lt;/title&gt; &lt;link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" /&gt; &lt;script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js"&gt;&lt;/script&gt; &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"&gt;&lt;/script&gt; &lt;/head&gt; &lt;body&gt; &lt;div class="container mt-5 mb-5"&gt; &lt;div class="row"&gt; &lt;div class="col-md-12"&gt; &lt;div class="text-center lh-1 mb-2"&gt; &lt;h6 class="fw-bold color_primary"&gt;{{company}} Payslip&lt;/h6&gt; &lt;span class="fw-normal color_sec" &gt;Payment slip for the month of {{month}} {{year}}&lt;/span &gt; &lt;/div&gt; &lt;div class="d-flex justify-content-end"&gt; &lt;span&gt;Working Branch: NewYork&lt;/span&gt; &lt;/div&gt; &lt;br&gt; &lt;div class="row"&gt; &lt;div class="col-md-10"&gt; &lt;div class="row"&gt; &lt;div class="col-sm-6"&gt; &lt;div&gt; &lt;span class="fw-bolder color_primary"&gt;EMP Code&lt;/span&gt; &lt;small class="ms-3 color_sec"&gt;{{employeeId}}&lt;/small&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class="col-sm-6"&gt; &lt;div&gt; &lt;span class="fw-bolder color_primary"&gt;EMP Name&lt;/span&gt; &lt;small class="ms-3 color_sec"&gt;{{employeeName}}&lt;/small&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class="row"&gt; &lt;div class="col-sm-6"&gt; &lt;div&gt; &lt;span class="fw-bolder color_primary"&gt;Mode of Pay&lt;/span&gt; &lt;small class="ms-3 color_sec"&gt;{{paymentMethod}}&lt;/small&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class="col-sm-6"&gt; &lt;div&gt; &lt;span class="fw-bolder color_primary"&gt;Ac No.&lt;/span&gt; &lt;small class="ms-3 color_sec"&gt;*******&lt;/small&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class="row"&gt; &lt;div class="col-sm-6"&gt; &lt;div&gt; &lt;span class="fw-bolder color_primary"&gt;Designation&lt;/span&gt; &lt;small class="ms-3 color_sec"&gt;{{designation}}&lt;/small&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;table class="mt-4 table table-bordered"&gt; &lt;thead class="bg-dark text-white"&gt; &lt;tr&gt; &lt;th scope="col"&gt;Earnings&lt;/th&gt; &lt;th scope="col"&gt;Amount&lt;/th&gt; &lt;th scope="col"&gt;Deductions&lt;/th&gt; &lt;th scope="col"&gt;Amount&lt;/th&gt; &lt;/tr&gt; &lt;/thead&gt; &lt;tbody&gt; &lt;tr&gt; &lt;th scope="row"&gt;Basic&lt;/th&gt; &lt;td&gt;{{basicSalary}}&lt;/td&gt; &lt;td&gt;Tax&lt;/td&gt; &lt;td&gt;{{deductions}}&lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;th scope="row"&gt;Allowances&lt;/th&gt; &lt;td&gt;{{allowances}}&lt;/td&gt; &lt;td colspan="2"&gt;&lt;/td&gt; &lt;/tr&gt; &lt;tr class="border-top"&gt; &lt;th scope="row"&gt;Total Earning&lt;/th&gt; &lt;td&gt;{{totalEarnings}}&lt;/td&gt; &lt;td&gt;Total Deductions&lt;/td&gt; &lt;td&gt;{{deductions}}&lt;/td&gt; &lt;/tr&gt; &lt;/tbody&gt; &lt;/table&gt; &lt;/div&gt; &lt;div class="row"&gt; &lt;div class="col-md-4"&gt; &lt;br /&gt; &lt;span class="fw-bold"&gt;Net Pay : {{netSalary}}&lt;/span&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;div&gt; &lt;br /&gt; &lt;p&gt;**** This is a system generated payslip ****&lt;/p&gt; &lt;/div&gt; &lt;/div&gt; &lt;/body&gt; &lt;/html&gt; {{% /panel_with_adjustment %}} * Click the CSS tab and paste the following code {{% panel_with_adjustment header="CSS" footer="button" scroll="set-scroll" class="language-css line-numbers" %}}body { font-family: "Times New Roman", Times, serif; } table { width: 100%; border-radius: 5px solid; border-spacing: 0; margin-bottom: 20px; } tr { border: solid 1px #524f4f; border-top-color: #524f4f; } th, td { padding: 8px; text-align: left; color: #101f3e; background-color: #fff; } th { background-color: #f8f9fb !important; color: #7888a8; } p { text-align: center; color: black; } .color_primary { color: black; } .color_sec { color: #4d618a; } {{% /panel_with_adjustment %}} {{%note%}}{{%bold%}}Note:{{%/bold%}} You can create your own custom template design using the editor. You can also create complex templates using the {{%italics%}}JavaScript editor{{%/italics%}}, and use the {{%italics%}}JSON Data editor{{%/italics%}} to provide placeholder values.{{%/note%}} 5. Click **Save**. You can view the template that will be rendered to the user from the preview section on the right. <br /> 6. Click **Settings** to style and format the template further. <br /> 7. We encourage you to explore the various options and style the visual format elements of the template as you prefer. The *Live Preview* section will render all of your changes in real-time and display the template that will appear to the user. <br /> {{%note%}}{{%bold%}}Note:{{%/bold%}} For the purposes of this tutorial, we recommend that you set the {{%bold%}}Output Format{{%/bold%}} as PDF.{{%/note%}} 8. Click **Save Settings** to save your preferences. Click the **back-arrow icon** near the name of the template after you have completed customizing your template. <br /> Your custom template is saved, and you will be able to view the unique **Template ID** generated by Catalyst. To learn more about the Templates component, visit this {{%link href="/en/smartbrowz/help/templates/create-templates/" %}}help document{{%/link%}}. <br /> <br /> -------------------------------------------------------------------------------- title: "Test the Template" description: "Build a basic web app that uses Catalyst components to generate a PDF document from a dynamic custom payslip template, and email the generated document to the end-user." last_updated: "2026-03-18T07:41:08.693Z" source: "https://docs.catalyst.zoho.com/en/tutorials/payslip-generator-app/nodejs/test-template/" service: "All Services" related: - Catalyst SmartBrowz (/en/smartbrowz/getting-started/introduction/) - Templates (/en/smartbrowz/help/templates/create-templates/) -------------------------------------------------------------------------------- # Test Your Template Now that you have created your template, let's test it with sample JSON data to ensure that all of the data renders properly. To test the template: 1. Click **PDF & Screenshot** under *Convert* in the *SmartBrowz* side menu bar to access the component. <br /> 2. Click **Playground**, and choose **Template** as the *Input Type*. <br /> 3. Select the custom template you have created from the *Template* drop-down. <br /> 4. Paste the following JSON snippet as the template data in the editor. {{% panel_with_adjustment header="Sample JSON Data" footer="button" scroll="set-scroll" class="language-json line-numbers" %}}{ "company": "Zylker Technologies", "employeeName": "Amelia Burrows", "employeeId": "ZT-789", "designation": "QA Analyst", "basicSalary": 10000, "allowances": 4500, "deductions": 1450, "totalEarnings": 14500, "netSalary": 13050, "paymentMethod": "Bank Transfer", "month": "September", "year": "2023" } {{% /panel_with_adjustment %}} <br /> {{%note%}}{{%bold%}}Note:{{%/bold%}} The sample JSON data above is only applicable for the template design that we have provided. If you have used your own custom design, you will need to provide a suitable JSON data as the input.{{%/note%}} <!-- 5. Ensure **Default Settings** is set as the *Template Settings*. You can find out more on the functionality of Custom Settings from this {{%link href="/en/smartbrowz/help/pdfnscreenshot/implementation/#templates" %}}help document{{%/link%}}. <br /> --> 6. Click **Generate**. <br /> A preview window will open, and you can view your custom template with the JSON data rendered. You can click **Download** to save the visual document to your local system. <br /> -------------------------------------------------------------------------------- title: "Configure the email address" description: "Build a basic web app that uses Catalyst components to generate a PDF document from a dynamic custom payslip template, and email the generated document to the end-user." last_updated: "2026-03-18T07:41:08.693Z" source: "https://docs.catalyst.zoho.com/en/tutorials/payslip-generator-app/nodejs/setup-email/" service: "All Services" related: - Catalyst Cloud Scale (/en/cloud-scale/getting-started/introduction/) - Mail (/en/cloud-scale/help/mail/introduction/) -------------------------------------------------------------------------------- # Set Up Email In this step, we will use the {{%link href="/en/cloud-scale/getting-started/introduction/" %}}Catalyst Cloud Scale{{%/link%}} component, {{%link href="/en/cloud-scale/help/mail/introduction/" %}}Mail{{%/link%}}, to set up the sender email address. This is the address from where the payslips will be emailed to various employees. To configure the sender's email address: 1. Click the **Catalyst Cloud Scale** icon to access the *Cloud Scale* service, and click **Start Exploring**. <br /> 2. Click **Mail** under *Notify* to access the Mail component, and click **Add Email**. <br /> 3. Provide the required details for your sender email address, and click **Add Email**. <br /> The email details will be listed in the *Email Configuration* section. <br /> {{%note%}}{{%bold%}}Note:{{%/bold%}} This email address will be the email ID from where the emails are sent to the employees.{{%/note%}} 4. Click on **Click to confirm** to verify the email address provided. <br /> A confirmation code will be generated by Catalyst and sent to the email address you provided. <br /> 5. Copy the confirmation code from your email, paste it in the space provided, and click **Confirm**. <br /> 6. The email ID will be verified, and the verified status will be indicated under the *Confirmation Status* column. <br /> The email has been configured. You can learn more about the Mail component from this {{%link href="/en/cloud-scale/help/mail/introduction/" %}}help document{{%/link%}}. <br /> -------------------------------------------------------------------------------- title: "Initialize the project" description: "Build a basic web app that uses Catalyst components to generate a PDF document from a dynamic custom payslip template, and email the generated document to the end-user." last_updated: "2026-03-18T07:41:08.694Z" source: "https://docs.catalyst.zoho.com/en/tutorials/payslip-generator-app/nodejs/initialize-project/" service: "All Services" related: - Initialize CLI Resources (/en/cli/v1/initialize-resources/introduction/) - Project Directory Structure (/en/cli/v1/project-directory-structure/introduction/) -------------------------------------------------------------------------------- # Initialize the Project from the CLI You can now begin working on your Catalyst project from the CLI. The first step is to initialize the project in an empty directory. This will be the home directory of your project, and all of the project files will be saved in it. You can learn more about this from the {{%link href="/en/cli/v1/project-directory-structure/introduction/" %}}Project Directory Structure help page{{%/link%}}. You can learn about initializing a project in detail from the {{%link href="/en/cli/v1/project-directory-structure/introduction/" %}}CLI help documentation{{%/link%}}. For the payslip generator application, we will initialize the Advanced I/O function first, followed by the Client component. {{%note%}}{{%bold%}}Note:{{%/bold%}} We recommend that you enter the function's package name or class name and the client's name exactly as instructed, because the application's code contains the same name.{{%/note%}} 1. Create a folder for the project on your local machine and navigate to it from the terminal. 2. Initialize a project by executing the following command from that directory: {{%cli%}}catalyst init{{%/cli%}} 3. Navigate using the **arrow keys** and select your preferred portal and press the **Enter** key. If you have no other organizations associated with the account, then the default one will be automatically selected. <br /> You can find out more about Catalyst’s multi-org portal feature from this {{%link href="/en/getting-started/catalyst-projects/#access-the-multi-org-portal" %}}help document{{%/link%}}. 4. The CLI will now ask you to associate a Catalyst project with the directory. Associate it with the project that we created earlier from the console. Select **PayslipGenerator** from the list and press **Enter**. <br /> 5. Navigate using **arrow keys** and select **Functions**, **Client** using the **space bar**. Press the **Enter** key to initialize. <br /> 6. The CLI will initiate the function setup. Select **AdvancedIO** as the function type. <br /> 7. Select the latest runtime of *Node.js* as the function stack. <br /> 8. Enter "{{%badge%}}payslip_generator_function{{%/badge%}}" as the package name, "{{%badge%}}index.js{{%/badge%}}" as the entry point, and your email address, as the author and press **Enter**. You can alternatively press **Enter** without entering inputs to fill in the default values. The CLI will prompt the initialization of the Node dependencies. Press **Y** to confirm the installation, and press **Enter** to confirm your choice. The Node modules will be installed. <br /> 9. The CLI will now initiate the client setup. Select "**Basic web app**" and press **Enter** to initialize your client as a {{%link href="/en/cli/v1/initialize-resources/initialize-client/#basic-client-applications" %}}basic web app{{%/link%}}. <br /> 10. Enter "**PayslipGenerator**" as the name of your client package and press **Enter**. You can also provide any name of your choice. <br /> Catalyst initialization is now complete. The {{%link href="/en/cli/v1/project-directory-structure/introduction/" %}}project directory{{%/link%}} is now set up with the client directory and the functions directory along with configuration files and dependencies. The project directory also contains the {{%link href="/en/cli/v1/project-directory-structure/catalyst-json/" %}}{{%badge%}}catalyst.json{{%/badge%}}{{%/link%}} configuration file and a hidden {{%badge%}}.catalystrc{{%/badge%}} file. The structure of your project directory should appear as shown below: <br /> -------------------------------------------------------------------------------- title: "Configure the Advanced I/O function" description: "Build a basic web app that uses Catalyst components to generate a PDF document from a dynamic custom payslip template, and email the generated document to the end-user." last_updated: "2026-03-18T07:41:08.694Z" source: "https://docs.catalyst.zoho.com/en/tutorials/payslip-generator-app/nodejs/configure-function/" service: "All Services" related: - Functions (/en/serverless/help/functions/introduction/) - Advanced I/O Functions (/en/serverless/help/functions/advanced-io/) - Functions Directory Structure (/en/cli/v1/project-directory-structure/functions-directory/) -------------------------------------------------------------------------------- # Configure the Advanced I/O Function Now, we will begin coding the payslip generator application by configuring the function component. The {{%link href="/en/cli/v1/project-directory-structure/functions-directory" %}}function’s directory{{%/link%}}, {{%badge%}}functions/payslip_generator_function{{%/badge%}} contains: * The {{%badge%}}index.js{{%/badge%}} main function file * The {{%badge%}}catalyst-config.json{{%/badge%}} configuration file * Node modules * {{%link href="https://docs.npmjs.com/files/package.json" %}}{{%badge%}}package.json{{%/badge%}}{{%/link%}} and {{%link href="https://docs.npmjs.com/configuring-npm/package-lock-json.html" %}}{{%badge%}}package-lock.json{{%/badge%}}{{%/link%}} dependency files You will be adding code in the {{%badge%}}index.js{{%/badge%}} file. The Advanced I/O function contains the following functionalities: * Triggers the {{%link href="/en/sdk/nodejs/v2/smartbrowz/generate-pdfnscreenshot/#generate-visual-documents-using-template" %}}PDF & Screenshot SDK{{%/link%}} to run a headless browser where we render the inputted details onto the template and generate a PDF document. * Triggers the {{%link href="/en/sdk/nodejs/v2/cloud-scale/mail/send-email/" %}}Send Mail SDK{{%/link%}} to attach the PDF document and send it via email from within the application. ### Install Express Framework for Node.js We will be using the {{%link href="https://expressjs.com/" %}}Express framework{{%/link%}} to code the Advanced I/O function. To import the Express package in your function’s code, you must install the Express dependency in your system. To install {{%badge%}}Express.js{{%/badge%}} in your local machine, navigate to the function’s home directory ({{%badge%}}functions/payslip_generator_function{{%/badge%}}) in your terminal and execute the following command: {{%cli%}}npm install express --save{{%/cli%}} This will install the Express module and save the dependencies. <br /> This information will also be updated in the {{%badge%}}package.json{{%/badge%}} file. <br /> Now, let's begin coding the Advanced I/O function. Copy the code given below and paste it in the {{%badge%}}index.js{{%/badge%}} in the {{%badge%}}functions/payslip_generator_function{{%/badge%}} directory of your project, and save the file. You can use any IDE of your choice to work with the application's files. {{%note%}}{{%bold%}}Note:{{%/bold%}} * Please go through the code in this section to make sure you fully understand it. * Ensure you have provided your {{%bold%}}Template ID{{%/bold%}} in line {{%bold%}}33{{%/bold%}}, and the configured {{%bold%}}email ID{{%/bold%}} in line {{%bold%}}68{{%/bold%}}.{{%/note%}} {{% panel_with_adjustment class="language-javascript line-numbers" header="index.js" footer="button" scroll="set-scroll" %}}'use strict' const express = require('express') const catalyst = require('zcatalyst-sdk-node') const fs = require('fs') const app = express() const os = require('os') const path = require('path') app.use(express.json()) app.post('/generatepayslip', async (req, res) => { try { const catalystApp = catalyst.initialize(req) const smartbrowz = catalystApp.smartbrowz() if (!req.body) { throw new Error('Request body is empty') } const { employeeName, employeeEmail, employeeId, designation, basicSalary, allowances, deductions, paymentMethod } = req.body const date = new Date() const currentMonth = date.toLocaleString('default', { month: 'long' }) const currentYear = date.getFullYear() const filepath = path.join(os.tmpdir(), '/payslip.pdf') // Generate output from template await smartbrowz .generateFromTemplate('xxxxxxxx12345', // Provide your Template ID { // Data to be passed to the template retrieved from the client template_data: { company: 'Zylker Technologies', employeeName, employeeId, designation, basicSalary, allowances, deductions, totalEarnings: parseFloat(basicSalary) + parseFloat(allowances), netSalary: parseFloat(basicSalary) + parseFloat(allowances) - parseFloat(deductions), paymentMethod, month: currentMonth, year: currentYear } }) .then((inputStream) => { return new Promise((resolve, reject) => { inputStream .pipe(fs.createWriteStream(filepath)) .on('close', resolve) .on('error', reject) }) }).catch((err) => { throw err }) await catalystApp .email() .sendMail({ from_email: 'emmy@zylker.com', // Provide your email ID configured in the Console to_email: [employeeEmail], html_mode: true, subject: `Payslip for the month of ${currentMonth} ${currentYear}`, content: `Hello ${employeeName}, Your payslip for ${currentMonth} ${currentYear} has been issued. You can find your payslip attached with this email. Cheers,Zylker`, attachments: [fs.createReadStream(filepath)] // create a file stream for the file attachment }) .then((row) => { res.status(200).send('Payslip generated and sent to Employee email') }) .catch((err) => { throw err }) } catch (error) { console.log(error) res.status(500).send(error) } }) module.exports = app {{% /panel_with_adjustment %}} <br /> The function directory is now configured. We can now proceed to configuring the client directory. <br /> -------------------------------------------------------------------------------- title: "Configure the client" description: "Build a basic web app that uses Catalyst components to generate a PDF document from a dynamic custom payslip template, and email the generated document to the end-user." last_updated: "2026-03-18T07:41:08.694Z" source: "https://docs.catalyst.zoho.com/en/tutorials/payslip-generator-app/nodejs/configure-client/" service: "All Services" related: - Client Directory Structure (/en/cli/v1/project-directory-structure/client-directory/) - Web Client Hosting (/en/cloud-scale/help/web-client-hosting/introduction/) -------------------------------------------------------------------------------- # Configure the Client Now, let’s configure the client component. The {{%link href="/en/cli/v1/project-directory-structure/client-directory/" %}}client directory{{%/link%}} contains: * The {{%badge%}}index.html{{%/badge%}} file that contains the HTML code for the front-end application * The {{%badge%}}main.css{{%/badge%}} file that contains the CSS code for the front-end application * The {{%badge%}}main.js{{%/badge%}} file that contains the JavaScript code * The {{%badge%}}client-package.json{{%/badge%}} configuration file We will be coding {{%badge%}}index.html{{%/badge%}}, {{%badge%}}main.css{{%/badge%}}, and {{%badge%}}main.js{{%/badge%}}. {{%note%}}{{%bold%}}Note:{{%/bold%}} Please go through the code in this section to make sure you fully understand it.{{%/note%}} Copy the code below and paste it into the respective files located in the {{%badge%}}client/directory{{%/badge%}} of your project using an IDE and save the files. {{% panel_with_adjustment header="index.html" footer="button" scroll="set-scroll" class="language-xml line-numbers" %}}&lt;!DOCTYPE html&gt; &lt;html&gt; &lt;head&gt; &lt;link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/css/bootstrap.min.css" /&gt; &lt;script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.1/dist/js/bootstrap.bundle.min.js"&gt;&lt;/script&gt; &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"&gt;&lt;/script&gt; &lt;script src="main.js"&gt;&lt;/script&gt; &lt;link rel="stylesheet" type="text/css" href="main.css"/&gt; &lt;script&gt; window.addEventListener("DOMContentLoaded", function () { // Retrieve input elements var basicSalaryInput = document.getElementById("basicSalary"); var allowancesInput = document.getElementById("allowances"); var deductionsInput = document.getElementById("deductions"); var netSalaryInput = document.getElementById("netSalary"); // Add event listeners to input fields basicSalaryInput.addEventListener("input", calculateNetSalary); allowancesInput.addEventListener("input", calculateNetSalary); deductionsInput.addEventListener("input", calculateNetSalary); // Function to calculate net salary function calculateNetSalary() { // Retrieve values from input fields var basicSalary = parseFloat(basicSalaryInput.value) || 0; var allowances = parseFloat(allowancesInput.value) || 0; var deductions = parseFloat(deductionsInput.value) || 0; // Calculate net salary var netSalary = basicSalary + allowances - deductions; // Update the net salary input field netSalaryInput.value = netSalary.toFixed(2); } }); &lt;/script&gt; &lt;/head&gt; &lt;body&gt; &lt;div class="container mt-5 mb-5"&gt; &lt;h2&gt;Payslip Generator&lt;/h2&gt; &lt;form onsubmit="generatePayslip();return false;"&gt; &lt;div class="row"&gt; &lt;div class="form-group col-md-6"&gt; &lt;label for="employeeName"&gt;Employee Name:&lt;/label&gt; &lt;input type="text" id="employeeName" name="employeeName" required /&gt; &lt;/div&gt; &lt;div class="form-group col-md-6"&gt; &lt;label for="employeeId"&gt;Employee ID:&lt;/label&gt; &lt;input type="text" id="employeeId" name="employeeId" required /&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class="row"&gt; &lt;div class="form-group col-md-6"&gt; &lt;label for="designation"&gt;Employee Designation:&lt;/label&gt; &lt;input type="text" id="designation" name="designation" required /&gt; &lt;/div&gt; &lt;div class="form-group col-md-6"&gt; &lt;label for="employeeEmail"&gt;Employee Email:&lt;/label&gt; &lt;input type="text" id="employeeEmail" name="employeeEmail" required /&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class="row"&gt; &lt;div class="form-group col-md-6"&gt; &lt;label for="basicSalary"&gt;Basic Salary:&lt;/label&gt; &lt;input type="number" id="basicSalary" name="basicSalary" min="0" oninput="validity.valid||(value='');" required /&gt; &lt;/div&gt; &lt;div class="form-group col-md-6"&gt; &lt;label for="allowances"&gt;Allowances:&lt;/label&gt; &lt;input type="number" id="allowances" name="allowances" min="0" oninput="validity.valid||(value='');" required /&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class="row"&gt; &lt;div class="form-group col-md-6"&gt; &lt;label for="deductions"&gt;Deductions:&lt;/label&gt; &lt;input type="number" id="deductions" name="deductions" min="0" oninput="validity.valid||(value='');" required /&gt; &lt;/div&gt; &lt;div class="form-group col-md-6"&gt; &lt;label for="netSalary"&gt;Net Salary:&lt;/label&gt; &lt;input type="number" id="netSalary" name="netSalary" readonly /&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class="row"&gt; &lt;div class="form-group col-md-6"&gt; &lt;label for="paymentMethod"&gt;Payment Method:&lt;/label&gt; &lt;select id="paymentMethod" name="paymentMethod" required&gt; &lt;option value=""&gt;Select&lt;/option&gt; &lt;option value="Bank Transfer"&gt;Bank Transfer&lt;/option&gt; &lt;option value="Cheque"&gt;Cheque&lt;/option&gt; &lt;option value="Cash"&gt;Cash&lt;/option&gt; &lt;/select&gt; &lt;/div&gt; &lt;/div&gt; &lt;input type="submit" value="Submit" /&gt; &lt;/form&gt; &lt;/div&gt; &lt;/body&gt; &lt;/html&gt; {{% /panel_with_adjustment %}} {{% panel_with_adjustment header="main.css" footer="button" scroll="set-scroll" class="language-css line-numbers" %}}.container { background-image: linear-gradient(to bottom, #ffffff, #f2f2f2); padding: 40px; margin-top: 50px; margin-bottom: 50px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); } h2 { background: linear-gradient(to right, #4caf50, #45a049); -webkit-background-clip: text; -webkit-text-fill-color: transparent; text-align: center; margin-bottom: 40px; } /* Styling for the form labels &#42;/ label { transition: color 0.3s ease; /* Add a subtle animation on hover */ } label:hover { /* Change the color on hover */ color: #4caf50; } /* Styling for the form input fields &#42;/ input[type="text"], input[type="number"], select { /* Increase the height of the input fields &#42;/ height: 40px; /* Add a subtle box shadow */ } /* Styling for the form input groups */ .form-group { display: flex; align-items: center; margin-bottom: 10px; } .form-group label { flex: 0 0 200px; /* Set a fixed width for the labels &#42;/ margin-right: 10px; /* Add some spacing between label and input */ } .form-group input, .form-group select { flex: 1; /* Allow the inputs to take up remaining space &#42;/ } /* Styling for the submit button &#42;/ input[type="submit"] { /* Add a gradient background &#42;/ background-image: linear-gradient(to right, #4caf50, #45a049); /* Add a box shadow &#42;/ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3); margin-top: 15px; width: 150px; margin-left: 600px; } input[type="submit"]:hover { /* Darken the background on hover */ background-image: linear-gradient(to right, #45a049, #398e3d); } {{% /panel_with_adjustment %}} <br /> {{%note%}}{{%bold%}}Note:{{%/bold%}} The Node.js function package’s name {{%badge%}}payslip_generator_function{{%/badge%}} has been added in the code for {{%badge%}}main.js{{%/badge%}} in the line {{%bold%}}13{{%/bold%}}. If you have provided a different package name, ensure you replace accordingly.{{%/note%}} <br /> {{% panel_with_adjustment header="main.js" footer="button" class="language-javascript line-numbers" scroll="set-scroll" %}} function generatePayslip() { // Retrieve form values const employeeName = document.getElementById('employeeName').value; const employeeId = document.getElementById('employeeId').value; const designation = document.getElementById('designation').value; const paymentMethod = document.getElementById('paymentMethod').value; const employeeEmail = document.getElementById('employeeEmail').value; const basicSalary = parseFloat(document.getElementById('basicSalary').value); const allowances = parseFloat(document.getElementById('allowances').value); const deductions = parseFloat(document.getElementById('deductions').value); $.ajax({ url: '/server/payslip_generator_function/generatepayslip', //provide your function endpoint here type: 'post', contentType: 'application/json', data: JSON.stringify({ employeeName, employeeId, basicSalary, allowances, deductions, designation, paymentMethod, employeeEmail }), success: function (data) { alert(data); window.location.reload(); }, error: function (error) { console.log(error); alert(error.responseText); window.location.reload(); } }); } {{% /panel_with_adjustment %}} The client directory is now configured. Let’s go over the working of the function and the client code: * The end-user enter inputs the employee details in the client-side. When the end-user clicks **Submit**, a {{%badge%}}POST{{%/badge%}} call in {{%badge%}}main.js{{%/badge%}} triggers the {{%badge%}}/generatepayslip{{%/badge%}} API endpoint and the data is passed to the function in a JSON format. * The function triggers the {{%link href="/en/sdk/nodejs/v2/smartbrowz/generate-pdfnscreenshot/#generate-visual-documents-using-template" %}}PDF & Screenshot SDK{{%/link%}} and the request body is passed and the PDF document is generated. The PDF is then stored in a temporary location. * The {{%link href="/en/sdk/nodejs/v2/cloud-scale/mail/send-email/" %}}Send Mail SDK{{%/link%}} is triggered and the PDF document is read from the temporary location and attached to the email. The email is sent to the employee from the email ID set up using the {{%link href="/en/cloud-scale/help/mail/introduction/" %}}Mail{{%/link%}} component. * A response containing the acknowledgement message will be displayed on the client-side, after the PDF document has been emailed. <br /> -------------------------------------------------------------------------------- title: "Test the application" description: "Build a basic web app that uses Catalyst components to generate a PDF document from a dynamic custom payslip template, and email the generated document to the end-user." last_updated: "2026-03-18T07:41:08.695Z" source: "https://docs.catalyst.zoho.com/en/tutorials/payslip-generator-app/nodejs/test-app/" service: "All Services" related: - Serve CLI Resources (/en/cli/v1/serve-resources/introduction/) -------------------------------------------------------------------------------- # Test the Application Before you deploy the application to the remote console, you can test the application on a local server and check if everything works using the Catalyst CLI. For detailed information on {{%badge%}}catalyst serve{{%/badge%}}, refer to the {{%link href="/en/cli/v1/serve-resources/introduction" %}}Serve Resources help page{{%/link%}}. To serve the Catalyst project locally, execute the following command from your project directory: {{%cli%}}catalyst serve{{%/cli%}} The payslip generator application will now be served at default {{%badge%}}port 3000{{%/badge%}}. The local endpoint URLs of the components will be displayed in the CLI. <br /> {{%note%}}{{%bold%}}Note:{{%/bold%}} Every time you access the home page or any of the sub-pages of your client, or the function, the CLI will display a live log of the URL accessed, along with the HTTP method that is used to access it.{{%/note%}} You can now open the client component’s local URL in a browser to access the application. <br /> Add sample data in the form to test the functionality of the application, and click **Submit**. <br /> You will get a success prompt after the email is sent. <br /> Log in to the email account you had entered here, and you will find an email that contains the payslip as a PDF attachment. <br /> If you view the attachment, you will find the details you inputted in the form rendered in your custom template. <br /> Depending on the email provider you use, you will also be able to download and save the {{%badge%}}payslip.pdf{{%/badge%}} document in your local system. If the test run was successful, we can deploy the project to the console. <br /> -------------------------------------------------------------------------------- title: "Deploy the project" description: "Build a basic web app that uses Catalyst components to generate a PDF document from a dynamic custom payslip template, and email the generated document to the end-user." last_updated: "2026-03-18T07:41:08.695Z" source: "https://docs.catalyst.zoho.com/en/tutorials/payslip-generator-app/nodejs/deploy-app/" service: "All Services" related: - Deploy CLI Resources (/en/cli/v1/deploy-resources/introduction/) - Web Client Hosting (/en/cloud-scale/help/web-client-hosting/introduction/') -------------------------------------------------------------------------------- # Deploy the Project To {{%link href="/en/cli/v1/deploy-resources/introduction/" %}}deploy your Catalyst project{{%/link%}} from the CLI, run the following command in your terminal from your project directory: {{%cli%}}catalyst deploy{{%/cli%}} The function is deployed first, followed by the client component. The URL endpoints of the components will be displayed in the CLI: <br /> You can now open the client component’s URL in a browser to access the deployed application. The payslip generator application can now be accessed from its web app URL. <br /> The payslip generator application is now functional and will work without any errors. <br />