--- title: "Code Your Application" url: https://docs.catalyst.zoho.com/en/tutorials/alien-city-appsail/python/code-app/ description: "Create an application and host it on Catalyst using the Catalyst AppSail service and Catalyst Data Store that allows you to report or look up alien encounters in a city." last_updated: 2026-08-17T12:16:04Z service: All Services type: tutorial related_links: - name: "Catalyst SDK for AppSail" url: /en/cli/v1/initialize-resources/introduction/ --- # Code Your Application Let's begin coding the application. Create the following files and directories to store your code: * A Python code file in your project's root directory (`AlienCity/`), name it "**app.py**". This file will contain the backend logic for your application. * A folder in your project's root directory, name it "**static**", and create the following files inside it (`AlienCity/static/`): - **index.html**: Contains the HTML code for the frontend of the application - **main.js**: Contains the JavaScript code of your application This is the final folder structure of the *AlienCity* project: ![catalyst_alien_city_cli_appsail_py_complete_dir](https://catalyst-docs-development.zohostratus.in/images/tutorials/alien-city-appsail-express/catalyst_alien_city_cli_appsail_py_complete_dir.webp) You will be coding the `app.py`, `index.html`, and `main.js` files. You will also be updating the `app-config.json` file. > **Note:** Please go through the code in this section to make sure you fully understand it. Copy the code below and paste it into the respective files of your project using an IDE and save the files. **app.py** ```python import sys sys.path.insert(0, './lib') from flask import Flask, request, jsonify import os import zcatalyst_sdk import logging tableName = 'AlienCity' # The table created in the Data Store columnName = 'CityName' app = Flask(__name__) @app.route('/') def index(): return app.send_static_file('index.html') @app.route('/alien', methods=['POST']) def post_alien_encounter(): try: logger = logging.getLogger() capp = zcatalyst_sdk.initialize(req=request) req_data = request.get_json() name = req_data.get('city_name') rowid = getAlienCountFromCatalystDataStore(request,name) # Queries the Catalyst Data Store table and checks whether a row is present for the given city if len(rowid) == 0: # If the row is not present, then a new row is inserted logger.info("Alien alert!") # Written to the logs. You can view this log from Logs under the Monitor section in the console datastore_service = capp.datastore() table_service = datastore_service.table(tableName) row_data = { columnName:name } table_service.insert_row(row_data) # Inserts the city name as a row in the Catalyst Data Store table return jsonify({ "message":"Thanks for reporting!!!" }),200 else: return jsonify({ "message": "Looks like you are not the first person to encounter aliens in this city! Someone has already reported an alien encounter here!" }), 200 except Exception as e: # If the row is present, then a message is sent indicating duplication print(e) return jsonify({ "message": "Internal server error" }), 500 @app.route('/alien', methods=['GET']) def get_alien_encounter(): try: name = request.args.get('city_name') rowid = getAlienCountFromCatalystDataStore(request,name) # Queries the Catalyst Data Store table and checks whether a row is present for the given city if len(rowid) == 0: return jsonify({ "message": "Hurray! No alien encounters in this city yet!", "signal": "negative" }), 200 else: return jsonify({ "message": "Uh oh! Looks like there are aliens in this city!", "signal": "positive" }), 200 except Exception as e: print(e) return jsonify({ "message": "Internal server error" }), 500 def getAlienCountFromCatalystDataStore(request,cityname): # Checks whether an alien encounter is already reported for the given city by querying the Data Store table capp = zcatalyst_sdk.initialize(req=request) zcql_service = capp.zcql() query = f"SELECT * FROM {tableName} WHERE {columnName} = '{cityname}'" output = zcql_service.execute_query(query) return output if __name__ == '__main__': port = int(os.environ.get('X_ZOHO_CATALYST_LISTEN_PORT', 9000)) app.run(host='0.0.0.0', port=port) ``` **index.html** ```xml <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>AlientCityAppClient</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" type="text/css" media="screen" href="main.css" /> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"> </script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"> </script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"> </script> <script src="static/main.js"> </script> </head> <body> <br> <br> <center> <h1>ALIEN CITY</h1> </center> <div class="container"> <ul class="nav nav-tabs" id="myTab" role="tablist"> <li class="nav-item"> <a class="nav-link active" id="check-tab" data-toggle="tab" href="#check" role="tab" aria-controls="check" aria-selected="true">Check My City</a> </li> <li class="nav-item"> <a class="nav-link" id="report-tab" data-toggle="tab" href="#report" role="tab" aria-controls="report" aria-selected="false">Report Alien Encounter</a> </li> </ul> <div class="tab-content" id="myTabContent"> <div class="tab-pane fade show active" id="check" role="tabpanel" aria-labelledby="check-tab"> <br> <br> <form> <div class="form-group"> <label for="city-get-input"> <b>Check if your city has aliens:</b> </label> <input type="text" class="form-control" id="city-get-input" aria-describedby="checkCity" placeholder="Enter City Name"> </div> <button type="submit" class="btn btn-primary" onclick="getAlienEncounter();return false;">Check</button> </form> <br> <br> <div id="result-container"> <div id="result-text"> </div> <br> <div id="result-image"> </div> </div> <div id="loader" style="display: none;"> <div class="spinner-border" role="status"> <span class="sr-only">Loading...</span> </div> </div> </div> <div class="tab-pane fade" id="report" role="tabpanel" aria-labelledby="report-tab"> <br> <br> <form> <div class="form-group"> <div class="city-post-input"> <label for="exampleInputEmail1"> <b>Enter the name of the city where you encountered an alien:</b> </label> <input type="text" class="form-control" id="city-post-input" aria-describedby="cityPost" placeholder="Enter City Name"> </div> </div> <button type="submit" class="btn btn-primary" onclick="postAlienEncounter();return false;">Report</button> </form> </div> </div> </div> </body> </html> ``` **main.js** ```javascript function postAlienEncounter() { debugger; var city = $("#city-post-input").val(); $.ajax({ url: "/alien", type: "post", contentType: "application/json", data: JSON.stringify({ "city_name": city }), success: function (data) { alert(data.message); }, error: function (error) { alert(error.message); } }); } function getAlienEncounter() { debugger showLoader(); var positive = "https://media.giphy.com/media/Y1GYiLui9NHcxVKhdo/giphy.gif"; var negative = "https://media.giphy.com/media/fsPcMdeXPxSP6zKxCA/giphy.gif"; var city = $("#city-get-input").val(); $.ajax({ url: "/alien?city_name=" + city, type: "get", success: function (data) { console.log(data); $("#result-text").text(""); $("#result-text").text(data.message); var imagesrc = negative; if (data.signal == 'positive') { imagesrc = positive; } $("#result-image").html(""); $("#result-image").html("<img src='" + imagesrc + "' />"); hideLoader(); }, error: function (error) { alert(error.message); } }); } function showLoader() { $("#result-container").hide(); $("#loader").show(); } function hideLoader() { $("#loader").hide(); $("#result-container").show(); } ``` Update the value of the key `command` as "**python3 app.py**" in the `app-config.json` file. This is the [startup command](https://docs.catalyst.zoho.com/en/serverless/help/appsail/key-concepts/appsail-execution/#startup-commands) that is specific for this programming stack and framework. **app-config.json** ```json { "command": "python3 app.py", "buildPath": "/Users/amelia-426/Catalyst/Alien City", // provide your build path "stack": "python_3_9", "env_variables": {}, "memory": 256, "scripts": {} } ``` Let’s quickly go through the working of the application: 1. **GET Operation** * When you enter a city name in the application to check for a record of previous alien encounters, the onClick event for the **Check** button in `index.html` triggers the `getAlienEncounter()` function defined in `main.js`. * This fires an Ajax call to the URL route defined in the function. The `GET` API defined in the `app.py` then invokes the `getAlienCountFromCatalystDataStore()` function and passes the request query. * This function searches for the data in the *AlienCity* table in the Data Store by executing a ZCQL query. * If a record matching the city name is found in the table, a *positive* signal is sent as the response. Otherwise, a *negative* signal is sent as the response. * The application then displays a message that matches the response. A GIF matching the response defined in `main.js` is also displayed. 2. **POST Operation** * When you enter a city name in the application to report an alien encounter, the onClick event for the **Report** button in `index.html` triggers the `postAlienEncounter()` function defined in `main.js`. * This fires an Ajax call to the URL route defined in the function. The `POST` API defined in `app.py` then invokes the `getAlienCountFromCatalystDataStore()` function and passes a request query to check if a record with the same city name already exists. * This function searches for the data in the *AlienCity* table in the Data Store by executing a ZCQL query. If the record already exists, a response is sent, which enables the client to display an appropriate message to the user. * If there are no records for the city name, a new row is created in the *AlienCity* table for the city name entered by the user. A pop-up box is displayed in the client confirming the insertion of the record in the Data Store. An appropriate message is also pushed to the logs which can be checked from [Logs](https://docs.catalyst.zoho.com/en/devops/help/logs/introduction/), a [Catalyst DevOps](https://docs.catalyst.zoho.com/en/devops/getting-started/introduction/) component under the *Monitor* section in the *DevOps* service section of the console.