diff --git a/README.md b/README.md index 6662e66..f159feb 100644 --- a/README.md +++ b/README.md @@ -15,14 +15,15 @@ Both contain the necessary steps to complete the exercise. ## Demos -| Demo | Description | Level | -| --- | --- | --- | -| [Simple Javascript Calculator](demos/Javascript-calculator) | A simple calculator that adds two numbers together | Easy | -| [Node Calculator](demos/Node-calculator) | A simple calculator that adds two numbers together | Easy | -| [NodeJS WebApp](demos/NodeJS-WebApp-Simple) | A simple NodeJS webapp that uses ExpressJS to serve a simple HTML page | Easy | -| [NodeJS app that runs shell commands](demos/Command-Execution-WebApp-NodeJS) | A NodeJS webapp that runs shell commands | Medium | +| Demo | Description | +| --- | --- | +| [Simple Javascript Calculator](demos/Javascript-calculator) | A simple calculator that adds two numbers together | +| [Node Calculator](demos/Node-calculator) | A simple calculator that adds two numbers together | +| [NodeJS app that runs shell commands with Copilot Chat](demos/Command-Execution-WebApp-NodeJS) | A NodeJS webapp that runs shell commands with Copilot Chat | +| [NodeJS app that runs shell commands without Copilot Chat](demos/Command-Execution-WebApp-NodeJS) | A NodeJS webapp that runs shell commands without Copilot Chat. Use this for customer `who does not want to use Copilot Chat or cannot` | ## Contribution Do you want to contribute to the project? That is great! Please read [**CONTRIBUTING.md**](CONTRIBUTING.md) guide to make the contribution to this repository. + diff --git a/demos/Command-Execution-WebApp-NodeJS/README.md b/demos/Command-Execution-WebApp-NodeJS-CopilotChat/README.md similarity index 97% rename from demos/Command-Execution-WebApp-NodeJS/README.md rename to demos/Command-Execution-WebApp-NodeJS-CopilotChat/README.md index 1b7e657..a2d3457 100644 --- a/demos/Command-Execution-WebApp-NodeJS/README.md +++ b/demos/Command-Execution-WebApp-NodeJS-CopilotChat/README.md @@ -1,6 +1,6 @@ -# How to build a fun NodeJS application that executes shell commands in a browser +# How to build a fun NodeJS application that executes shell commands in a browser - Copilot Chat version -This is a simple NodeJS application that executes shell commands in a browser using **Github Copilot**. Please follow instructions below to build and run the application. This demo will primarily drive using **Github Copilot Chat** to build the application. It is possible to use other Interative Development Editor (IDEs) that support GitHub Copilot and GitHub Copilot Chat, but it is easier to follow and better experience to use VS Code. +This is a simple NodeJS application that executes shell commands in a browser using **Github Copilot**. Please follow instructions below to build and run the application. This demo will primarily drive using **Github Copilot Chat** to build the application. It is possible to use other Integrated Development Environment (IDEs) that support GitHub Copilot and GitHub Copilot Chat, but it is easier to follow and better experience to use VS Code. ## Prerequisites @@ -10,13 +10,13 @@ This is a simple NodeJS application that executes shell commands in a browser us - GitHub Copilot extension installed in VS Code - GitHub Copilot Chat extension installed in VS Code -## Step-by-step guides +## Step-by-step guide Please follow the instruction below. ### Step 1: Make sure that all prerequisites are met -Make sure that you met all prerequisites are met :) +Make sure that you met all prerequisites above. ### Step 2: Open Visual Studio Code with GitHub Copilot Chat diff --git a/demos/Command-Execution-WebApp-NodeJS/images/0_CopilotChatOpen.jpg b/demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/0_CopilotChatOpen.jpg similarity index 100% rename from demos/Command-Execution-WebApp-NodeJS/images/0_CopilotChatOpen.jpg rename to demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/0_CopilotChatOpen.jpg diff --git a/demos/Command-Execution-WebApp-NodeJS/images/10_AskCopilotStep3_Step1.jpg b/demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/10_AskCopilotStep3_Step1.jpg similarity index 100% rename from demos/Command-Execution-WebApp-NodeJS/images/10_AskCopilotStep3_Step1.jpg rename to demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/10_AskCopilotStep3_Step1.jpg diff --git a/demos/Command-Execution-WebApp-NodeJS/images/11_WebsiteHistoryView.jpg b/demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/11_WebsiteHistoryView.jpg similarity index 100% rename from demos/Command-Execution-WebApp-NodeJS/images/11_WebsiteHistoryView.jpg rename to demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/11_WebsiteHistoryView.jpg diff --git a/demos/Command-Execution-WebApp-NodeJS/images/12_AskCopilotChat_Step4.jpg b/demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/12_AskCopilotChat_Step4.jpg similarity index 100% rename from demos/Command-Execution-WebApp-NodeJS/images/12_AskCopilotChat_Step4.jpg rename to demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/12_AskCopilotChat_Step4.jpg diff --git a/demos/Command-Execution-WebApp-NodeJS/images/13_AskCopilot_Step5.jpg b/demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/13_AskCopilot_Step5.jpg similarity index 100% rename from demos/Command-Execution-WebApp-NodeJS/images/13_AskCopilot_Step5.jpg rename to demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/13_AskCopilot_Step5.jpg diff --git a/demos/Command-Execution-WebApp-NodeJS/images/14_WebsiteClickableLink.jpg b/demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/14_WebsiteClickableLink.jpg similarity index 100% rename from demos/Command-Execution-WebApp-NodeJS/images/14_WebsiteClickableLink.jpg rename to demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/14_WebsiteClickableLink.jpg diff --git a/demos/Command-Execution-WebApp-NodeJS/images/15_AskCopilot_Step6.jpg b/demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/15_AskCopilot_Step6.jpg similarity index 100% rename from demos/Command-Execution-WebApp-NodeJS/images/15_AskCopilot_Step6.jpg rename to demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/15_AskCopilot_Step6.jpg diff --git a/demos/Command-Execution-WebApp-NodeJS/images/16_WebsiteHighlighting.jpg b/demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/16_WebsiteHighlighting.jpg similarity index 100% rename from demos/Command-Execution-WebApp-NodeJS/images/16_WebsiteHighlighting.jpg rename to demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/16_WebsiteHighlighting.jpg diff --git a/demos/Command-Execution-WebApp-NodeJS/images/17_AskCopilot_Step6.jpg b/demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/17_AskCopilot_Step6.jpg similarity index 100% rename from demos/Command-Execution-WebApp-NodeJS/images/17_AskCopilot_Step6.jpg rename to demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/17_AskCopilot_Step6.jpg diff --git a/demos/Command-Execution-WebApp-NodeJS/images/18_WebsiteFix.jpg b/demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/18_WebsiteFix.jpg similarity index 100% rename from demos/Command-Execution-WebApp-NodeJS/images/18_WebsiteFix.jpg rename to demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/18_WebsiteFix.jpg diff --git a/demos/Command-Execution-WebApp-NodeJS/images/19_AskCopilot_Step7.jpg b/demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/19_AskCopilot_Step7.jpg similarity index 100% rename from demos/Command-Execution-WebApp-NodeJS/images/19_AskCopilot_Step7.jpg rename to demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/19_AskCopilot_Step7.jpg diff --git a/demos/Command-Execution-WebApp-NodeJS/images/1_AskCopilotStep1.jpg b/demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/1_AskCopilotStep1.jpg similarity index 100% rename from demos/Command-Execution-WebApp-NodeJS/images/1_AskCopilotStep1.jpg rename to demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/1_AskCopilotStep1.jpg diff --git a/demos/Command-Execution-WebApp-NodeJS/images/20_FinalResult.jpg b/demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/20_FinalResult.jpg similarity index 100% rename from demos/Command-Execution-WebApp-NodeJS/images/20_FinalResult.jpg rename to demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/20_FinalResult.jpg diff --git a/demos/Command-Execution-WebApp-NodeJS/images/2_AskCopilotStep1_2.jpg b/demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/2_AskCopilotStep1_2.jpg similarity index 100% rename from demos/Command-Execution-WebApp-NodeJS/images/2_AskCopilotStep1_2.jpg rename to demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/2_AskCopilotStep1_2.jpg diff --git a/demos/Command-Execution-WebApp-NodeJS/images/3_AskCopilotStep1_3.jpg b/demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/3_AskCopilotStep1_3.jpg similarity index 100% rename from demos/Command-Execution-WebApp-NodeJS/images/3_AskCopilotStep1_3.jpg rename to demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/3_AskCopilotStep1_3.jpg diff --git a/demos/Command-Execution-WebApp-NodeJS/images/4_InsertNewFile.jpg b/demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/4_InsertNewFile.jpg similarity index 100% rename from demos/Command-Execution-WebApp-NodeJS/images/4_InsertNewFile.jpg rename to demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/4_InsertNewFile.jpg diff --git a/demos/Command-Execution-WebApp-NodeJS/images/5_ResultFromStep1.jpg b/demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/5_ResultFromStep1.jpg similarity index 100% rename from demos/Command-Execution-WebApp-NodeJS/images/5_ResultFromStep1.jpg rename to demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/5_ResultFromStep1.jpg diff --git a/demos/Command-Execution-WebApp-NodeJS/images/6_AskCopilotStep2.jpg b/demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/6_AskCopilotStep2.jpg similarity index 100% rename from demos/Command-Execution-WebApp-NodeJS/images/6_AskCopilotStep2.jpg rename to demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/6_AskCopilotStep2.jpg diff --git a/demos/Command-Execution-WebApp-NodeJS/images/6_InsertAtCursor.jpg b/demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/6_InsertAtCursor.jpg similarity index 100% rename from demos/Command-Execution-WebApp-NodeJS/images/6_InsertAtCursor.jpg rename to demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/6_InsertAtCursor.jpg diff --git a/demos/Command-Execution-WebApp-NodeJS/images/7_Boostrap.jpg b/demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/7_Boostrap.jpg similarity index 100% rename from demos/Command-Execution-WebApp-NodeJS/images/7_Boostrap.jpg rename to demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/7_Boostrap.jpg diff --git a/demos/Command-Execution-WebApp-NodeJS/images/8_NavigationBar.jpg b/demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/8_NavigationBar.jpg similarity index 100% rename from demos/Command-Execution-WebApp-NodeJS/images/8_NavigationBar.jpg rename to demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/8_NavigationBar.jpg diff --git a/demos/Command-Execution-WebApp-NodeJS/images/9_NavBarWebsite.jpg b/demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/9_NavBarWebsite.jpg similarity index 100% rename from demos/Command-Execution-WebApp-NodeJS/images/9_NavBarWebsite.jpg rename to demos/Command-Execution-WebApp-NodeJS-CopilotChat/images/9_NavBarWebsite.jpg diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/README.md b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/README.md new file mode 100644 index 0000000..6bd2b35 --- /dev/null +++ b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/README.md @@ -0,0 +1,244 @@ +# How to build a fun NodeJS application that executes shell commands in a browser - No Copilot Chat version + +This is a simple NodeJS application that executes shell commands in a browser using **Github Copilot**. Please follow instructions below to build and run the application. This demo will not use **Github Copilot Chat**. + +> This demo is specifically made for customers who have not enabled Copilot Chat. Please [use the other demo](../Command-Execution-WebApp-NodeJS-CopilotChat) if customers have enabled Copilot Chat. + +It is possible to use other Interactive Development Editors (IDEs) that support GitHub Copilot, but it is easier to follow and better experience to use VS Code. + +## Prerequisites + +- [NodeJS](https://nodejs.org/en/download/) with NPM installed. NodeJS version should not matter as there, but NodeJS version I tested was `v20.8.0` and NPM version was `10.1.0` +- GitHub Account with a Copilot seat applied +- [VS Code](https://code.visualstudio.com/download) installed +- GitHub Copilot extension installed in VS Code + +In addition, this demo, compared to the alternative demo that uses GitHub Copilot Chat, requires quite a bit of knowledge around NodeJS, HTML, and Javascript, as it requires that you know how to get started. Also, note that refactoring capability is limited as the only way to improve the code is by rewriting comments or providing an accurate context. + +## Step-by-step guide + +Please follow the instruction below. + +### Step 1: Make sure that all prerequisites are met + +Make sure that you meet all prerequisites above. + +### Step 2: Starting with a NodeJS project + +Let's start with a very simple step to create a NodeJS project. Open **Visual Studio Code** and create a new folder if you have not. Create a file called `index.js`, and type in the following command as a Javascript comment. + +`// NodeJS project that can run shell command and display result in a web page` + +Hit **Tab** button to accept the suggestion. You can also toggle through suggestions. + +If you keep typing, you will see GitHub Copilot makes suggestions line by line as shown below. It can sometimes make a block suggestion. + +> Note that GitHub Copilot is highly generative in nature. Thus, note that the result you get will not likely be the exact same. + +![First comment entry](./images/1_TypingAndSuggesting.gif) + +This, as you can see, is one way to get suggestions from GitHub Copilot. Copilot can get the suggestions through whatever the context you are providing. More detailed and accurate your context is, GitHub Copilot can generate a better result. + +Now, what if you want to see more recommendations? What about a block suggestion instead of just a line suggestion? Because you decided not to turn off GitHub Copilot Chat, suggestions are bit limited, but we can still work with what we have. + +Delete the Copilot's suggestion, and let's go back to the end of your comment. Another cool feature of Copilot is the ability to see 10 full-page suggestions, instead of a single one-liner suggestion, and choosing which suits the code best. + +To do that, press `^ + Return` on a Mac keyboard or `Ctrl + Enter` on Windows to open a list of suggestions, as shown below. + +![Full page suggestions](./images/2_GettingSuggestions.gif) + +Sometimes, you will get all 10 suggestions. Othertimes, you will get less than that. Scroll to see what codes look right to you. And even these suggestions are not same all the time because Copilot is generative in nature. For me, I want a NodeJS logic that can run shell commands and display result in a web page. So, I will find one that opens port and listens to it, then displays the webpage in public as a static file. + +Click **Accept Solution** link right above the suggestion block that you want to apply. + +### Step 3: Understand the generated code and refactor + +Now, your suggestion might come with `index.html` if you are lucky. Mine did not. But I still want to see through the code and check if it accomplishes what it wants to be, understand what dependencies are needed, and refactor the code to make it more readable. + +![Generated code](./images/3_RefactoringInitial.gif) + +I decided to take out a huge block of comments and analyzed some dependencies here and there. For example. this one uses **ExpressJS**, so I definitely need to take care of that dependency later. + +But yours might look completely different from mine. Again, if we were to use Copilot Chat, we could get a better suggestion, so **not using** GitHub Copilot without Copilot Chat **requires more knowledge from the respective developers**. + +Make sure that your codes have some logic to use **express** library to read from **public** folder and display HTML page. + +Save the file, and we can continue. + +### Step 4: Creating static contents: public folder and index.html + +Next, we need to create `public` folder, where we will store `index.html` file. Create a folder called `public` and a file called `index.html` inside the folder. + +![Creating index.html](./images/4_CreateHTML.gif) + +Once you created it, type some html codes like `` block. You will see GitHub Copilot will make suggestions as you type. + +> TIP: If your GitHub Copilot does not generate anything inside HTML, it is likely that you need to configure settings in your GitHub Copilot plugin. Discuss with your GitHub engineer to understand what needs to be done. + +Type more contents such as setting title and adding a button where we can execute shell commands. Notice how GitHub Copilot makes suggestion as type. + +![Adding HTML content](./images/5_TypeHTML.gif) + +### Step 5: Make a test run, observe it fail, then fix by adding dependency + +Let's try to test our website! You can open a separate **console** window to run it, but I will try to use built-in Terminal inside **Visual Studio Code.** + +- For Visual Studio Code, you can go to **Terminal** menu and select **New Terminal**. That should open a Terminal in the current directory. +- Or, if you are using other Terminal or a console window, you can navigate to the directory where you have `index.js` file and `public` folder. + +From there, type the following command to run the application: `node index.js`. You should see the error complaining about missing dependencies. + +![Running the application and getting error](./images/6_ErrorRunningServer.gif) + +Uh oh! What happened? This is expected because ExpressJS is a dependency that does not come bundled with **NodeJS.** We need to install it. + +> If we did have GitHub Copilot Chat, we could ask to troubleshoot it. But unfortunately, we don't. So, we need to know how to troubleshoot by knowing what is needed. + +For NodeJS, you can use a command like `npm install express` to install it. But we want to manage through `package.json`. + +Let's manually create a `package.json` file. Once you created the file, you can start typing to create a JSON object. You will see GitHub Copilot will make suggestions as you type. + +Make sure to overwrite suggestions made for **name**, **version**, and **description** as Copilot's suggestions might not be too accurate. Most importantly, you need to add a dependency. Type `dependencies` and hit **Tab** button to accept the suggestion. Most likely, you will see a suggestion like this. + +```json +"dependencies": { + "express": "^4.17.1" +} +``` + +![Creating package.json](./images/7_CreatePackageJSON.gif) + +That version you see there might be the latest or one that you want. This is one of shortcomings of GitHub Copilot as enforcement of version is not there. But you can always change it later. + +> Tip: Always discuss with your team members about what versions and dependencies you want to use. GitHub Copilot is not a replacement for that. + +Once you are done, go back to your Terminal again. Then, type the following command to install dependencies: `npm install`. This will install all dependencies listed in `package.json` file. + +![Installing dependencies](./images/8_PackageJSONInstall.gif) + +Once you are done installing, let's check what resources got created. You can see **node_module** folder is there. If you expand that, you can see **express** folder with other folders. That means we have successfully installed dependencies. You will also see other folders and files that are created. These are created by **npm** command and packaged together with **express**/ + +You will also notice `package-lock.json` file. This file is good to have because we can ensure that we can install the same version of dependencies later. This is a good practice to have. + +![Checking installed dependencies](./images/9_CheckInstalledModules.gif) + +### Step 6: Starting server and checking our first success + +Let's go back to our Terminal and type the command to start the server: `node index.js`. You should see the message saying that the server is running. + +![Starting server](./images/10_StartServer.gif) + +Now, you can open a browser window and visit `http://localhost:3000`. You should see the page with a button. If you click the button, you will see nothing happens. I will open a **Chrome DevTool** to troubleshoot if it is really indeed the case. If you are using other browser, don't worry. You can still follow along. + +![Checking the page](./images/11_TestWebsite.gif) + +Alright. So, it looks as we need to add some logic to execute shell commands. Let's go back to our files and add some logic and design. + +### Step 7: Adding design and logic for executing shell commands + +First, we want to modify our HTML file to include the following things: +- Button that can actually execute command when I click that button +- Text field to enter shell command + +We also need to add a result page, but we will do that later. + +I will use a comment this time to let GitHub Copilot to help me. I will type the following comment: + +`` + +Again, Copilot is very generative in nature. Based on what you have, it may give what you exactly want or something completely different. Make your best judgement to accept the suggestion. + +As you can see, I tried to modify comment multiple time to get what I want. Keypoint, though, is to know what you want to do. If you don't know what you want to do, you will get a lot of suggestions that you don't want. + +![Adding HTML content](./images/12_ModifyHTMLToExecute.gif) + +Once you are done with `index.html`'s code, we need to add Javascript logic to make sure it can execute. You can type comment like the following: + +`` + +Even with detailed description, your result might be hit or miss. You can use **Synthesizing Solution** feature to browse through possible options. I found the one I want, but I still have to modify to get that exact result that I want. Again, make your best judgement. + +![Adding Javascript content](./images/13_AddJavascript.gif) + +Now, let's switch to `index.js` where it can handle the request. You need to switch back and forth between `index.html` and `index.js` to make sure you can get the right code. This is one of the shortcomings of GitHub Copilot as it does not have a way to keep track of what you are doing. So, you need to keep track of what you are doing. + +You need to create a **POST** based request handler function, so it can process the request sent from HTML form's Javascript. You can probably create a comment to generate that function, but I decided to start typing my own function and let GitHub Copilot suggestion to help me along the way. + +![Solidifying the logic for executing shell command](./images/14_ExecuteCommandFunction.gif) + +Now, to troubleshoot, it is helpful to add a log. In this way, if something fails, we will know where it fails. + +![Adding log to troubleshoot](./images/15_AddLog.gif) + +Make sure that you stop your NPM server and start again. This is necessary because we modified `index.js`. Then, start server again with `node index.js`. Now, you can go back to your browser and test it out. You should see the result like this: + +![Testing the execution of shell command](./images/16_TestExecution.gif) + +If you look through Chrome DevTool, you may see undefined or nothing is happening. Again, the result can look different if you used different snippets than I am. But if you do see `undefined` or some other error, it means that we need to fix our code. + +Because we added a log through `console.log`, we can check that to see what's shown there. As you can see, command does go to function in `index.js`, but the failure seems to happen while it is handling the logic through Javascript in `index.html` after a result gets returned from `index.js`. + +![Monitoring through shell command](./images/17_MonitorConsole.gif) + +This happens because we are not returning the correct result. Let's fix that. + +### Step 8: Add a section and respective logic to show the result + +If we go back to `index.html`, we need to make sure that the data returned from the function in `index.js` in order to pass correctly. At the same time, we want to make sure that the result can be displayed in the webpage, not just in the console. + +This is really where your understanding of Javascript and HTML helps. I will follow these two steps in order: + +1. First, introduce **Result** section in `index.html` to display the result. In this way, **Copilot can understand that we want to display the result in that specific field.** +2. Next, modify the Javascript function in `index.js` to return the result. Because we provided HTML tag through first step, it should know where to display it. + +I created a HTML comment with the following description: + +`` + +This ends up creating a `
` tags block, though yours might look little different.
+
+Then, I went back to Javascript code, removed some redundant code lines, and entered the following Javascript comment to generate a result with right context:
+
+`// Display the result from output of executing command in highlighted code to pre id with result`
+
+I had to make some changes to make sure that the end result works as I wanted it to.
+
+Your result should look like this.
+
+![Modify the code](./images/19_ModifyCodeExecution.gif)
+
+Now, if we go back and test our webpage again, you should see a result similar to this:
+
+![Testing the result](./images/20_TestRunWithExecution.gif)
+
+### Step 9: Make website prettier with Twitter Bootstrap
+
+Our result looks good, but it looks too plain. To make the website prettier, we will use **Twitter Bootstrap.** I will use the following comment to ask Copilot to help me with this.
+
+``
+
+This should import Bootstrap from CDN. This version might not be the latest or one that you want to use. So, you have to make sure that you are using a version that you want.
+
+From there, you can change buttons and text field to make sure they get applied with Bootstrap.
+
+![Import Bootstrap](./images/21_AddBootstrap.gif)
+
+Let's go back to your web browser and test it. You can see that it looks much better now, but a little more improvement can help.
+
+![Testing the result](./images/22_TestWithBootstrap.gif)
+
+Bootstrap has a concept called **Container** and **Columns**. We may want to create two columns where the larger column can display the result while the smaller column can be the place where you can enter your shell command.
+
+Go back to your `index.html` and enter the following comment.
+
+``
+
+Copilot should create a container with two columns. You can then modify the code to make sure that the result is displayed in the left column while the text field and button are displayed in the right column. You have to do some copy-and-paste as shown here.
+
+![Adding Bootstrap container](./images/23_AddContainerLayout.gif)
+
+Now, if you go back to your browser and test it, you should see the result like this:
+
+![Final result](./images/24_ResultEnd.gif)
+
+Hooray! Using GitHub Copilot, we are done with creating a simple website that can execute shell command. You can use this as a starting point to create your own website.
diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/10_StartServer.gif b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/10_StartServer.gif
new file mode 100644
index 0000000..0fbafed
Binary files /dev/null and b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/10_StartServer.gif differ
diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/11_TestWebsite.gif b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/11_TestWebsite.gif
new file mode 100644
index 0000000..a81a698
Binary files /dev/null and b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/11_TestWebsite.gif differ
diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/12_ModifyHTMLToExecute.gif b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/12_ModifyHTMLToExecute.gif
new file mode 100644
index 0000000..e2a5a3b
Binary files /dev/null and b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/12_ModifyHTMLToExecute.gif differ
diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/13_AddJavascript.gif b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/13_AddJavascript.gif
new file mode 100644
index 0000000..8afa8a6
Binary files /dev/null and b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/13_AddJavascript.gif differ
diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/14_ExecuteCommandFunction.gif b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/14_ExecuteCommandFunction.gif
new file mode 100644
index 0000000..3132d23
Binary files /dev/null and b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/14_ExecuteCommandFunction.gif differ
diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/15_AddLog.gif b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/15_AddLog.gif
new file mode 100644
index 0000000..75ab64d
Binary files /dev/null and b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/15_AddLog.gif differ
diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/16_TestExecution.gif b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/16_TestExecution.gif
new file mode 100644
index 0000000..dea9848
Binary files /dev/null and b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/16_TestExecution.gif differ
diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/17_MonitorConsole.gif b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/17_MonitorConsole.gif
new file mode 100644
index 0000000..8929b99
Binary files /dev/null and b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/17_MonitorConsole.gif differ
diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/18_ModifyToShowResult.gif b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/18_ModifyToShowResult.gif
new file mode 100644
index 0000000..f845919
Binary files /dev/null and b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/18_ModifyToShowResult.gif differ
diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/19_ModifyCodeExecution.gif b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/19_ModifyCodeExecution.gif
new file mode 100644
index 0000000..aabe8a5
Binary files /dev/null and b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/19_ModifyCodeExecution.gif differ
diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/1_TypingAndSuggesting.gif b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/1_TypingAndSuggesting.gif
new file mode 100644
index 0000000..c5d9db3
Binary files /dev/null and b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/1_TypingAndSuggesting.gif differ
diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/20_TestRunWithExecution.gif b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/20_TestRunWithExecution.gif
new file mode 100644
index 0000000..03dfa78
Binary files /dev/null and b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/20_TestRunWithExecution.gif differ
diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/21_AddBootstrap.gif b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/21_AddBootstrap.gif
new file mode 100644
index 0000000..071dd75
Binary files /dev/null and b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/21_AddBootstrap.gif differ
diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/22_TestWithBootstrap.gif b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/22_TestWithBootstrap.gif
new file mode 100644
index 0000000..bf73fc7
Binary files /dev/null and b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/22_TestWithBootstrap.gif differ
diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/23_AddContainerLayout.gif b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/23_AddContainerLayout.gif
new file mode 100644
index 0000000..86d8f49
Binary files /dev/null and b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/23_AddContainerLayout.gif differ
diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/24_ResultEnd.gif b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/24_ResultEnd.gif
new file mode 100644
index 0000000..bc5cbf9
Binary files /dev/null and b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/24_ResultEnd.gif differ
diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/2_GettingSuggestions.gif b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/2_GettingSuggestions.gif
new file mode 100644
index 0000000..56cf6bd
Binary files /dev/null and b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/2_GettingSuggestions.gif differ
diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/3_RefactoringInitial.gif b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/3_RefactoringInitial.gif
new file mode 100644
index 0000000..3f13fd8
Binary files /dev/null and b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/3_RefactoringInitial.gif differ
diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/4_CreateHTML.gif b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/4_CreateHTML.gif
new file mode 100644
index 0000000..35fa979
Binary files /dev/null and b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/4_CreateHTML.gif differ
diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/5_TypeHTML.gif b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/5_TypeHTML.gif
new file mode 100644
index 0000000..f5e54d6
Binary files /dev/null and b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/5_TypeHTML.gif differ
diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/6_ErrorRunningServer.gif b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/6_ErrorRunningServer.gif
new file mode 100644
index 0000000..1fe5389
Binary files /dev/null and b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/6_ErrorRunningServer.gif differ
diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/7_CreatePackageJSON.gif b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/7_CreatePackageJSON.gif
new file mode 100644
index 0000000..3b9a787
Binary files /dev/null and b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/7_CreatePackageJSON.gif differ
diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/8_PackageJSONInstall.gif b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/8_PackageJSONInstall.gif
new file mode 100644
index 0000000..1698a73
Binary files /dev/null and b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/8_PackageJSONInstall.gif differ
diff --git a/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/9_CheckInstalledModules.gif b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/9_CheckInstalledModules.gif
new file mode 100644
index 0000000..d6039e3
Binary files /dev/null and b/demos/Command-Execution-WebApp-NodeJS-NoCopilotChat/images/9_CheckInstalledModules.gif differ