{"id":11651,"date":"2020-09-29T18:22:35","date_gmt":"2020-09-29T16:22:35","guid":{"rendered":"https:\/\/blog.mi.hdm-stuttgart.de\/?p=11651"},"modified":"2023-06-18T18:10:45","modified_gmt":"2023-06-18T16:10:45","slug":"circle-clicker","status":"publish","type":"post","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2020\/09\/29\/circle-clicker\/","title":{"rendered":"Your first Web App in the cloud &#8211; AWS and Beanstalk"},"content":{"rendered":"\n<p>Hello fellow readers!&nbsp;<br><br>In this blog you will learn how to set up a web-game with worldwide ranking in the cloud without having to deal with complicated deployment. That means for you: More time on your application.&nbsp;<\/p>\n\n\n\n<p>The app uses Node.js with Express and MongoDB as backend. The frontend is made out of plain html, css and javascript. For deployment we used the PAAS (platform as a service) from Amazon AWS, Beanstalk.<\/p>\n\n\n\n<p>You can find the game on GitHub:<br><a href=\"https:\/\/github.com\/Pyrokahd\/CircleClicker\">https:\/\/github.com\/Pyrokahd\/CircleClicker<\/a><\/p>\n\n\n\n<h1 class=\"wp-block-heading\">App&nbsp;<\/h1>\n\n\n\n<p>CircleClicker is a skill game with the goal to click on the appearing circles as fast as possible before they disappear again.&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh6.googleusercontent.com\/94km_-ABxxtYp92raHzp_erXJbn5rGxef-4Gx_H_4lNjJopHLKK7YcZ1MXr0x36FWgiVYUtsoB2Zyrv4lieXMJoxlo6fVURi_ypj7UXk6rU1llPwjp2Z04bmdDemx45sBA8WGGYe\" alt=\"\"\/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/IPcD_Bt6guztMibxzL8jNtdmtMWOShjrhsHXEFMqPrdS6TG7sfsjOm1XuEM0bVgv_a-xqS3npiEmtrC8qAHUY_kkvwwPqtkqwJRr38Kg-SipNsAUvAqgOv1WOP9LK9Cugk6nPn2M\" alt=\"\"\/><\/figure>\n\n\n\n<p>We used javascript for the Frontend and Backend, in the form of Node.js. Javascript is well known and is used almost everywhere. This is also connected to a huge community and therefore already many answers to questions asked.&nbsp;<\/p>\n\n\n\n<p>Tip:<br>When deciding which programming language or tool you want to work with, always consider what the community is like and how many tutorials are available.\u00a0<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Backend<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Getting started<\/h3>\n\n\n\n<p>After installing node.js and express, we can use the \u201cExpress Application Generator\u201d to generate a skeleton web server. We do this by navigating to the folder, in which we want the project to be and type the following command:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh3.googleusercontent.com\/UZgPXL5KTKKM1t5xE4ftUyWwH1EdaMfYP4wklAtvBQNGnqC9i0aXf-ti30NVLQH65Ky1_tlmX9SwOPYSNptJOh63v_TzOnq6Q2epM0RI3uwicP5AbSC8PjIR1FXPDdGBR_IHDb9l\" alt=\"\"\/><\/figure>\n\n\n\n<p>With &#8211;view we define which view engine to use, for example pug or ejs. Those are used to generate response pages using templates and variables.<br>However in this project we don&#8217;t use them except for the auto generated uses, to keep it simple.<\/p>\n\n\n\n<p>To install additional modules type npm install ModuleName.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh5.googleusercontent.com\/PtJM9NEBtnvpBfF4lWQjl5yVDNikd0B8U1IZ8Nh6oEWL0vw_2ojkBMfgU4OcEfnqhe9BZEssP5D785BTs3VPk8yuQeYPpVfcwNWUJmy1G1_w5_lSzjiBImz2CKQnSb66Hh5evV17\" alt=\"\"\/><\/figure>\n\n\n\n<p>This will add the dependency to the package.json. Beanstalk will install all the modules listed in your package.json file automatically, so you don\u2019t have to worry about uploading or installing them by yourself.<\/p>\n\n\n\n<p>Now we add responses for the server to reply to client requests.<\/p>\n\n\n\n<p>The first one sends the default page to the client, once it is connected. This will be our html site containing the game.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">app.get(&#039;\/&#039;, function(req, res, next) {\n    res.sendFile(path.join(__dirname +           &quot;\/public\/main.html&quot;)); \n});<\/code><\/pre>\n\n\n\n<p>Here we tell our server to respond to GET requests on the root server path \u201c\/\u201d, which is the URL without anything behind it. The Response is our main.html located in the public folder behind the root. This means we have our main.html as the default web page.<\/p>\n\n\n\n<p>The next GET response will respond to the url \u201c\/getScore\u201d by sending the top 10 highscores to the client.&nbsp;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">app.get(&#039;\/getScore&#039;, function(req, res, next) {\n<\/code><\/pre>\n\n\n\n<p>In there we make a query to our MongoDB and then construct a JSON string out of it to send it to the client. The query is shown later when we talk about MongoDB.<\/p>\n\n\n\n<p>The last response answers a POST request from the client and is used to create new entries for the database, if the player sends a score.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">app.post(&#039;\/sendScore&#039;, function(req, res, next) {<\/code><\/pre>\n\n\n\n<p>In this function we receive a name and a score from the client in the form of a JSON object. Those variables are then used to create a database entry.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Frontend<\/h2>\n\n\n\n<p>The Frontend consists of the HTML page, the CSS stylesheet and one or more javascript files for the logic and functionality.<\/p>\n\n\n\n<p>The HTML and javascript files are stored in their respective folder under the \u201cpublic\u201d folder in the server.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">HTML<\/h3>\n\n\n\n<p>For the HTML document the important parts are a form to enter the archived score plus a name and buttons to start the game and send the score to the server. Other important parts, like the HTML canvas are generated once the game is started.<\/p>\n\n\n\n<p>How exactly the html looks is not important. It just needs all the relevant elements with a respective ID, to be called upon in the javascript file, in which all the event handling and game logic happens.<\/p>\n\n\n\n<p>The following should be avoided because it violates the content security policy (CSP):<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>inline css<\/li><li>inline javascript<\/li><li>inline eventhandler (i.e. onClick=\u201dfunction\u201d for a button)<\/li><li>importing scripts which are not hosted on your own server (i.e. download jquery and put it on your server)<\/li><\/ul>\n\n\n\n<p>It is also important to import the gameLogic script at the end of the html body. That way the html will be loaded first and we can access all elements in the javascript file without trouble.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Javascript<\/h3>\n\n\n\n<p>First we give the buttons on the site some functions to invoke, by adding click events to them. A HTML canvas is created inside an object, which holds the gamelogic, once the site has loaded.&nbsp;<\/p>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow\">\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">document.getElementById(&quot;startBtn&quot;).addEventListener(&quot;click&quot;, startGame);\ndocument.getElementById(&quot;showPopUpBtn&quot;).addEventListener(&quot;click&quot;, showPopUp);\ndocument.getElementById(&quot;submitBtn&quot;).addEventListener(&quot;click&quot;, sendScore);\ndocument.getElementById(&quot;resetBtn&quot;).addEventListener(&quot;click&quot;, hidePopUp);<\/code><\/pre>\n<\/div><\/div>\n\n\n\n<p>The first three of those buttons provide the necessary functionality to play the game and interact with the server.&nbsp;<\/p>\n\n\n\n<p>The first one \u201cstartBtn\u201d does exactly what the name suggests. It starts the game by calling the startGame function. This sets some variables like lifes and points and then starts an intervalTimer to act as our Game Loop. After a certain time, which decreases the longer the game runs, a circle-object is spawned. This has the logic to increase points or decrease lifes and despawn after a while.<br>The canvas has an EventListener to check for clicks inside it. To check if a circle is clicked, the mouse-position and the circle-position are compared (the circle position needs to be increased by the offset of the canvas position and decreased by the scroll-y height).<\/p>\n\n\n\n<p>The second button has the functionality to show the popup-form, which is used to enter a name and send it, together with the archived, score to the server. This function is also called automatically once you lose the game.<\/p>\n\n\n\n<p>The submit Button calls the sendScore function, which uses jquery and ajax to make a POST request to the server and send the score and username as a JSON object named data. Here we also use the \u201c\/sendScore\u201d url which we set for a post response, at the server.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">const serverURL = window.location.origin;\n\n$.ajax({\n            type:&quot;POST&quot;,\n            async: true,\n            url: serverURL+&quot;\/sendScore&quot;,\n            data:data,\n            success: function(dataResponse){\n                console.log(&quot;success beim senden: &quot;);\n                console.log(dataResponse);\n                setTimeout(requestLeaderboard,1000);\n            },\n            statusCode: {\n                404: function(){\n                    alert(&quot;not found&quot;);\n                } \/\/, 300:()=&gt;{}, ...\n            }\n});<\/code><\/pre>\n\n\n\n<p>The last relevant function is to request the leaderboard. This is called upon loading the page and once we send our new score to the server, to update the leaderboard. This also uses jquery and ajax to make it easier to write the GET request.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">$.ajax\n({\n    type:&quot;GET&quot;,\n    async: true,\n    url: serverURL+&quot;\/getScore&quot;,\n    success: function(dataResponse){\n    highScores = JSON.parse(dataResponse);\n\n    \/\/Build html String from JSON response\n    var leaderBoardString = &quot;&lt;h2&gt;Leaderboard&lt;\/h2&gt;&quot;;\n    var tableString = &#039;&lt;table id=&quot;table&quot;&gt;&lt;tr&gt;\n                       &lt;th&gt;Name&lt;\/th&gt;  &lt;th&gt;Score&lt;\/th&gt;&#039;;\n    for (var i = 0; i &lt; highScores.user.length;i++){\n        tableString += &quot;&lt;tr&gt;&lt;td&gt;&quot;+highScores.user&#091;i].name\n                    +&quot;&lt;\/td&gt;&lt;td&gt;&quot;\n                    +highScores.user&#091;i].score\n                    +&quot;&lt;\/td&gt;&lt;\/tr&gt;&quot;;\n    }\n    tableString += &#039;&lt;\/tr&gt;&lt;\/table&gt;&#039;;\n    \/\/Update leaderBoard with created table\n    document.getElementById(&quot;leaderboardArea&quot;).innerHTML\n                    = leaderBoardString+tableString;\n     },\n     statusCode: {\n         404: function(){\n             alert(&quot;not found&quot;);\n         } \/\/, 300:()=&gt;{}, ...\n    }\n});<\/code><\/pre>\n\n\n\n<p>The \u201c\/getScore\u201d url from the GET response of the server used to get the top 10 scores as a JSON object. This JSON object is then used to create a table in the form of a HTML string, which is set as the innerHTML of a div-box.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">MongoDB<\/h2>\n\n\n\n<p>In our application we use MongoDB together with the mongoose module. The mongoose module simplifies certain MongoDB functions.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Host<\/h3>\n\n\n\n<p>As the host for the database we used MongoDB Atlas, which lets you create a free MongoDB in the cloud of a provider of your choice. We chose AWS, since we also use their Beanstalk service. The free version of this database has some limits, but for a small project like this, it is more than enough.<\/p>\n\n\n\n<p>After a database is created, you can create a user, assign rights and copy a connection-string from MongoDB Atlas.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Connection<\/h3>\n\n\n\n<p>We are using this string and mongoose to connect to the DB in a few lines of code.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">mongoose.connect(mongoDBConnectionString, { useNewUrlParser: true },);\n\/\/Get the default connection\nvar db = mongoose.connection;\n\/\/Bind connection to error event (to get notification of connection errors)\ndb.on(&#039;error&#039;, console.error.bind(console, &#039;MongoDB connection error:&#039;));<\/code><\/pre>\n\n\n\n<p>After the connection is established we can create a mongoose model, which is like a blueprint for the entries in one table. This model is created from a mongoose schema in which we define the structure.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">var UserModelSchema = new mongoose.Schema({\nname: String,\nscore: Number\n});\nvar UserModel = mongoose.model(&#039;UserModel&#039;, UserModelSchema );<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Create Entry<\/h3>\n\n\n\n<p>Now we are ready to add new entries to the database. This is easily done by creating an instance of the mongoose model and filling in the appropriate fields. After calling the save function, a new entry is added.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">var testInstance = new UserModel({name: _name, score: _score});\n    testInstance.save(function (err, testInstance) {\n        if (err) return console.error(err);\n        console.log(&quot;new Entry saved&quot;);\n    });<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Query<\/h3>\n\n\n\n<p>To make a query is just as easy. First we define a query object and set the parameter according to our needs.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">\/\/ find all athletes that play tennis\n    var query = UserModel.find();\n    \/\/ selecting the &#039;name&#039; and &#039;score&#039; fields but no _id field\n    query.select(&#039;name score -_id&#039;); \n    \/\/ sort by score\n    query.sort({ score: -1 });\n    \/\/limit our results to 10 items\n    query.limit(10);\n    \/\/to return JS objects not Mongoose Documents\n    query.lean();<\/code><\/pre>\n\n\n\n<p>We can then execute that query and receive a result depending on the settings<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">query.exec(function (err, queryResult) {\n      if (err) return handleError(err);\n\n        \/\/use queryResult (JS-Object)\n        \/\/to create JSON string\n\n        \/\/and send it to client\n        res.send(resJSON); \n    });<\/code><\/pre>\n\n\n\n<h1 class=\"wp-block-heading\">Into the cloud!<\/h1>\n\n\n\n<p>But how do we get into the cloud? The first thing we do is decide on a cloud provider. We very quickly chose AWS because we were particularly impressed by the service they offered. It&#8217;s about AWS Beanstalk. Amazon promises to take over a lot of backend provisioning, like load-balancing,scaling, e2-instances and security groups.<\/p>\n\n\n\n<p>Which means more time for actually programming.&nbsp;<\/p>\n\n\n\n<p>Does that work? To a large extent yes!&nbsp;<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/lh4.googleusercontent.com\/HxMZru7GvW49NDvqeSLmwwD-BQALw5XVrGV1_ZtHagP70ZcVdMhNwJAjh_W0tFu-juAt7vU6lQmELDWnsXBFoXfFajzRIRoWoqjPgctUAnO0yA383hAlA0e-ttegisT0mvuCD_ht\" alt=\"\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">How does it work?<\/h2>\n\n\n\n<p>Very simple. You create an Amazon AWS account, go into the development console and create a new AWS Beanstalk environment. Here you define the domain name and in which programming language your app is written. Then start the environment. Afterwards you upload the app which is put together to an archive and check on the domain if the app works. Updates are done the same way. Merge the new code into an archive, upload and select.&nbsp;<\/p>\n\n\n\n<p>You now have a website with your own game. Load Balancer is included, highscore is included and basic security settings are set.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Check Logs on CloudWatch<\/h2>\n\n\n\n<p>In your Beanstalk environment configuration under monitoring, you can enable your logs to be streamed to CloudWatch. This comes with some extra cost, but allows you to have all your logs online and centralized in one location.&nbsp;<\/p>\n\n\n\n<p>CloudWatch also has many more functionalities like alarms when your application gets downscaled because there is less traffic, or monitoring of the performance of your ressources.<\/p>\n\n\n\n<p>However we are interested in our logs, which you find under your protocol groups in CloudWatch. There is one log with the ending stdout.log (by default). This is where all of the console.log or console.error messages from our server are located.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Security Settings<\/h1>\n\n\n\n<p>If you want to make your application even more secure, you can put a little more time into it. We have decided to set up HTTPS and use the SCP protocol.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">HTTPS<\/h2>\n\n\n\n<p>To provide HTTPS, proceed as follows:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Create a certificate for domain names in AWS Certificate Manager (ACM)<\/li><li>LoadBalancer https Configuration<\/li><li>Add listener<\/li><li>Port 443<\/li><li>Protocol HTTPS<\/li><li>Upload Certificate<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Helmet Security<\/h2>\n\n\n\n<p>Helmet is a library that checks some basic security issues regarding the header. One important aspect of this is the Content Security Policy (CSP) header. It forces you to write your html files in a secure manner to avoid cross site scripting attacks.<\/p>\n\n\n\n<p>Problem: CSP-header enforces security policies<\/p>\n\n\n\n<p>Despite not being completely CSP conform it worked on the local server but<\/p>\n\n\n\n<p>to make it work in the cloud we had to follow the CSP guidelines. So we had to remove all inline Javascript and CSS to eradicate all errors regarding CSP.<\/p>\n\n\n\n<p>Problem: HTTPS Forwarding<\/p>\n\n\n\n<p>By activating Helmet security the resources of the website become unreachable. Through the AWS logs we found the following error message, but could not find out exactly where the problem was:<\/p>\n\n\n\n<p><em>2020\/09\/05 17:53:16 [error] 19019#0: *7 connect() failed (111: Connection refused) while connecting to upstream, client:<a href=\"http:\/\/172.31.37.17\/\"> <\/a>172.31.37.17, server: , request: &#8220;GET \/ HTTP\/1.1&#8221;, upstream: &#8220;http:\/\/127.0.0.1:8080\/&#8221;, host: &#8220;172.31.41.163&#8221;<\/em><\/p>\n\n\n\n<p>We have also looked at load balancers and security groups, but all the settings are correct here. In further research with the Developer Console in the browser, we found out that https requests are required.&nbsp;<\/p>\n\n\n\n<p><em>GET https:\/\/&#8230;elasticbeanstalk.com\/javascripts\/GameLogic.js net::ERR_CONNECTION_TIMED_OUT<\/em><\/p>\n\n\n\n<p>Since we do not have the required permissions, we could not set up https. So we had to turn off the CSP for our game. The already implemented security features such as the removal of css inline tags remain.&nbsp;<\/p>\n\n\n\n<p>In previous tests, while disabling helmet we didn\u2019t generate a new package-lock.json file, which holds a tree of generated packages. Because this was not updated we didn\u2019t remove helmet completely and got wrong results for the test, which led us wrongly to believe helmet was not the problem.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Conclusion<\/h1>\n\n\n\n<p>Although this was not the initial goal, we learned a lot about networking during this project. Especially topics like setting up a server as well as the communication between database, client and server. Despite the roadblocks, we were very positively surprised by the AWS Cloud and Beanstalk. We can recommend Beanstalk if you want to get simple applications and websites in the cloud ASAP. As soon as we implemented security related code we had to make an additional effort, which went beyond beanstalk alone, to get it running.&nbsp;&nbsp;<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hello fellow readers!&nbsp; In this blog you will learn how to set up a web-game with worldwide ranking in the cloud without having to deal with complicated deployment. That means for you: More time on your application.&nbsp; The app uses Node.js with Express and MongoDB as backend. The frontend is made out of plain html, [&hellip;]<\/p>\n","protected":false},"author":980,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[120,262,26],"tags":[],"ppma_author":[824],"class_list":["post-11651","post","type-post","status-publish","format-standard","hentry","category-cloud-technologies","category-rich-media-systems","category-secure-systems"],"aioseo_notices":[],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":22151,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2022\/02\/22\/designing-and-implementing-a-scalable-web-application\/","url_meta":{"origin":11651,"position":0},"title":"Designing the framework for a scalable CI\/CD supported web application","author":"Danial Eshete","date":"22. February 2022","format":false,"excerpt":"Documentation of our approaches to the project, our experiences and finally the lessons we learned. The development team approaches the project with little knowledge of cloud services and infrastructure. Furthermore, no one has significant experience with containers and\/or containerized applications. However, the team is well experienced in web development and\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2022\/02\/Design_Desktop_Logged_In-3-150x150.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2022\/02\/Design_Desktop_Logged_In-3-150x150.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2022\/02\/Design_Desktop_Logged_In-3-150x150.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2022\/02\/Design_Desktop_Logged_In-3-150x150.jpg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2022\/02\/Design_Desktop_Logged_In-3-150x150.jpg?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2022\/02\/Design_Desktop_Logged_In-3-150x150.jpg?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":7396,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2019\/08\/31\/multiplayer-typescript-application-deploy-on-aws-services\/","url_meta":{"origin":11651,"position":1},"title":"Multiplayer TypeScript Application run on AWS Services","author":"bj009","date":"31. August 2019","format":false,"excerpt":"Daniel Knizia - dk100@hdm-stuttgart.deBenjamin Janzen - bj009@hdm-stuttgart.de The project CatchMe is a location-based multiplayer game for mobile devices. The idea stems from the classic board game Scotland Yard, basically a modern version of hide & seek. You play in a group with up to 5 players outside, where on of\u2026","rel":"","context":"In &quot;Cloud Technologies&quot;","block_context":{"text":"Cloud Technologies","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/scalable-systems\/cloud-technologies\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/08\/variables.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/08\/variables.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/08\/variables.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2019\/08\/variables.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":21653,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2021\/09\/17\/studidash-a-serverless-web-application\/","url_meta":{"origin":11651,"position":2},"title":"&#8220;Studidash&#8221; | A serverless web application","author":"dk119","date":"17. September 2021","format":false,"excerpt":"by Oliver Klein (ok061), Daniel Koch (dk119), Luis B\u00fchler (lb159), Micha Huhn (mh334) Abstract You are probably familiar with the HdM SB-Funktionen. After nearly four semesters we were tired of the boring design and decided to give it a more modern look with a bit more functionality then it currently\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/09\/grafik-1.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/09\/grafik-1.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/09\/grafik-1.png?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":25865,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2023\/09\/15\/guess-what-we-built-a-web-game-with-firebase\/","url_meta":{"origin":11651,"position":3},"title":"Guess What? We Built a Web Game with Firebase","author":"mc071","date":"15. September 2023","format":false,"excerpt":"What is more or less? \"More or Less\" is a guessing game where you guess which item has a higher value for a specific attribute. For example, in the \"Commit Clash: Which GitHub repo has more commits?\" mode, you see one GitHub repository's commit count and another repository. You have\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/1_guessing_game.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/1_guessing_game.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/1_guessing_game.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/1_guessing_game.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2023\/09\/1_guessing_game.png?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":27914,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2025\/08\/27\/how-to-develop-an-aws-hosted-discord-bot\/","url_meta":{"origin":11651,"position":4},"title":"How to develop an AWS hosted Discord Bot","author":"Lara Blersch","date":"27. August 2025","format":false,"excerpt":"Introduction This semester, our team set itself the goal of developing a game for a Discord bot. Taking inspiration from Hitster and Nobody's Perfect, we created Headliner.Over three rounds, players receive meta information about a newspaper article, such as what happened, who was involved, where it happened, and when. Based\u2026","rel":"","context":"In &quot;Cloud Technologies&quot;","block_context":{"text":"Cloud Technologies","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/scalable-systems\/cloud-technologies\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/Architecture.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/Architecture.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/Architecture.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/Architecture.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/Architecture.png?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/08\/Architecture.png?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":12032,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2020\/09\/30\/admin-panel-web-app-in-der-aws-cloud\/","url_meta":{"origin":11651,"position":5},"title":"Admin Panel (Web App) in der AWS Cloud","author":"ss447","date":"30. September 2020","format":false,"excerpt":"1. Einleitung Im Rahmen der Vorlesung \u201eSoftware Development for Cloud Computing\u201c haben wir uns als Gruppe dazu entschieden aufbauend auf teilweise bereits vorhandener Codebasis an einem Startup-Projekt weiterzuarbeiten. Der Hauptfokus lag bei uns auf dem Ausbau von DevOps-Aspekten und auf dem eines stabilen und sicheren Systems, welches auch in der\u2026","rel":"","context":"In &quot;Cloud Technologies&quot;","block_context":{"text":"Cloud Technologies","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/scalable-systems\/cloud-technologies\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/img.youtube.com\/vi\/qw9ZkWnvR4M\/0.jpg?resize=350%2C200","width":350,"height":200},"classes":[]}],"jetpack_sharing_enabled":true,"authors":[{"term_id":824,"user_id":980,"is_guest":0,"slug":"mf144","display_name":"mf144","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/be7c3ae7c4da87bbe1cc52b7602e7b91a38acaff3d0793ceaf23024f57da2570?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_links":{"self":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/11651","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/users\/980"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/comments?post=11651"}],"version-history":[{"count":11,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/11651\/revisions"}],"predecessor-version":[{"id":11669,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/11651\/revisions\/11669"}],"wp:attachment":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/media?parent=11651"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/categories?post=11651"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/tags?post=11651"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/ppma_author?post=11651"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}