--- title: "Configure AppSail Service" url: https://docs.catalyst.zoho.com/en/tutorials/photo-store-app/nodejs/config-appsail/ description: "Build a React gallery app to upload and share images in a Stratus bucket. Host the app on AppSail and deploy it from GitHub using Pipelines." last_updated: 2026-11-04T10:10:44Z service: All Services type: tutorial related_links: - name: "Catalyst Stratus" url: /en/cloud-scale/help/stratus/introduction/ - name: "Catalyst AppSail" url: /en/serverless/help/appsail/introduction/ - name: "Catalyst Pipelines" url: /en/pipelines/help/pipelines/introduction/ - name: "Serve Resources" url: /en/cli/v1/serve-resources/introduction/ - name: "Deploy Resources" url: /en/cli/v1/deploy-resources/introduction/ --- # Configure AppSail Service Before we deploy your [AppSail](https://docs.catalyst.zoho.com/en/serverless/help/appsail/introduction/) service to the console, you need to add the following files and code to your project directory: - Create a folder named `server` in your project root directory, and create the following files in them: - `index.js`: This file will act as the proxy server to server your compiled react files. - Create a folder named `scripts`, and add the following files to it: - `filesHelper.js`: This file will be used to copy the files from the `server` and `photo-store-app` directories to the AppSail build path. - Create a folder named `build` in your project's root directory. This folder will contain the compiled react files of your client. You need to point this folder as your build path to start your application. Create the following folders in the build directory. - `server` - `photo-store-app` The application's directory should now appear in the following manner: ![catalyst_tutorials_photostore_stratus_second_dir_struct](https://catalyst-docs-development.zohostratus.in/images/tutorials/photo-store/catalyst_tutorials_photostore_stratus_second_dir_struct.webp) Next navigate to the `PhotoStoreApp/server/` directory and perform the following steps: 1. Run the following CLI command from your terminal: ```sh npm init ``` ![catalyst_tutorials_photostore_stratus_npm_start_appsail_npm_init](https://catalyst-docs-development.zohostratus.in/images/tutorials/photo-store/catalyst_tutorials_photostore_stratus_npm_start_appsail_npm_init.webp) 2. Run the following command to install the *Express* package to handle HTTP requests and responses. ```sh npm install express --save ``` ![catalyst_tutorials_photostore_stratus_express_install](https://catalyst-docs-development.zohostratus.in/images/tutorials/photo-store/catalyst_tutorials_photostore_stratus_express_install.webp) This will also create a `node_modules` folder in the `PhotoStoreApp/server` directory. 3. Add the following code to your `index.js` file present in the `PhotoStoreApp/server/` directory. **index.js** ```js 'use strict'; const express = require('express'); const path = require('path'); const app = express(); const appDir = path.join(__dirname, '../photo-store-app'); const port = process.env.X_ZOHO_CATALYST_LISTEN_PORT || 9000; app.get('/', function (req, res) { res.sendFile(path.join(appDir)); }); app.use(express.static(appDir)); app.listen(port, () => { console.log(`Example app listening on port ${port}`); }); ``` ![catalyst_tutorials_photostore_stratus_express_install](https://catalyst-docs-development.zohostratus.in/images/tutorials/photo-store/catalyst_tutorials_photostore_stratus_express_install.webp) > **Note:** You need to use the environment variable '`X_ZOHO_CATALYST_LISTEN_PORT`' to listen to the port configured by Catalyst. 4. Next, navigate to the `scripts` folder present in the `PhotoStoreApp/scripts` directory and execute the following command: ```sh npm init ``` Ensure you enter the defaults, and this command will create a `package.json` file. ![catalyst_tutorials_photostore_stratus_npm_start_appsail_scripts_npminit](https://catalyst-docs-development.zohostratus.in/images/tutorials/photo-store/catalyst_tutorials_photostore_stratus_npm_start_appsail_scripts_npminit.webp) 5. Execute the following command in your `scripts` folder to install the required packages: ```sh npm install path util fs ``` ![catalyst_tutorials_photostore_stratus_npm_start_appsail_scripts_npm_packs](https://catalyst-docs-development.zohostratus.in/images/tutorials/photo-store/catalyst_tutorials_photostore_stratus_npm_start_appsail_scripts_npm_packs.webp) This command will install the following packages: - `path`: This package will be used to handle file and directory paths. - `util`: This package is required to use utilities like `promisify`, `inherits`, and so on. - `fs`: This package is required to implement file system operations. 6. Copy the following code and paste it in the `filesHelper.js` file present in the `PhotoStoreApp/scripts` directory. **filesHelper.js** ```js const Path = require('path'); const { promisify } = require('util'); const Fs = require('fs'); const readdir = promisify(Fs.readdir); const stat = promisify(Fs.stat); const copyFile = promisify(Fs.copyFile); const mkdir = promisify(Fs.mkdir); const unlink = promisify(Fs.unlink); const rmdir = promisify(Fs.rmdir); if (process.argv.length < 4) { console.error('Usage: node copyAndDelete.js [-c|-d] <sourcePath> <destinationPath>'); process.exit(1); } const operation = process.argv[2]; if (operation !== '-c' && operation !== '-d') { console.error('Invalid operation. Use -c for copy or -d for delete.'); process.exit(1); } if (operation === '-c') { const sourcePath = Path.resolve(process.argv[3]); const destinationPath = Path.resolve(process.argv[4]); copyFolders(sourcePath, destinationPath) .then(() => { console.log('Copy completed successfully.'); }) .catch((err) => { console.error(`Error: ${err}`); }); } else if (operation === '-d') { const sourcePath = Path.resolve(process.argv[3]); deleteFolder(sourcePath) .then(() => { console.log('Delete completed successfully.'); }) .catch((err) => { console.error(`Error: ${err}`); }); } async function copyFolders(source, destination) { try { await mkdir(destination, { recursive: true }); const files = await readdir(source); for (const file of files) { const sourceFilePath = Path.join(source, file); const destFilePath = Path.join(destination, file); const fileStat = await stat(sourceFilePath); if (fileStat.isDirectory()) { await copyFolders(sourceFilePath, destFilePath); } else { await copyFile(sourceFilePath, destFilePath); } } } catch (err) { throw err; } } async function deleteFolder(destinationPath) { try { const files = await readdir(destinationPath); for (const file of files) { const filePath = Path.join(destinationPath, file); const fileStat = await stat(filePath); if (fileStat.isDirectory()) { await deleteFolder(filePath); } else { await unlink(filePath); } } await rmdir(destinationPath); } catch (err) { throw err; } } ``` Now, navigate to the `app-config.json` file present in the project directory `PhotoStoreApp/app-config.json` and paste the following code. **app-config.json** ```json { "command": "node ./server/index.js", "build_path": "./build", "stack": "node24", "env_variables": {}, "memory": 256, "scripts": { "preserve": "cd photo-store-app && npm run build && cd .. && cd server && npm install && cd .. && cd scripts && npm install && cd .. && node ./scripts/filesHelper.js -c ./server/ ./build/server/ && node ./scripts/filesHelper.js -c ./photo-store-app/build/ ./build/photo-store-app/", "postserve": "node ./scripts/filesHelper.js -d ./build/server && node ./scripts/filesHelper.js -d ./build/photo-store-app", "predeploy": "cd photo-store-app && npm run build && cd .. && node ./scripts/filesHelper.js -c ./server/ ./build/server/ && node ./scripts/filesHelper.js -c ./photo-store-app/build/ ./build/photo-store-app/", "postdeploy": "node ./scripts/filesHelper.js -d ./build/server && node ./scripts/filesHelper.js -d ./build/photo-store-app" }, "raw": {}, "catalyst_auth": true, "login_redirect": "/index.html" } ``` > **Note**: You need to include the the following key value pairs in the `app-config.json` file: * `catalyst_auth` key's value needs to be set as true, to enable [Catalyst Authentication](https://docs.catalyst.zoho.com/en/cloud-scale/help/authentication/introduction/) for the AppSail service. * You need to set the value of `login_redirect` key as `index.html` to ensure proper redirection after authentication process. ### Test and Deploy the AppSail Service Next, navigate to your project's root directory. To check if all the steps completed thus far are error free, we are going to serve the application from the CLI using the following Catalyst CLI command: ```sh catalyst serve ``` ![catalyst_tutorials_photostore_stratus_pipelines_serve_cli_1](https://catalyst-docs-development.zohostratus.in/images/tutorials/photo-store/catalyst_tutorials_photostore_stratus_pipelines_serve_cli_1.webp) This command will serve the application on your localhost. The local endpoint URLs of the components are displayed. ![catalyst_tutorials_photostore_stratus_catalyst_serve_init_2](https://catalyst-docs-development.zohostratus.in/images/tutorials/photo-store/catalyst_tutorials_photostore_stratus_catalyst_serve_init_2.webp) If the application is error free, the AppSail service will be successfully compiled and served typically on `localhost:3001`. > **Info:** 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 request method. Once you ensure the application is running error free, you can [deploy the application](https://docs.catalyst.zoho.com/en/cli/v1/deploy-resources/introduction/) to the Catalyst console using the following Catalyst CLI command: ```sh catalyst deploy ``` ![catalyst_tutorials_photostore_stratus_catalyst_deploy](https://catalyst-docs-development.zohostratus.in/images/tutorials/photo-store/catalyst_tutorials_photostore_stratus_catalyst_deploy.webp) The application will now be deployed to the Catalyst console. You can access the AppSail service in the console by navigating to the **AppSail** component present in the *Catalyst Serverless* section. ![catalyst_tutorials_photostore_stratus_pipelines_icons](https://catalyst-docs-development.zohostratus.in/images/tutorials/photo-store/app-sail-navigation-photostore-app.webp) You can find more details about the *AppSail* service by clicking on the required service. ![catalyst_tutorials_photostore_stratus_catalyst_appsail_service_url_first_dep](https://catalyst-docs-development.zohostratus.in/images/tutorials/photo-store/catalyst_tutorials_photostore_stratus_catalyst_appsail_service_url_first_dep.webp) The AppSail service has been configured for your application. ### Enable Bucket CORS Once the AppSail service is deployed to the Catalyst console, we will have the application URL. Given that the domains for the bucket and the AppService are different, we need to enable Cross-Origin Resource Sharing (CORS) policy to authenticate and allow seamless interaction between the AppSail service and the Bucket. > **Info:** [Learn more about Bucket CORS](https://docs.catalyst.zoho.com/en/cloud-scale/help/stratus/stratus-config/bucket-cors/) To enable Bucket CORS: 1. Navigate to your Bucket present in Stratus. ![catalyst_tutorials-photostore-app-stratus-cors-start](https://catalyst-docs-development.zohostratus.in/images/tutorials/photo-store/catalyst_tutorials-photostore-app-stratus-cors-start.webp) 2. Navigate to the **Bucket CORS** section present in the **Configurations** tab, and click **Add Domain**. ![catalyst_tutorials-photostore-app-stratus-cors-config-domain](https://catalyst-docs-development.zohostratus.in/images/tutorials/photo-store/catalyst_tutorials-photostore-app-stratus-cors-config-domain.webp) 3. Select all **Request Methods** provided in the drop-down and paste the AppSail service's URL generated in the previous step. ![catalyst_tutorials-photostore-app-stratus-cors-domain-adding](https://catalyst-docs-development.zohostratus.in/images/tutorials/photo-store/catalyst_tutorials-photostore-app-stratus-cors-domain-adding.webp) 4. Click **Add**, and CORS will be enabled for the AppSail service, ensuring secure access. ![catalyst_tutorials-photostore-app-stratus-cors-domain-added](https://catalyst-docs-development.zohostratus.in/images/tutorials/photo-store/catalyst_tutorials-photostore-app-stratus-cors-domain-added.webp) ### Setup GitHub With the application deployed to the Catalyst console, you need to ensure that you have pushed the application files to your GitHub account. ![catalyst_tutorials_photostore_stratus_github_first_deploy](https://catalyst-docs-development.zohostratus.in/images/tutorials/photo-store/catalyst_tutorials_photostore_stratus_github_first_deploy.webp) > **Note:** Going ahead, we are going to implement the [Pipelines](https://docs.catalyst.zoho.com/en/pipelines/help/pipelines/introduction/) service to deploy the application and sync the GitHub project with the Catalyst console.